Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
6
7#include <chrono>
8
17
18namespace flutter {
19
20namespace {
21// The maximum duration to block the Windows event loop 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
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
180 if (resize_status_ == ResizeState::kDone) {
181 // Request new frame.
182 engine_->ScheduleFrame();
183 }
184}
185
186// Called on the platform thread.
188 if (!engine_->egl_manager()) {
189 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
190 return true;
191 }
192
193 if (!surface_ || !surface_->IsValid()) {
194 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
195 return true;
196 }
197
198 // We're using OpenGL rendering. Resizing the surface must happen on the
199 // raster thread.
200 bool surface_will_update =
201 SurfaceWillUpdate(surface_->width(), surface_->height(), width, height);
202 if (!surface_will_update) {
203 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
204 return true;
205 }
206
207 {
208 std::unique_lock<std::mutex> lock(resize_mutex_);
209 resize_status_ = ResizeState::kResizeStarted;
210 resize_target_width_ = width;
211 resize_target_height_ = height;
212 }
213
214 SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
215
216 std::chrono::time_point<std::chrono::steady_clock> start_time =
217 std::chrono::steady_clock::now();
218
219 while (true) {
220 if (std::chrono::steady_clock::now() > start_time + kWindowResizeTimeout) {
221 return false;
222 }
223 std::unique_lock<std::mutex> lock(resize_mutex_);
224 if (resize_status_ == ResizeState::kDone) {
225 break;
226 }
227 lock.unlock();
228 engine_->task_runner()->PollOnce(kWindowResizeTimeout);
229 }
230 return true;
231}
232
236
238 double y,
239 FlutterPointerDeviceKind device_kind,
240 int32_t device_id,
241 int modifiers_state) {
242 engine_->keyboard_key_handler()->SyncModifiersIfNeeded(modifiers_state);
243 SendPointerMove(x, y, GetOrCreatePointerState(device_kind, device_id));
244}
245
247 double x,
248 double y,
249 FlutterPointerDeviceKind device_kind,
250 int32_t device_id,
251 FlutterPointerMouseButtons flutter_button) {
252 if (flutter_button != 0) {
253 auto state = GetOrCreatePointerState(device_kind, device_id);
254 state->buttons |= flutter_button;
255 SendPointerDown(x, y, state);
256 }
257}
258
260 double x,
261 double y,
262 FlutterPointerDeviceKind device_kind,
263 int32_t device_id,
264 FlutterPointerMouseButtons flutter_button) {
265 if (flutter_button != 0) {
266 auto state = GetOrCreatePointerState(device_kind, device_id);
267 state->buttons &= ~flutter_button;
268 SendPointerUp(x, y, state);
269 }
270}
271
273 double y,
274 FlutterPointerDeviceKind device_kind,
275 int32_t device_id) {
276 SendPointerLeave(x, y, GetOrCreatePointerState(device_kind, device_id));
277}
278
280 PointerLocation point = binding_handler_->GetPrimaryPointerLocation();
281 SendPointerPanZoomStart(device_id, point.x, point.y);
282}
283
285 double pan_x,
286 double pan_y,
287 double scale,
288 double rotation) {
289 SendPointerPanZoomUpdate(device_id, pan_x, pan_y, scale, rotation);
290}
291
293 SendPointerPanZoomEnd(device_id);
294}
295
296void FlutterWindowsView::OnText(const std::u16string& text) {
297 SendText(text);
298}
299
301 int scancode,
302 int action,
303 char32_t character,
304 bool extended,
305 bool was_down,
308}
309
311 FlutterViewFocusDirection direction) {
312 SendFocus(focus_state, direction);
313}
314
316 SendComposeBegin();
317}
318
320 SendComposeCommit();
321}
322
324 SendComposeEnd();
325}
326
327void FlutterWindowsView::OnComposeChange(const std::u16string& text,
328 int cursor_pos) {
329 SendComposeChange(text, cursor_pos);
330}
331
333 double y,
334 double delta_x,
335 double delta_y,
336 int scroll_offset_multiplier,
337 FlutterPointerDeviceKind device_kind,
338 int32_t device_id) {
339 SendScroll(x, y, delta_x, delta_y, scroll_offset_multiplier, device_kind,
340 device_id);
341}
342
344 PointerLocation point = binding_handler_->GetPrimaryPointerLocation();
345 SendScrollInertiaCancel(device_id, point.x, point.y);
346}
347
349 engine_->UpdateSemanticsEnabled(enabled);
350}
351
353 if (!accessibility_bridge_) {
354 return nullptr;
355 }
356
357 return accessibility_bridge_->GetChildOfAXFragmentRoot();
358}
359
361 binding_handler_->OnCursorRectUpdated(rect);
362}
363
365 binding_handler_->OnResetImeComposing();
366}
367
368// Sends new size information to FlutterEngine.
369void FlutterWindowsView::SendWindowMetrics(size_t width,
370 size_t height,
371 double pixel_ratio) const {
372 FlutterEngineDisplayId display_id = binding_handler_->GetDisplayId();
373 FlutterWindowMetricsEvent event = {};
374 event.struct_size = sizeof(event);
375 event.width = width;
376 event.height = height;
377 event.pixel_ratio = pixel_ratio;
378 event.display_id = display_id;
379 event.view_id = view_id_;
380 engine_->SendWindowMetricsEvent(event);
381}
382
384 PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
385 double pixel_ratio = binding_handler_->GetDpiScale();
386 FlutterEngineDisplayId display_id = binding_handler_->GetDisplayId();
387
388 FlutterWindowMetricsEvent event = {};
389 event.struct_size = sizeof(event);
390 event.width = bounds.width;
391 event.height = bounds.height;
392 event.pixel_ratio = pixel_ratio;
393 event.display_id = display_id;
394 event.view_id = view_id_;
395
396 return event;
397}
398
400 // Non-implicit views' initial window metrics are sent when the view is added
401 // to the engine.
402 if (!IsImplicitView()) {
403 return;
404 }
405
407}
408
409FlutterWindowsView::PointerState* FlutterWindowsView::GetOrCreatePointerState(
410 FlutterPointerDeviceKind device_kind,
411 int32_t device_id) {
412 // Create a virtual pointer ID that is unique across all device types
413 // to prevent pointers from clashing in the engine's converter
414 // (lib/ui/window/pointer_data_packet_converter.cc)
415 int32_t pointer_id = (static_cast<int32_t>(device_kind) << 28) | device_id;
416
417 auto [it, added] = pointer_states_.try_emplace(pointer_id, nullptr);
418 if (added) {
419 auto state = std::make_unique<PointerState>();
420 state->device_kind = device_kind;
421 state->pointer_id = pointer_id;
422 it->second = std::move(state);
423 }
424
425 return it->second.get();
426}
427
428// Set's |event_data|'s phase to either kMove or kHover depending on the current
429// primary mouse button state.
430void FlutterWindowsView::SetEventPhaseFromCursorButtonState(
431 FlutterPointerEvent* event_data,
432 const PointerState* state) const {
433 // For details about this logic, see FlutterPointerPhase in the embedder.h
434 // file.
435 if (state->buttons == 0) {
436 event_data->phase = state->flutter_state_is_down
439 } else {
440 event_data->phase = state->flutter_state_is_down
443 }
444}
445
446void FlutterWindowsView::SendPointerMove(double x,
447 double y,
448 PointerState* state) {
449 FlutterPointerEvent event = {};
450 event.x = x;
451 event.y = y;
452
453 SetEventPhaseFromCursorButtonState(&event, state);
454 SendPointerEventWithData(event, state);
455}
456
457void FlutterWindowsView::SendPointerDown(double x,
458 double y,
459 PointerState* state) {
460 FlutterPointerEvent event = {};
461 event.x = x;
462 event.y = y;
463
464 SetEventPhaseFromCursorButtonState(&event, state);
465 SendPointerEventWithData(event, state);
466
467 state->flutter_state_is_down = true;
468}
469
470void FlutterWindowsView::SendPointerUp(double x,
471 double y,
472 PointerState* state) {
473 FlutterPointerEvent event = {};
474 event.x = x;
475 event.y = y;
476
477 SetEventPhaseFromCursorButtonState(&event, state);
478 SendPointerEventWithData(event, state);
479 if (event.phase == FlutterPointerPhase::kUp) {
480 state->flutter_state_is_down = false;
481 }
482}
483
484void FlutterWindowsView::SendPointerLeave(double x,
485 double y,
486 PointerState* state) {
487 FlutterPointerEvent event = {};
488 event.x = x;
489 event.y = y;
490 event.phase = FlutterPointerPhase::kRemove;
491 SendPointerEventWithData(event, state);
492}
493
494void FlutterWindowsView::SendPointerPanZoomStart(int32_t device_id,
495 double x,
496 double y) {
497 auto state =
498 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
499 state->pan_zoom_start_x = x;
500 state->pan_zoom_start_y = y;
501 FlutterPointerEvent event = {};
502 event.x = x;
503 event.y = y;
505 SendPointerEventWithData(event, state);
506}
507
508void FlutterWindowsView::SendPointerPanZoomUpdate(int32_t device_id,
509 double pan_x,
510 double pan_y,
511 double scale,
512 double rotation) {
513 auto state =
514 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
515 FlutterPointerEvent event = {};
516 event.x = state->pan_zoom_start_x;
517 event.y = state->pan_zoom_start_y;
518 event.pan_x = pan_x;
519 event.pan_y = pan_y;
520 event.scale = scale;
521 event.rotation = rotation;
523 SendPointerEventWithData(event, state);
524}
525
526void FlutterWindowsView::SendPointerPanZoomEnd(int32_t device_id) {
527 auto state =
528 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
529 FlutterPointerEvent event = {};
530 event.x = state->pan_zoom_start_x;
531 event.y = state->pan_zoom_start_y;
533 SendPointerEventWithData(event, state);
534}
535
536void FlutterWindowsView::SendText(const std::u16string& text) {
537 engine_->text_input_plugin()->TextHook(text);
538}
539
540void FlutterWindowsView::SendKey(int key,
541 int scancode,
542 int action,
543 char32_t character,
544 bool extended,
545 bool was_down,
546 KeyEventCallback callback) {
549 [engine = engine_, view_id = view_id_, key, scancode, action, character,
550 extended, was_down, callback = std::move(callback)](bool handled) {
551 if (!handled) {
552 engine->text_input_plugin()->KeyboardHook(
554 }
555 if (engine->view(view_id)) {
556 callback(handled);
557 }
558 });
559}
560
561void FlutterWindowsView::SendFocus(FlutterViewFocusState focus_state,
562 FlutterViewFocusDirection direction) {
563 FlutterViewFocusEvent event = {};
564 event.struct_size = sizeof(event);
565 event.view_id = view_id_;
566 event.state = focus_state;
567 event.direction = direction;
568 engine_->SendViewFocusEvent(event);
569}
570
571void FlutterWindowsView::SendComposeBegin() {
573}
574
575void FlutterWindowsView::SendComposeCommit() {
577}
578
579void FlutterWindowsView::SendComposeEnd() {
580 engine_->text_input_plugin()->ComposeEndHook();
581}
582
583void FlutterWindowsView::SendComposeChange(const std::u16string& text,
584 int cursor_pos) {
585 engine_->text_input_plugin()->ComposeChangeHook(text, cursor_pos);
586}
587
588void FlutterWindowsView::SendScroll(double x,
589 double y,
590 double delta_x,
591 double delta_y,
592 int scroll_offset_multiplier,
593 FlutterPointerDeviceKind device_kind,
594 int32_t device_id) {
595 auto state = GetOrCreatePointerState(device_kind, device_id);
596
597 FlutterPointerEvent event = {};
598 event.x = x;
599 event.y = y;
601 event.scroll_delta_x = delta_x * scroll_offset_multiplier;
602 event.scroll_delta_y = delta_y * scroll_offset_multiplier;
603 SetEventPhaseFromCursorButtonState(&event, state);
604 SendPointerEventWithData(event, state);
605}
606
607void FlutterWindowsView::SendScrollInertiaCancel(int32_t device_id,
608 double x,
609 double y) {
610 auto state =
611 GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
612
613 FlutterPointerEvent event = {};
614 event.x = x;
615 event.y = y;
616 event.signal_kind =
618 SetEventPhaseFromCursorButtonState(&event, state);
619 SendPointerEventWithData(event, state);
620}
621
622void FlutterWindowsView::SendPointerEventWithData(
623 const FlutterPointerEvent& event_data,
624 PointerState* state) {
625 // If sending anything other than an add, and the pointer isn't already added,
626 // synthesize an add to satisfy Flutter's expectations about events.
627 if (!state->flutter_state_is_added &&
628 event_data.phase != FlutterPointerPhase::kAdd) {
629 FlutterPointerEvent event = {};
631 event.x = event_data.x;
632 event.y = event_data.y;
633 event.buttons = 0;
634 SendPointerEventWithData(event, state);
635 }
636
637 // Don't double-add (e.g., if events are delivered out of order, so an add has
638 // already been synthesized).
639 if (state->flutter_state_is_added &&
640 event_data.phase == FlutterPointerPhase::kAdd) {
641 return;
642 }
643
644 FlutterPointerEvent event = event_data;
645 event.device_kind = state->device_kind;
646 event.device = state->pointer_id;
647 event.buttons = state->buttons;
648 event.view_id = view_id_;
649
650 // Set metadata that's always the same regardless of the event.
651 event.struct_size = sizeof(event);
652 event.timestamp =
653 std::chrono::duration_cast<std::chrono::microseconds>(
654 std::chrono::high_resolution_clock::now().time_since_epoch())
655 .count();
656
657 engine_->SendPointerEvent(event);
658
659 if (event_data.phase == FlutterPointerPhase::kAdd) {
660 state->flutter_state_is_added = true;
661 } else if (event_data.phase == FlutterPointerPhase::kRemove) {
662 auto it = pointer_states_.find(state->pointer_id);
663 if (it != pointer_states_.end()) {
664 pointer_states_.erase(it);
665 }
666 }
667}
668
670 // Called on the engine's raster thread.
671 std::unique_lock<std::mutex> lock(resize_mutex_);
672
673 switch (resize_status_) {
674 case ResizeState::kResizeStarted:
675 // The caller must first call |OnFrameGenerated| or
676 // |OnEmptyFrameGenerated| before calling this method. This
677 // indicates one of the following:
678 //
679 // 1. The caller did not call these methods.
680 // 2. The caller ignored these methods' result.
681 // 3. The platform thread started a resize after the caller called these
682 // methods. We might have presented a frame of the wrong size to the
683 // view.
684 return;
685 case ResizeState::kFrameGenerated: {
686 // A frame was generated for a pending resize.
687 resize_status_ = ResizeState::kDone;
688 // Unblock the platform thread.
689 engine_->task_runner()->PostTask([this] {});
690
691 lock.unlock();
692
693 // Blocking the raster thread until DWM flushes alleviates glitches where
694 // previous size surface is stretched over current size view.
695 windows_proc_table_->DwmFlush();
696 }
697 case ResizeState::kDone:
698 return;
699 }
700}
701
703 return binding_handler_->OnBitmapSurfaceCleared();
704}
705
707 size_t row_bytes,
708 size_t height) {
709 return binding_handler_->OnBitmapSurfaceUpdated(allocation, row_bytes,
710 height);
711}
712
714 return view_id_;
715}
716
718 return view_id_ == kImplicitViewId;
719}
720
722 FML_DCHECK(surface_ == nullptr);
723
724 if (engine_->egl_manager()) {
725 PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
726 surface_ = engine_->egl_manager()->CreateWindowSurface(
727 GetWindowHandle(), bounds.width, bounds.height);
728
729 UpdateVsync(*engine_, surface_.get(), NeedsVsync());
730
731 resize_target_width_ = bounds.width;
732 resize_target_height_ = bounds.height;
733 }
734}
735
736bool FlutterWindowsView::ResizeRenderSurface(size_t width, size_t height) {
737 FML_DCHECK(surface_ != nullptr);
738
739 // No-op if the surface is already the desired size.
740 if (width == surface_->width() && height == surface_->height()) {
741 return true;
742 }
743
744 auto const existing_vsync = surface_->vsync_enabled();
745
746 // TODO: Destroying the surface and re-creating it is expensive.
747 // Ideally this would use ANGLE's automatic surface sizing instead.
748 // See: https://github.com/flutter/flutter/issues/79427
749 if (!surface_->Destroy()) {
750 FML_LOG(ERROR) << "View resize failed to destroy surface";
751 return false;
752 }
753
754 std::unique_ptr<egl::WindowSurface> resized_surface =
756 height);
757 if (!resized_surface) {
758 FML_LOG(ERROR) << "View resize failed to create surface";
759 return false;
760 }
761
762 if (!resized_surface->MakeCurrent() ||
763 !resized_surface->SetVSyncEnabled(existing_vsync)) {
764 // Surfaces block until the v-blank by default.
765 // Failing to update the vsync might result in unnecessary blocking.
766 // This regresses performance but not correctness.
767 FML_LOG(ERROR) << "View resize failed to set vsync";
768 }
769
770 surface_ = std::move(resized_surface);
771 return true;
772}
773
775 return surface_.get();
776}
777
781
783 return binding_handler_->GetWindowHandle();
784}
785
787 return engine_;
788}
789
790void FlutterWindowsView::AnnounceAlert(const std::wstring& text) {
791 auto alert_delegate = binding_handler_->GetAlertDelegate();
792 if (!alert_delegate) {
793 return;
794 }
795 alert_delegate->SetText(fml::WideStringToUtf16(text));
796 ui::AXPlatformNodeWin* alert_node = binding_handler_->GetAlert();
798}
799
800void FlutterWindowsView::NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
801 ax::mojom::Event event) {
802 if (node) {
803 node->NotifyAccessibilityEvent(event);
804 }
805}
806
808 return accessibility_bridge_.get();
809}
810
811ui::AXPlatformNodeWin* FlutterWindowsView::AlertNode() const {
812 return binding_handler_->GetAlert();
813}
814
815std::shared_ptr<AccessibilityBridgeWindows>
817 return std::make_shared<AccessibilityBridgeWindows>(this);
818}
819
821 if (semantics_enabled_ != enabled) {
822 semantics_enabled_ = enabled;
823
824 if (!semantics_enabled_ && accessibility_bridge_) {
825 accessibility_bridge_.reset();
826 } else if (semantics_enabled_ && !accessibility_bridge_) {
827 accessibility_bridge_ = CreateAccessibilityBridge();
828 }
829 }
830}
831
833 UpdateVsync(*engine_, surface_.get(), NeedsVsync());
834}
835
837 engine_->OnWindowStateEvent(hwnd, event);
838}
839
841 return binding_handler_->Focus();
842}
843
844bool FlutterWindowsView::NeedsVsync() const {
845 // If the Desktop Window Manager composition is enabled,
846 // the system itself synchronizes with vsync.
847 // See: https://learn.microsoft.com/windows/win32/dwm/composition-ovw
848 return !windows_proc_table_->DwmIsCompositionEnabled();
849}
850
851} // namespace flutter
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event)
void SendViewFocusEvent(const FlutterViewFocusEvent &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 OnWindowStateEvent(HWND hwnd, WindowStateEvent event) override
virtual void OnPointerPanZoomEnd(int32_t device_id) override
FlutterWindowMetricsEvent CreateWindowMetricsEvent() const
void AnnounceAlert(const std::wstring &text)
virtual bool PresentSoftwareBitmap(const void *allocation, size_t row_bytes, size_t height)
void OnFocus(FlutterViewFocusState focus_state, FlutterViewFocusDirection direction) override
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
void PollOnce(std::chrono::milliseconds timeout)
void PostTask(TaskClosure task)
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:276
int32_t x
uint64_t FlutterEngineDisplayId
Definition embedder.h:1043
FlutterViewFocusState
Represents the focus state of a given [FlutterView].
Definition embedder.h:1189
FlutterViewFocusDirection
Definition embedder.h:1170
@ kPanZoomUpdate
The pan/zoom updated.
Definition embedder.h:1273
@ kHover
The pointer moved while up.
Definition embedder.h:1269
@ kUp
Definition embedder.h:1245
@ kPanZoomStart
A pan/zoom started on this pointer.
Definition embedder.h:1271
@ kRemove
Definition embedder.h:1267
@ kDown
Definition embedder.h:1252
@ kAdd
Definition embedder.h:1262
@ kMove
Definition embedder.h:1257
@ kPanZoomEnd
The pan/zoom ended.
Definition embedder.h:1275
FlutterPointerMouseButtons
Definition embedder.h:1288
@ kFlutterPointerSignalKindScrollInertiaCancel
Definition embedder.h:1302
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1301
FlutterPointerDeviceKind
The device type that created a pointer event.
Definition embedder.h:1279
@ kFlutterPointerDeviceKindTrackpad
Definition embedder.h:1283
FlutterEngine engine
Definition main.cc:84
VkSurfaceKHR surface
Definition main.cc:65
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
std::u16string text
double y
WindowStateEvent
An event representing a change in window state that may update the.
constexpr FlutterViewId kImplicitViewId
int64_t FlutterViewId
internal::CopyableLambda< T > MakeCopyable(T lambda)
std::u16string WideStringToUtf16(const std::wstring_view str)
UnimplementedNativeViewAccessible * NativeViewAccessible
Definition ref_ptr.h:261
int32_t height
int32_t width
double y
The y coordinate of the pointer event in physical pixels.
Definition embedder.h:1317
double x
The x coordinate of the pointer event in physical pixels.
Definition embedder.h:1315
FlutterPointerDeviceKind device_kind
Definition embedder.h:1331
FlutterPointerPhase phase
Definition embedder.h:1309
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition embedder.h:1047