Flutter Engine
The Flutter Engine
flutter_windows_view.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/shell/platform/windows/flutter_windows_view.h"
6
7#include <chrono>
8
9#include "flutter/common/constants.h"
10#include "flutter/fml/make_copyable.h"
11#include "flutter/fml/platform/win/wstring_conversion.h"
12#include "flutter/fml/synchronization/waitable_event.h"
13#include "flutter/shell/platform/common/accessibility_bridge.h"
14#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
15#include "flutter/shell/platform/windows/text_input_plugin.h"
16#include "flutter/third_party/accessibility/ax/platform/ax_platform_node_win.h"
17
18namespace flutter {
19
20namespace {
21// The maximum duration to block the platform thread for while waiting
22// for a window resize operation to complete.
23constexpr std::chrono::milliseconds kWindowResizeTimeout{100};
24
25/// Returns true if the surface will be updated as part of the resize process.
26///
27/// This is called on window resize to determine if the platform thread needs
28/// to be blocked until the frame with the right size has been rendered. It
29/// should be kept in-sync with how the engine deals with a new surface request
30/// as seen in `CreateOrUpdateSurface` in `GPUSurfaceGL`.
31bool SurfaceWillUpdate(size_t cur_width,
32 size_t cur_height,
33 size_t target_width,
34 size_t target_height) {
35 // TODO (https://github.com/flutter/flutter/issues/65061) : Avoid special
36 // handling for zero dimensions.
37 bool non_zero_target_dims = target_height > 0 && target_width > 0;
38 bool not_same_size =
39 (cur_height != target_height) || (cur_width != target_width);
40 return non_zero_target_dims && not_same_size;
41}
42
43/// Update the surface's swap interval to block until the v-blank iff
44/// the system compositor is disabled.
45void UpdateVsync(const FlutterWindowsEngine& engine,
46 egl::WindowSurface* surface,
47 bool needs_vsync) {
48 egl::Manager* egl_manager = engine.egl_manager();
49 if (!egl_manager) {
50 return;
51 }
52
53 auto update_vsync = [egl_manager, surface, needs_vsync]() {
54 if (!surface || !surface->IsValid()) {
55 return;
56 }
57
58 if (!surface->MakeCurrent()) {
59 FML_LOG(ERROR) << "Unable to make the render surface current to update "
60 "the swap interval";
61 return;
62 }
63
64 if (!surface->SetVSyncEnabled(needs_vsync)) {
65 FML_LOG(ERROR) << "Unable to update the render surface's swap interval";
66 }
67
68 if (!egl_manager->render_context()->ClearCurrent()) {
69 FML_LOG(ERROR) << "Unable to clear current surface after updating "
70 "the swap interval";
71 }
72 };
73
74 // Updating the vsync makes the EGL context and render surface current.
75 // If the engine is running, the render surface should only be made current on
76 // the raster thread. If the engine is initializing, the raster thread doesn't
77 // exist yet and the render surface can be made current on the platform
78 // thread.
79 if (engine.running()) {
80 engine.PostRasterThreadTask(update_vsync);
81 } else {
82 update_vsync();
83 }
84}
85
86/// Destroys a rendering surface that backs a Flutter view.
87void DestroyWindowSurface(const FlutterWindowsEngine& engine,
88 std::unique_ptr<egl::WindowSurface> surface) {
89 // EGL surfaces are used on the raster thread if the engine is running.
90 // There may be pending raster tasks that use this surface. Destroy the
91 // surface on the raster thread to avoid concurrent uses.
92 if (engine.running()) {
93 engine.PostRasterThreadTask(fml::MakeCopyable(
94 [surface = std::move(surface)] { surface->Destroy(); }));
95 } else {
96 // There's no raster thread if engine isn't running. The surface can be
97 // destroyed on the platform thread.
98 surface->Destroy();
99 }
100}
101
102} // namespace
103
105 FlutterViewId view_id,
107 std::unique_ptr<WindowBindingHandler> window_binding,
108 std::shared_ptr<WindowsProcTable> windows_proc_table)
109 : view_id_(view_id),
110 engine_(engine),
111 windows_proc_table_(std::move(windows_proc_table)) {
112 if (windows_proc_table_ == nullptr) {
113 windows_proc_table_ = std::make_shared<WindowsProcTable>();
114 }
115
116 // Take the binding handler, and give it a pointer back to self.
117 binding_handler_ = std::move(window_binding);
118 binding_handler_->SetView(this);
119}
120
122 // The view owns the child window.
123 // Notify the engine the view's child window will no longer be visible.
125
126 if (surface_) {
127 DestroyWindowSurface(*engine_, std::move(surface_));
128 }
129}
130
132 // Called on the raster thread.
133 std::unique_lock<std::mutex> lock(resize_mutex_);
134
135 if (surface_ == nullptr || !surface_->IsValid()) {
136 return false;
137 }
138
139 if (resize_status_ != ResizeState::kResizeStarted) {
140 return true;
141 }
142
143 if (!ResizeRenderSurface(resize_target_height_, resize_target_width_)) {
144 return false;
145 }
146
147 // Platform thread is blocked for the entire duration until the
148 // resize_status_ is set to kDone by |OnFramePresented|.
149 resize_status_ = ResizeState::kFrameGenerated;
150 return true;
151}
152
154 // Called on the raster thread.
155 std::unique_lock<std::mutex> lock(resize_mutex_);
156
157 if (surface_ == nullptr || !surface_->IsValid()) {
158 return false;
159 }
160
161 if (resize_status_ != ResizeState::kResizeStarted) {
162 return true;
163 }
164
165 if (resize_target_width_ != width || resize_target_height_ != height) {
166 return false;
167 }
168
169 if (!ResizeRenderSurface(resize_target_width_, resize_target_height_)) {
170 return false;
171 }
172
173 // Platform thread is blocked for the entire duration until the
174 // resize_status_ is set to kDone by |OnFramePresented|.
175 resize_status_ = ResizeState::kFrameGenerated;
176 return true;
177}
178
179void FlutterWindowsView::UpdateFlutterCursor(const std::string& cursor_name) {
180 binding_handler_->UpdateFlutterCursor(cursor_name);
181}
182
184 binding_handler_->SetFlutterCursor(cursor);
185}
186
188 if (resize_status_ == ResizeState::kDone) {
189 // Request new frame.
190 engine_->ScheduleFrame();
191 }
192}
193
195 // Called on the platform thread.
196 std::unique_lock<std::mutex> lock(resize_mutex_);
197
198 if (!engine_->egl_manager()) {
199 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
200 return true;
201 }
202
203 if (!surface_ || !surface_->IsValid()) {
204 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
205 return true;
206 }
207
208 // We're using OpenGL rendering. Resizing the surface must happen on the
209 // raster thread.
210 bool surface_will_update =
211 SurfaceWillUpdate(surface_->width(), surface_->height(), width, height);
212 if (!surface_will_update) {
213 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
214 return true;
215 }
216
217 resize_status_ = ResizeState::kResizeStarted;
218 resize_target_width_ = width;
219 resize_target_height_ = height;
220
221 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
222
223 // Block the platform thread until a frame is presented with the target
224 // size. See |OnFrameGenerated|, |OnEmptyFrameGenerated|, and
225 // |OnFramePresented|.
226 return resize_cv_.wait_for(lock, kWindowResizeTimeout,
227 [&resize_status = resize_status_] {
228 return resize_status == ResizeState::kDone;
229 });
230}
231
233 ForceRedraw();
234}
235
237 double y,
238 FlutterPointerDeviceKind device_kind,
239 int32_t device_id,
240 int modifiers_state) {
241 engine_->keyboard_key_handler()->SyncModifiersIfNeeded(modifiers_state);
242 SendPointerMove(x, y, GetOrCreatePointerState(device_kind, device_id));
243}
244
246 double x,
247 double y,
248 FlutterPointerDeviceKind device_kind,
249 int32_t device_id,
250 FlutterPointerMouseButtons flutter_button) {
251 if (flutter_button != 0) {
252 auto state = GetOrCreatePointerState(device_kind, device_id);
253 state->buttons |= flutter_button;
254 SendPointerDown(x, y, state);
255 }
256}
257
259 double x,
260 double y,
261 FlutterPointerDeviceKind device_kind,
262 int32_t device_id,
263 FlutterPointerMouseButtons flutter_button) {
264 if (flutter_button != 0) {
265 auto state = GetOrCreatePointerState(device_kind, device_id);
266 state->buttons &= ~flutter_button;
267 SendPointerUp(x, y, state);
268 }
269}
270
272 double y,
273 FlutterPointerDeviceKind device_kind,
274 int32_t device_id) {
275 SendPointerLeave(x, y, GetOrCreatePointerState(device_kind, device_id));
276}
277
279 PointerLocation point = binding_handler_->GetPrimaryPointerLocation();
280 SendPointerPanZoomStart(device_id, point.x, point.y);
281}
282
284 double pan_x,
285 double pan_y,
286 double scale,
287 double rotation) {
288 SendPointerPanZoomUpdate(device_id, pan_x, pan_y, scale, rotation);
289}
290
292 SendPointerPanZoomEnd(device_id);
293}
294
295void FlutterWindowsView::OnText(const std::u16string& text) {
296 SendText(text);
297}
298
300 int scancode,
301 int action,
302 char32_t character,
303 bool extended,
304 bool was_down,
307}
308
310 SendComposeBegin();
311}
312
314 SendComposeCommit();
315}
316
318 SendComposeEnd();
319}
320
321void FlutterWindowsView::OnComposeChange(const std::u16string& text,
322 int cursor_pos) {
323 SendComposeChange(text, cursor_pos);
324}
325
327 double y,
328 double delta_x,
329 double delta_y,
330 int scroll_offset_multiplier,
331 FlutterPointerDeviceKind device_kind,
332 int32_t device_id) {
333 SendScroll(x, y, delta_x, delta_y, scroll_offset_multiplier, device_kind,
334 device_id);
335}
336
338 PointerLocation point = binding_handler_->GetPrimaryPointerLocation();
339 SendScrollInertiaCancel(device_id, point.x, point.y);
340}
341
343 engine_->UpdateSemanticsEnabled(enabled);
344}
345
347 if (!accessibility_bridge_) {
348 return nullptr;
349 }
350
351 return accessibility_bridge_->GetChildOfAXFragmentRoot();
352}
353
355 binding_handler_->OnCursorRectUpdated(rect);
356}
357
359 binding_handler_->OnResetImeComposing();
360}
361
362// Sends new size information to FlutterEngine.
363void FlutterWindowsView::SendWindowMetrics(size_t width,
364 size_t height,
365 double pixel_ratio) const {
366 FlutterWindowMetricsEvent event = {};
367 event.struct_size = sizeof(event);
368 event.width = width;
369 event.height = height;
370 event.pixel_ratio = pixel_ratio;
371 event.view_id = view_id_;
373}
374
376 PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
377 double pixel_ratio = binding_handler_->GetDpiScale();
378
379 FlutterWindowMetricsEvent event = {};
380 event.struct_size = sizeof(event);
381 event.width = bounds.width;
382 event.height = bounds.height;
383 event.pixel_ratio = pixel_ratio;
384 event.view_id = view_id_;
385
386 return event;
387}
388
390 // Non-implicit views' initial window metrics are sent when the view is added
391 // to the engine.
392 if (!IsImplicitView()) {
393 return;
394 }
395
397}
398
399FlutterWindowsView::PointerState* FlutterWindowsView::GetOrCreatePointerState(
400 FlutterPointerDeviceKind device_kind,
401 int32_t device_id) {
402 // Create a virtual pointer ID that is unique across all device types
403 // to prevent pointers from clashing in the engine's converter
404 // (lib/ui/window/pointer_data_packet_converter.cc)
405 int32_t pointer_id = (static_cast<int32_t>(device_kind) << 28) | device_id;
406
407 auto [it, added] = pointer_states_.try_emplace(pointer_id, nullptr);
408 if (added) {
409 auto state = std::make_unique<PointerState>();
410 state->device_kind = device_kind;
411 state->pointer_id = pointer_id;
412 it->second = std::move(state);
413 }
414
415 return it->second.get();
416}
417
418// Set's |event_data|'s phase to either kMove or kHover depending on the current
419// primary mouse button state.
420void FlutterWindowsView::SetEventPhaseFromCursorButtonState(
421 FlutterPointerEvent* event_data,
422 const PointerState* state) const {
423 // For details about this logic, see FlutterPointerPhase in the embedder.h
424 // file.
425 if (state->buttons == 0) {
426 event_data->phase = state->flutter_state_is_down
429 } else {
430 event_data->phase = state->flutter_state_is_down
433 }
434}
435
436void FlutterWindowsView::SendPointerMove(double x,
437 double y,
438 PointerState* state) {
439 FlutterPointerEvent event = {};
440 event.x = x;
441 event.y = y;
442
443 SetEventPhaseFromCursorButtonState(&event, state);
444 SendPointerEventWithData(event, state);
445}
446
447void FlutterWindowsView::SendPointerDown(double x,
448 double y,
449 PointerState* state) {
450 FlutterPointerEvent event = {};
451 event.x = x;
452 event.y = y;
453
454 SetEventPhaseFromCursorButtonState(&event, state);
455 SendPointerEventWithData(event, state);
456
457 state->flutter_state_is_down = true;
458}
459
460void FlutterWindowsView::SendPointerUp(double x,
461 double y,
462 PointerState* state) {
463 FlutterPointerEvent event = {};
464 event.x = x;
465 event.y = y;
466
467 SetEventPhaseFromCursorButtonState(&event, state);
468 SendPointerEventWithData(event, state);
469 if (event.phase == FlutterPointerPhase::kUp) {
470 state->flutter_state_is_down = false;
471 }
472}
473
474void FlutterWindowsView::SendPointerLeave(double x,
475 double y,
476 PointerState* state) {
477 FlutterPointerEvent event = {};
478 event.x = x;
479 event.y = y;
480 event.phase = FlutterPointerPhase::kRemove;
481 SendPointerEventWithData(event, state);
482}
483
484void FlutterWindowsView::SendPointerPanZoomStart(int32_t device_id,
485 double x,
486 double y) {
487 auto state =
488 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
489 state->pan_zoom_start_x = x;
490 state->pan_zoom_start_y = y;
491 FlutterPointerEvent event = {};
492 event.x = x;
493 event.y = y;
495 SendPointerEventWithData(event, state);
496}
497
498void FlutterWindowsView::SendPointerPanZoomUpdate(int32_t device_id,
499 double pan_x,
500 double pan_y,
501 double scale,
502 double rotation) {
503 auto state =
504 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
505 FlutterPointerEvent event = {};
506 event.x = state->pan_zoom_start_x;
507 event.y = state->pan_zoom_start_y;
508 event.pan_x = pan_x;
509 event.pan_y = pan_y;
510 event.scale = scale;
511 event.rotation = rotation;
513 SendPointerEventWithData(event, state);
514}
515
516void FlutterWindowsView::SendPointerPanZoomEnd(int32_t device_id) {
517 auto state =
518 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
519 FlutterPointerEvent event = {};
520 event.x = state->pan_zoom_start_x;
521 event.y = state->pan_zoom_start_y;
523 SendPointerEventWithData(event, state);
524}
525
526void FlutterWindowsView::SendText(const std::u16string& text) {
527 engine_->text_input_plugin()->TextHook(text);
528}
529
530void FlutterWindowsView::SendKey(int key,
531 int scancode,
532 int action,
533 char32_t character,
534 bool extended,
535 bool was_down,
536 KeyEventCallback callback) {
539 [=, callback = std::move(callback)](bool handled) {
540 if (!handled) {
541 engine_->text_input_plugin()->KeyboardHook(
543 }
544 callback(handled);
545 });
546}
547
548void FlutterWindowsView::SendComposeBegin() {
550}
551
552void FlutterWindowsView::SendComposeCommit() {
554}
555
556void FlutterWindowsView::SendComposeEnd() {
557 engine_->text_input_plugin()->ComposeEndHook();
558}
559
560void FlutterWindowsView::SendComposeChange(const std::u16string& text,
561 int cursor_pos) {
562 engine_->text_input_plugin()->ComposeChangeHook(text, cursor_pos);
563}
564
565void FlutterWindowsView::SendScroll(double x,
566 double y,
567 double delta_x,
568 double delta_y,
569 int scroll_offset_multiplier,
570 FlutterPointerDeviceKind device_kind,
571 int32_t device_id) {
572 auto state = GetOrCreatePointerState(device_kind, device_id);
573
574 FlutterPointerEvent event = {};
575 event.x = x;
576 event.y = y;
578 event.scroll_delta_x = delta_x * scroll_offset_multiplier;
579 event.scroll_delta_y = delta_y * scroll_offset_multiplier;
580 SetEventPhaseFromCursorButtonState(&event, state);
581 SendPointerEventWithData(event, state);
582}
583
584void FlutterWindowsView::SendScrollInertiaCancel(int32_t device_id,
585 double x,
586 double y) {
587 auto state =
588 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
589
590 FlutterPointerEvent event = {};
591 event.x = x;
592 event.y = y;
593 event.signal_kind =
595 SetEventPhaseFromCursorButtonState(&event, state);
596 SendPointerEventWithData(event, state);
597}
598
599void FlutterWindowsView::SendPointerEventWithData(
600 const FlutterPointerEvent& event_data,
601 PointerState* state) {
602 // If sending anything other than an add, and the pointer isn't already added,
603 // synthesize an add to satisfy Flutter's expectations about events.
604 if (!state->flutter_state_is_added &&
605 event_data.phase != FlutterPointerPhase::kAdd) {
606 FlutterPointerEvent event = {};
608 event.x = event_data.x;
609 event.y = event_data.y;
610 event.buttons = 0;
611 SendPointerEventWithData(event, state);
612 }
613
614 // Don't double-add (e.g., if events are delivered out of order, so an add has
615 // already been synthesized).
616 if (state->flutter_state_is_added &&
617 event_data.phase == FlutterPointerPhase::kAdd) {
618 return;
619 }
620
621 FlutterPointerEvent event = event_data;
622 event.device_kind = state->device_kind;
623 event.device = state->pointer_id;
624 event.buttons = state->buttons;
625 event.view_id = view_id_;
626
627 // Set metadata that's always the same regardless of the event.
628 event.struct_size = sizeof(event);
629 event.timestamp =
630 std::chrono::duration_cast<std::chrono::microseconds>(
631 std::chrono::high_resolution_clock::now().time_since_epoch())
632 .count();
633
634 engine_->SendPointerEvent(event);
635
636 if (event_data.phase == FlutterPointerPhase::kAdd) {
637 state->flutter_state_is_added = true;
638 } else if (event_data.phase == FlutterPointerPhase::kRemove) {
639 auto it = pointer_states_.find(state->pointer_id);
640 if (it != pointer_states_.end()) {
641 pointer_states_.erase(it);
642 }
643 }
644}
645
647 // Called on the engine's raster thread.
648 std::unique_lock<std::mutex> lock(resize_mutex_);
649
650 switch (resize_status_) {
651 case ResizeState::kResizeStarted:
652 // The caller must first call |OnFrameGenerated| or
653 // |OnEmptyFrameGenerated| before calling this method. This
654 // indicates one of the following:
655 //
656 // 1. The caller did not call these methods.
657 // 2. The caller ignored these methods' result.
658 // 3. The platform thread started a resize after the caller called these
659 // methods. We might have presented a frame of the wrong size to the
660 // view.
661 return;
662 case ResizeState::kFrameGenerated: {
663 // A frame was generated for a pending resize.
664 // Unblock the platform thread.
665 resize_status_ = ResizeState::kDone;
666 lock.unlock();
667 resize_cv_.notify_all();
668
669 // Blocking the raster thread until DWM flushes alleviates glitches where
670 // previous size surface is stretched over current size view.
671 windows_proc_table_->DwmFlush();
672 }
673 case ResizeState::kDone:
674 return;
675 }
676}
677
679 return binding_handler_->OnBitmapSurfaceCleared();
680}
681
683 size_t row_bytes,
684 size_t height) {
685 return binding_handler_->OnBitmapSurfaceUpdated(allocation, row_bytes,
686 height);
687}
688
690 return view_id_;
691}
692
694 return view_id_ == kImplicitViewId;
695}
696
698 FML_DCHECK(surface_ == nullptr);
699
700 if (engine_->egl_manager()) {
701 PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
702 surface_ = engine_->egl_manager()->CreateWindowSurface(
703 GetWindowHandle(), bounds.width, bounds.height);
704
705 UpdateVsync(*engine_, surface_.get(), NeedsVsync());
706
707 resize_target_width_ = bounds.width;
708 resize_target_height_ = bounds.height;
709 }
710}
711
712bool FlutterWindowsView::ResizeRenderSurface(size_t width, size_t height) {
713 FML_DCHECK(surface_ != nullptr);
714
715 // No-op if the surface is already the desired size.
716 if (width == surface_->width() && height == surface_->height()) {
717 return true;
718 }
719
720 auto const existing_vsync = surface_->vsync_enabled();
721
722 // TODO: Destroying the surface and re-creating it is expensive.
723 // Ideally this would use ANGLE's automatic surface sizing instead.
724 // See: https://github.com/flutter/flutter/issues/79427
725 if (!surface_->Destroy()) {
726 FML_LOG(ERROR) << "View resize failed to destroy surface";
727 return false;
728 }
729
730 std::unique_ptr<egl::WindowSurface> resized_surface =
732 height);
733 if (!resized_surface) {
734 FML_LOG(ERROR) << "View resize failed to create surface";
735 return false;
736 }
737
738 if (!resized_surface->MakeCurrent() ||
739 !resized_surface->SetVSyncEnabled(existing_vsync)) {
740 // Surfaces block until the v-blank by default.
741 // Failing to update the vsync might result in unnecessary blocking.
742 // This regresses performance but not correctness.
743 FML_LOG(ERROR) << "View resize failed to set vsync";
744 }
745
746 surface_ = std::move(resized_surface);
747 return true;
748}
749
751 return surface_.get();
752}
753
755 engine_->UpdateHighContrastMode();
756}
757
759 return binding_handler_->GetWindowHandle();
760}
761
763 return engine_;
764}
765
766void FlutterWindowsView::AnnounceAlert(const std::wstring& text) {
767 auto alert_delegate = binding_handler_->GetAlertDelegate();
768 if (!alert_delegate) {
769 return;
770 }
771 alert_delegate->SetText(fml::WideStringToUtf16(text));
772 ui::AXPlatformNodeWin* alert_node = binding_handler_->GetAlert();
774}
775
776void FlutterWindowsView::NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
778 if (node) {
779 node->NotifyAccessibilityEvent(event);
780 }
781}
782
784 return accessibility_bridge_.get();
785}
786
787ui::AXPlatformNodeWin* FlutterWindowsView::AlertNode() const {
788 return binding_handler_->GetAlert();
789}
790
791std::shared_ptr<AccessibilityBridgeWindows>
793 return std::make_shared<AccessibilityBridgeWindows>(this);
794}
795
797 if (semantics_enabled_ != enabled) {
798 semantics_enabled_ = enabled;
799
800 if (!semantics_enabled_ && accessibility_bridge_) {
801 accessibility_bridge_.reset();
802 } else if (semantics_enabled_ && !accessibility_bridge_) {
803 accessibility_bridge_ = CreateAccessibilityBridge();
804 }
805 }
806}
807
809 UpdateVsync(*engine_, surface_.get(), NeedsVsync());
810}
811
813 engine_->OnWindowStateEvent(hwnd, event);
814}
815
816bool FlutterWindowsView::NeedsVsync() const {
817 // If the Desktop Window Manager composition is enabled,
818 // the system itself synchronizes with vsync.
819 // See: https://learn.microsoft.com/windows/win32/dwm/composition-ovw
820 return !windows_proc_table_->DwmIsCompositionEnabled();
821}
822
823} // namespace flutter
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event)
void SendPointerEvent(const FlutterPointerEvent &event)
void SendWindowMetricsEvent(const FlutterWindowMetricsEvent &event)
KeyboardHandlerBase * keyboard_key_handler()
virtual void OnPointerPanZoomStart(int32_t device_id) override
void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button) override
FlutterWindowsView(FlutterViewId view_id, FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > window_binding, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
virtual void UpdateSemanticsEnabled(bool enabled)
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate() override
void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state) override
void OnScrollInertiaCancel(int32_t device_id) override
virtual std::shared_ptr< AccessibilityBridgeWindows > CreateAccessibilityBridge()
ui::AXPlatformNodeWin * AlertNode() const
virtual void OnUpdateSemanticsEnabled(bool enabled) override
void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id=0) override
virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin *node, ax::mojom::Event event)
FlutterWindowsEngine * GetEngine() const
void OnScroll(double x, double y, double delta_x, double delta_y, int scroll_offset_multiplier, FlutterPointerDeviceKind device_kind, int32_t device_id) override
void UpdateFlutterCursor(const std::string &cursor_name)
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event) override
virtual void OnPointerPanZoomEnd(int32_t device_id) override
FlutterWindowMetricsEvent CreateWindowMetricsEvent() const
void AnnounceAlert(const std::wstring &text)
void SetFlutterCursor(HCURSOR cursor)
virtual bool PresentSoftwareBitmap(const void *allocation, size_t row_bytes, size_t height)
virtual HWND GetWindowHandle() const
egl::WindowSurface * surface() const
bool OnWindowSizeChanged(size_t width, size_t height) override
void OnText(const std::u16string &) override
virtual void OnPointerPanZoomUpdate(int32_t device_id, double pan_x, double pan_y, double scale, double rotation) override
void OnComposeChange(const std::u16string &text, int cursor_pos) override
void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button) override
virtual gfx::NativeViewAccessible GetNativeViewAccessible() override
virtual void OnCursorRectUpdated(const Rect &rect)
void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
bool OnFrameGenerated(size_t width, size_t height)
virtual void SyncModifiersIfNeeded(int modifiers_state)=0
virtual void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback)=0
virtual void ComposeChangeHook(const std::u16string &text, int cursor_pos)
virtual void TextHook(const std::u16string &text)
virtual std::unique_ptr< WindowSurface > CreateWindowSurface(HWND hwnd, size_t width, size_t height)
Definition: manager.cc:266
@ kPanZoomUpdate
The pan/zoom updated.
Definition: embedder.h:1001
@ kHover
The pointer moved while up.
Definition: embedder.h:997
@ kUp
Definition: embedder.h:973
@ kPanZoomStart
A pan/zoom started on this pointer.
Definition: embedder.h:999
@ kRemove
Definition: embedder.h:995
@ kDown
Definition: embedder.h:980
@ kAdd
Definition: embedder.h:990
@ kMove
Definition: embedder.h:985
@ kPanZoomEnd
The pan/zoom ended.
Definition: embedder.h:1003
FlutterPointerMouseButtons
Definition: embedder.h:1016
@ kFlutterPointerSignalKindScrollInertiaCancel
Definition: embedder.h:1030
@ kFlutterPointerSignalKindScroll
Definition: embedder.h:1029
FlutterPointerDeviceKind
The device type that created a pointer event.
Definition: embedder.h:1007
@ kFlutterPointerDeviceKindTrackpad
Definition: embedder.h:1011
FlutterEngine engine
Definition: main.cc:68
VkSurfaceKHR surface
Definition: main.cc:49
AtkStateType state
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_DCHECK(condition)
Definition: logging.h:103
std::u16string text
double y
double x
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
WindowStateEvent
An event representing a change in window state that may update the.
constexpr FlutterViewId kImplicitViewId
int64_t FlutterViewId
Definition: flutter_view.h:13
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
std::u16string WideStringToUtf16(const std::wstring_view str)
UnimplementedNativeViewAccessible * NativeViewAccessible
Definition: ref_ptr.h:256
int32_t height
int32_t width
const Scalar scale
double y
The y coordinate of the pointer event in physical pixels.
Definition: embedder.h:1045
double x
The x coordinate of the pointer event in physical pixels.
Definition: embedder.h:1043
FlutterPointerDeviceKind device_kind
Definition: embedder.h:1059
FlutterPointerPhase phase
Definition: embedder.h:1037
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition: embedder.h:843
#define ERROR(message)
Definition: elf_loader.cc:260