Flutter Windows Embedder
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 
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"
16 #include "flutter/third_party/accessibility/ax/platform/ax_platform_node_win.h"
17 
18 namespace flutter {
19 
20 namespace {
21 // The maximum duration to block the platform thread for while waiting
22 // for a window resize operation to complete.
23 constexpr 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`.
31 bool 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.
45 void 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.
87 void 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,
106  FlutterWindowsEngine* engine,
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 
153 bool FlutterWindowsView::OnFrameGenerated(size_t width, size_t height) {
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 
179 void 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 
194 bool FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
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 
295 void 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 
321 void 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 
346 gfx::NativeViewAccessible FlutterWindowsView::GetNativeViewAccessible() {
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.
363 void 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_;
372  engine_->SendWindowMetricsEvent(event);
373 }
374 
375 FlutterWindowMetricsEvent FlutterWindowsView::CreateWindowMetricsEvent() const {
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 
399 FlutterWindowsView::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.
420 void 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
427  ? FlutterPointerPhase::kUp
428  : FlutterPointerPhase::kHover;
429  } else {
430  event_data->phase = state->flutter_state_is_down
431  ? FlutterPointerPhase::kMove
432  : FlutterPointerPhase::kDown;
433  }
434 }
435 
436 void 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 
447 void 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 
460 void 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 
474 void 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 
484 void 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;
494  event.phase = FlutterPointerPhase::kPanZoomStart;
495  SendPointerEventWithData(event, state);
496 }
497 
498 void 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;
512  event.phase = FlutterPointerPhase::kPanZoomUpdate;
513  SendPointerEventWithData(event, state);
514 }
515 
516 void 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;
522  event.phase = FlutterPointerPhase::kPanZoomEnd;
523  SendPointerEventWithData(event, state);
524 }
525 
526 void FlutterWindowsView::SendText(const std::u16string& text) {
527  engine_->text_input_plugin()->TextHook(text);
528 }
529 
530 void 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  [engine = engine_, view_id = view_id_, key, scancode, action, character,
540  extended, was_down, callback = std::move(callback)](bool handled) {
541  if (!handled) {
542  engine->text_input_plugin()->KeyboardHook(
544  }
545  if (engine->view(view_id)) {
546  callback(handled);
547  }
548  });
549 }
550 
551 void FlutterWindowsView::SendComposeBegin() {
552  engine_->text_input_plugin()->ComposeBeginHook();
553 }
554 
555 void FlutterWindowsView::SendComposeCommit() {
556  engine_->text_input_plugin()->ComposeCommitHook();
557 }
558 
559 void FlutterWindowsView::SendComposeEnd() {
560  engine_->text_input_plugin()->ComposeEndHook();
561 }
562 
563 void FlutterWindowsView::SendComposeChange(const std::u16string& text,
564  int cursor_pos) {
565  engine_->text_input_plugin()->ComposeChangeHook(text, cursor_pos);
566 }
567 
568 void FlutterWindowsView::SendScroll(double x,
569  double y,
570  double delta_x,
571  double delta_y,
572  int scroll_offset_multiplier,
573  FlutterPointerDeviceKind device_kind,
574  int32_t device_id) {
575  auto state = GetOrCreatePointerState(device_kind, device_id);
576 
577  FlutterPointerEvent event = {};
578  event.x = x;
579  event.y = y;
580  event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll;
581  event.scroll_delta_x = delta_x * scroll_offset_multiplier;
582  event.scroll_delta_y = delta_y * scroll_offset_multiplier;
583  SetEventPhaseFromCursorButtonState(&event, state);
584  SendPointerEventWithData(event, state);
585 }
586 
587 void FlutterWindowsView::SendScrollInertiaCancel(int32_t device_id,
588  double x,
589  double y) {
590  auto state =
591  GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
592 
593  FlutterPointerEvent event = {};
594  event.x = x;
595  event.y = y;
596  event.signal_kind =
597  FlutterPointerSignalKind::kFlutterPointerSignalKindScrollInertiaCancel;
598  SetEventPhaseFromCursorButtonState(&event, state);
599  SendPointerEventWithData(event, state);
600 }
601 
602 void FlutterWindowsView::SendPointerEventWithData(
603  const FlutterPointerEvent& event_data,
604  PointerState* state) {
605  // If sending anything other than an add, and the pointer isn't already added,
606  // synthesize an add to satisfy Flutter's expectations about events.
607  if (!state->flutter_state_is_added &&
608  event_data.phase != FlutterPointerPhase::kAdd) {
609  FlutterPointerEvent event = {};
610  event.phase = FlutterPointerPhase::kAdd;
611  event.x = event_data.x;
612  event.y = event_data.y;
613  event.buttons = 0;
614  SendPointerEventWithData(event, state);
615  }
616 
617  // Don't double-add (e.g., if events are delivered out of order, so an add has
618  // already been synthesized).
619  if (state->flutter_state_is_added &&
620  event_data.phase == FlutterPointerPhase::kAdd) {
621  return;
622  }
623 
624  FlutterPointerEvent event = event_data;
625  event.device_kind = state->device_kind;
626  event.device = state->pointer_id;
627  event.buttons = state->buttons;
628  event.view_id = view_id_;
629 
630  // Set metadata that's always the same regardless of the event.
631  event.struct_size = sizeof(event);
632  event.timestamp =
633  std::chrono::duration_cast<std::chrono::microseconds>(
634  std::chrono::high_resolution_clock::now().time_since_epoch())
635  .count();
636 
637  engine_->SendPointerEvent(event);
638 
639  if (event_data.phase == FlutterPointerPhase::kAdd) {
640  state->flutter_state_is_added = true;
641  } else if (event_data.phase == FlutterPointerPhase::kRemove) {
642  auto it = pointer_states_.find(state->pointer_id);
643  if (it != pointer_states_.end()) {
644  pointer_states_.erase(it);
645  }
646  }
647 }
648 
650  // Called on the engine's raster thread.
651  std::unique_lock<std::mutex> lock(resize_mutex_);
652 
653  switch (resize_status_) {
654  case ResizeState::kResizeStarted:
655  // The caller must first call |OnFrameGenerated| or
656  // |OnEmptyFrameGenerated| before calling this method. This
657  // indicates one of the following:
658  //
659  // 1. The caller did not call these methods.
660  // 2. The caller ignored these methods' result.
661  // 3. The platform thread started a resize after the caller called these
662  // methods. We might have presented a frame of the wrong size to the
663  // view.
664  return;
665  case ResizeState::kFrameGenerated: {
666  // A frame was generated for a pending resize.
667  // Unblock the platform thread.
668  resize_status_ = ResizeState::kDone;
669  lock.unlock();
670  resize_cv_.notify_all();
671 
672  // Blocking the raster thread until DWM flushes alleviates glitches where
673  // previous size surface is stretched over current size view.
674  windows_proc_table_->DwmFlush();
675  }
676  case ResizeState::kDone:
677  return;
678  }
679 }
680 
682  return binding_handler_->OnBitmapSurfaceCleared();
683 }
684 
685 bool FlutterWindowsView::PresentSoftwareBitmap(const void* allocation,
686  size_t row_bytes,
687  size_t height) {
688  return binding_handler_->OnBitmapSurfaceUpdated(allocation, row_bytes,
689  height);
690 }
691 
693  return view_id_;
694 }
695 
697  return view_id_ == kImplicitViewId;
698 }
699 
701  FML_DCHECK(surface_ == nullptr);
702 
703  if (engine_->egl_manager()) {
704  PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
705  surface_ = engine_->egl_manager()->CreateWindowSurface(
706  GetWindowHandle(), bounds.width, bounds.height);
707 
708  UpdateVsync(*engine_, surface_.get(), NeedsVsync());
709 
710  resize_target_width_ = bounds.width;
711  resize_target_height_ = bounds.height;
712  }
713 }
714 
715 bool FlutterWindowsView::ResizeRenderSurface(size_t width, size_t height) {
716  FML_DCHECK(surface_ != nullptr);
717 
718  // No-op if the surface is already the desired size.
719  if (width == surface_->width() && height == surface_->height()) {
720  return true;
721  }
722 
723  auto const existing_vsync = surface_->vsync_enabled();
724 
725  // TODO: Destroying the surface and re-creating it is expensive.
726  // Ideally this would use ANGLE's automatic surface sizing instead.
727  // See: https://github.com/flutter/flutter/issues/79427
728  if (!surface_->Destroy()) {
729  FML_LOG(ERROR) << "View resize failed to destroy surface";
730  return false;
731  }
732 
733  std::unique_ptr<egl::WindowSurface> resized_surface =
734  engine_->egl_manager()->CreateWindowSurface(GetWindowHandle(), width,
735  height);
736  if (!resized_surface) {
737  FML_LOG(ERROR) << "View resize failed to create surface";
738  return false;
739  }
740 
741  if (!resized_surface->MakeCurrent() ||
742  !resized_surface->SetVSyncEnabled(existing_vsync)) {
743  // Surfaces block until the v-blank by default.
744  // Failing to update the vsync might result in unnecessary blocking.
745  // This regresses performance but not correctness.
746  FML_LOG(ERROR) << "View resize failed to set vsync";
747  }
748 
749  surface_ = std::move(resized_surface);
750  return true;
751 }
752 
754  return surface_.get();
755 }
756 
758  engine_->UpdateHighContrastMode();
759 }
760 
762  return binding_handler_->GetWindowHandle();
763 }
764 
766  return engine_;
767 }
768 
769 void FlutterWindowsView::AnnounceAlert(const std::wstring& text) {
770  auto alert_delegate = binding_handler_->GetAlertDelegate();
771  if (!alert_delegate) {
772  return;
773  }
774  alert_delegate->SetText(fml::WideStringToUtf16(text));
775  ui::AXPlatformNodeWin* alert_node = binding_handler_->GetAlert();
776  NotifyWinEventWrapper(alert_node, ax::mojom::Event::kAlert);
777 }
778 
779 void FlutterWindowsView::NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
780  ax::mojom::Event event) {
781  if (node) {
782  node->NotifyAccessibilityEvent(event);
783  }
784 }
785 
786 ui::AXFragmentRootDelegateWin* FlutterWindowsView::GetAxFragmentRootDelegate() {
787  return accessibility_bridge_.get();
788 }
789 
790 ui::AXPlatformNodeWin* FlutterWindowsView::AlertNode() const {
791  return binding_handler_->GetAlert();
792 }
793 
794 std::shared_ptr<AccessibilityBridgeWindows>
796  return std::make_shared<AccessibilityBridgeWindows>(this);
797 }
798 
800  if (semantics_enabled_ != enabled) {
801  semantics_enabled_ = enabled;
802 
803  if (!semantics_enabled_ && accessibility_bridge_) {
804  accessibility_bridge_.reset();
805  } else if (semantics_enabled_ && !accessibility_bridge_) {
806  accessibility_bridge_ = CreateAccessibilityBridge();
807  }
808  }
809 }
810 
812  UpdateVsync(*engine_, surface_.get(), NeedsVsync());
813 }
814 
816  engine_->OnWindowStateEvent(hwnd, event);
817 }
818 
819 bool FlutterWindowsView::NeedsVsync() const {
820  // If the Desktop Window Manager composition is enabled,
821  // the system itself synchronizes with vsync.
822  // See: https://learn.microsoft.com/windows/win32/dwm/composition-ovw
823  return !windows_proc_table_->DwmIsCompositionEnabled();
824 }
825 
826 } // namespace flutter
flutter::FlutterWindowsView::OnPointerMove
void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state) override
Definition: flutter_windows_view.cc:236
flutter::TextInputPlugin::ComposeBeginHook
virtual void ComposeBeginHook()
Definition: text_input_plugin.cc:125
flutter::TextInputPlugin::ComposeChangeHook
virtual void ComposeChangeHook(const std::u16string &text, int cursor_pos)
Definition: text_input_plugin.cc:192
flutter::FlutterWindowsView::OnPointerUp
void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button) override
Definition: flutter_windows_view.cc:258
flutter::kImplicitViewId
constexpr FlutterViewId kImplicitViewId
Definition: flutter_windows_engine.h:55
flutter::WindowStateEvent
WindowStateEvent
An event representing a change in window state that may update the.
Definition: windows_lifecycle_manager.h:24
flutter::FlutterWindowsView::OnWindowStateEvent
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event) override
Definition: flutter_windows_view.cc:815
flutter::FlutterWindowsView::CreateRenderSurface
void CreateRenderSurface()
Definition: flutter_windows_view.cc:700
flutter::FlutterWindowsView::OnUpdateSemanticsEnabled
virtual void OnUpdateSemanticsEnabled(bool enabled) override
Definition: flutter_windows_view.cc:342
flutter::WindowStateEvent::kHide
@ kHide
flutter::FlutterWindowsView::FlutterWindowsView
FlutterWindowsView(FlutterViewId view_id, FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > window_binding, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
Definition: flutter_windows_view.cc:104
flutter::FlutterWindowsView::OnComposeCommit
void OnComposeCommit() override
Definition: flutter_windows_view.cc:313
flutter::FlutterWindowsEngine::SendPointerEvent
void SendPointerEvent(const FlutterPointerEvent &event)
Definition: flutter_windows_engine.cc:686
scancode
int scancode
Definition: keyboard_key_handler_unittests.cc:115
flutter::FlutterWindowsView::~FlutterWindowsView
virtual ~FlutterWindowsView()
Definition: flutter_windows_view.cc:121
was_down
bool was_down
Definition: keyboard_key_handler_unittests.cc:119
text_input_plugin.h
flutter::FlutterWindowsView::surface
egl::WindowSurface * surface() const
Definition: flutter_windows_view.cc:753
extended
bool extended
Definition: keyboard_key_handler_unittests.cc:118
flutter::egl::WindowSurface
Definition: window_surface.h:19
flutter::FlutterWindowsView::OnPointerDown
void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button) override
Definition: flutter_windows_view.cc:245
flutter::FlutterWindowsEngine
Definition: flutter_windows_engine.h:90
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
flutter::FlutterWindowsView::OnComposeChange
void OnComposeChange(const std::u16string &text, int cursor_pos) override
Definition: flutter_windows_view.cc:321
flutter::TextInputPlugin::ComposeEndHook
virtual void ComposeEndHook()
Definition: text_input_plugin.cc:175
flutter::FlutterWindowsView::OnScrollInertiaCancel
void OnScrollInertiaCancel(int32_t device_id) override
Definition: flutter_windows_view.cc:337
flutter::FlutterWindowsView::ForceRedraw
void ForceRedraw()
Definition: flutter_windows_view.cc:187
flutter::FlutterWindowsView::OnPointerPanZoomStart
virtual void OnPointerPanZoomStart(int32_t device_id) override
Definition: flutter_windows_view.cc:278
flutter::TextInputPlugin::ComposeCommitHook
virtual void ComposeCommitHook()
Definition: text_input_plugin.cc:140
flutter::FlutterWindowsView::IsImplicitView
bool IsImplicitView() const
Definition: flutter_windows_view.cc:696
flutter::Rect
Definition: geometry.h:56
flutter::PhysicalWindowBounds::width
size_t width
Definition: window_binding_handler.h:28
flutter::PhysicalWindowBounds
Definition: window_binding_handler.h:27
flutter::PointerLocation
Definition: window_binding_handler.h:34
flutter::FlutterWindowsView::AnnounceAlert
void AnnounceAlert(const std::wstring &text)
Definition: flutter_windows_view.cc:769
flutter::FlutterWindowsView::GetWindowHandle
virtual HWND GetWindowHandle() const
Definition: flutter_windows_view.cc:761
flutter::FlutterWindowsView::OnPointerPanZoomUpdate
virtual void OnPointerPanZoomUpdate(int32_t device_id, double pan_x, double pan_y, double scale, double rotation) override
Definition: flutter_windows_view.cc:283
flutter::FlutterWindowsView::OnWindowRepaint
void OnWindowRepaint() override
Definition: flutter_windows_view.cc:232
flutter::WindowBindingHandlerDelegate::KeyEventCallback
std::function< void(bool)> KeyEventCallback
Definition: window_binding_handler_delegate.h:20
flutter::FlutterWindowsView::OnComposeEnd
void OnComposeEnd() override
Definition: flutter_windows_view.cc:317
flutter::PointerLocation::y
size_t y
Definition: window_binding_handler.h:36
flutter_windows_view.h
text
std::u16string text
Definition: keyboard_unittests.cc:332
flutter::FlutterWindowsEngine::SendWindowMetricsEvent
void SendWindowMetricsEvent(const FlutterWindowMetricsEvent &event)
Definition: flutter_windows_engine.cc:679
flutter::TextInputPlugin::TextHook
virtual void TextHook(const std::u16string &text)
Definition: text_input_plugin.cc:67
flutter::FlutterWindowsView::view_id
FlutterViewId view_id() const
Definition: flutter_windows_view.cc:692
flutter::KeyboardHandlerBase::SyncModifiersIfNeeded
virtual void SyncModifiersIfNeeded(int modifiers_state)=0
flutter::FlutterWindowsView::OnHighContrastChanged
void OnHighContrastChanged() override
Definition: flutter_windows_view.cc:757
flutter::FlutterWindowsView::OnWindowSizeChanged
bool OnWindowSizeChanged(size_t width, size_t height) override
Definition: flutter_windows_view.cc:194
flutter::FlutterViewId
int64_t FlutterViewId
Definition: flutter_view.h:13
flutter::FlutterWindowsView::OnFrameGenerated
bool OnFrameGenerated(size_t width, size_t height)
Definition: flutter_windows_view.cc:153
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::FlutterWindowsView::UpdateFlutterCursor
void UpdateFlutterCursor(const std::string &cursor_name)
Definition: flutter_windows_view.cc:179
flutter::FlutterWindowsView::SetFlutterCursor
void SetFlutterCursor(HCURSOR cursor)
Definition: flutter_windows_view.cc:183
flutter::FlutterWindowsView::OnPointerLeave
void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id=0) override
Definition: flutter_windows_view.cc:271
flutter::FlutterWindowsView::OnText
void OnText(const std::u16string &) override
Definition: flutter_windows_view.cc:295
flutter::FlutterWindowsEngine::keyboard_key_handler
KeyboardHandlerBase * keyboard_key_handler()
Definition: flutter_windows_engine.h:182
flutter::FlutterWindowsView::PresentSoftwareBitmap
virtual bool PresentSoftwareBitmap(const void *allocation, size_t row_bytes, size_t height)
Definition: flutter_windows_view.cc:685
flutter::FlutterWindowsView::OnCursorRectUpdated
virtual void OnCursorRectUpdated(const Rect &rect)
Definition: flutter_windows_view.cc:354
flutter::FlutterWindowsView::AlertNode
ui::AXPlatformNodeWin * AlertNode() const
Definition: flutter_windows_view.cc:790
flutter::FlutterWindowsView::GetEngine
FlutterWindowsEngine * GetEngine() const
Definition: flutter_windows_view.cc:765
flutter::FlutterWindowsEngine::text_input_plugin
TextInputPlugin * text_input_plugin()
Definition: flutter_windows_engine.h:185
flutter::FlutterWindowsView::OnPointerPanZoomEnd
virtual void OnPointerPanZoomEnd(int32_t device_id) override
Definition: flutter_windows_view.cc:291
flutter::FlutterWindowsView::OnDwmCompositionChanged
void OnDwmCompositionChanged()
Definition: flutter_windows_view.cc:811
flutter::FlutterWindowsView::NotifyWinEventWrapper
virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin *node, ax::mojom::Event event)
Definition: flutter_windows_view.cc:779
flutter::FlutterWindowsEngine::ScheduleFrame
void ScheduleFrame()
Definition: flutter_windows_engine.cc:759
flutter::FlutterWindowsEngine::UpdateHighContrastMode
void UpdateHighContrastMode()
Definition: flutter_windows_engine.cc:921
flutter::FlutterWindowsView::OnEmptyFrameGenerated
bool OnEmptyFrameGenerated()
Definition: flutter_windows_view.cc:131
flutter::FlutterWindowsView::ClearSoftwareBitmap
virtual bool ClearSoftwareBitmap()
Definition: flutter_windows_view.cc:681
flutter::PhysicalWindowBounds::height
size_t height
Definition: window_binding_handler.h:29
flutter::FlutterWindowsView::UpdateSemanticsEnabled
virtual void UpdateSemanticsEnabled(bool enabled)
Definition: flutter_windows_view.cc:799
flutter::FlutterWindowsView::OnComposeBegin
void OnComposeBegin() override
Definition: flutter_windows_view.cc:309
flutter::FlutterWindowsView::SendInitialBounds
void SendInitialBounds()
Definition: flutter_windows_view.cc:389
flutter::FlutterWindowsView::CreateAccessibilityBridge
virtual std::shared_ptr< AccessibilityBridgeWindows > CreateAccessibilityBridge()
Definition: flutter_windows_view.cc:795
action
int action
Definition: keyboard_key_handler_unittests.cc:116
flutter::FlutterWindowsView::OnScroll
void OnScroll(double x, double y, double delta_x, double delta_y, int scroll_offset_multiplier, FlutterPointerDeviceKind device_kind, int32_t device_id) override
Definition: flutter_windows_view.cc:326
flutter::FlutterWindowsEngine::UpdateSemanticsEnabled
void UpdateSemanticsEnabled(bool enabled)
Definition: flutter_windows_engine.cc:886
flutter::PointerLocation::x
size_t x
Definition: window_binding_handler.h:35
flutter::FlutterWindowsView::GetAxFragmentRootDelegate
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate() override
Definition: flutter_windows_view.cc:786
flutter::FlutterWindowsEngine::egl_manager
egl::Manager * egl_manager() const
Definition: flutter_windows_engine.h:165
key
int key
Definition: keyboard_key_handler_unittests.cc:114
accessibility_bridge.h
flutter::FlutterWindowsView::CreateWindowMetricsEvent
FlutterWindowMetricsEvent CreateWindowMetricsEvent() const
Definition: flutter_windows_view.cc:375
flutter::FlutterWindowsEngine::OnWindowStateEvent
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event)
Definition: flutter_windows_engine.cc:962
keyboard_key_channel_handler.h
flutter::FlutterWindowsView::OnKey
void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
Definition: flutter_windows_view.cc:299
flutter::KeyboardHandlerBase::KeyboardHook
virtual void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback)=0
flutter::FlutterWindowsView::GetNativeViewAccessible
virtual gfx::NativeViewAccessible GetNativeViewAccessible() override
Definition: flutter_windows_view.cc:346
flutter::FlutterWindowsView::OnResetImeComposing
virtual void OnResetImeComposing()
Definition: flutter_windows_view.cc:358
flutter::egl::Manager::CreateWindowSurface
virtual std::unique_ptr< WindowSurface > CreateWindowSurface(HWND hwnd, size_t width, size_t height)
Definition: manager.cc:239
flutter::FlutterWindowsView::OnFramePresented
virtual void OnFramePresented()
Definition: flutter_windows_view.cc:649
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52