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  [=, callback = std::move(callback)](bool handled) {
540  if (!handled) {
541  engine_->text_input_plugin()->KeyboardHook(
543  }
544  callback(handled);
545  });
546 }
547 
548 void FlutterWindowsView::SendComposeBegin() {
549  engine_->text_input_plugin()->ComposeBeginHook();
550 }
551 
552 void FlutterWindowsView::SendComposeCommit() {
553  engine_->text_input_plugin()->ComposeCommitHook();
554 }
555 
556 void FlutterWindowsView::SendComposeEnd() {
557  engine_->text_input_plugin()->ComposeEndHook();
558 }
559 
560 void FlutterWindowsView::SendComposeChange(const std::u16string& text,
561  int cursor_pos) {
562  engine_->text_input_plugin()->ComposeChangeHook(text, cursor_pos);
563 }
564 
565 void 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;
577  event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll;
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 
584 void 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 =
594  FlutterPointerSignalKind::kFlutterPointerSignalKindScrollInertiaCancel;
595  SetEventPhaseFromCursorButtonState(&event, state);
596  SendPointerEventWithData(event, state);
597 }
598 
599 void 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 = {};
607  event.phase = FlutterPointerPhase::kAdd;
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 
682 bool FlutterWindowsView::PresentSoftwareBitmap(const void* allocation,
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 
712 bool 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 =
731  engine_->egl_manager()->CreateWindowSurface(GetWindowHandle(), width,
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 
766 void 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();
773  NotifyWinEventWrapper(alert_node, ax::mojom::Event::kAlert);
774 }
775 
776 void FlutterWindowsView::NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
777  ax::mojom::Event event) {
778  if (node) {
779  node->NotifyAccessibilityEvent(event);
780  }
781 }
782 
783 ui::AXFragmentRootDelegateWin* FlutterWindowsView::GetAxFragmentRootDelegate() {
784  return accessibility_bridge_.get();
785 }
786 
787 ui::AXPlatformNodeWin* FlutterWindowsView::AlertNode() const {
788  return binding_handler_->GetAlert();
789 }
790 
791 std::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 
816 bool 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
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:812
flutter::FlutterWindowsView::CreateRenderSurface
void CreateRenderSurface()
Definition: flutter_windows_view.cc:697
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:685
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:750
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:693
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:766
flutter::FlutterWindowsView::GetWindowHandle
virtual HWND GetWindowHandle() const
Definition: flutter_windows_view.cc:758
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:678
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:689
flutter::KeyboardHandlerBase::SyncModifiersIfNeeded
virtual void SyncModifiersIfNeeded(int modifiers_state)=0
flutter::FlutterWindowsView::OnHighContrastChanged
void OnHighContrastChanged() override
Definition: flutter_windows_view.cc:754
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:682
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:787
flutter::FlutterWindowsView::GetEngine
FlutterWindowsEngine * GetEngine() const
Definition: flutter_windows_view.cc:762
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:808
flutter::FlutterWindowsView::NotifyWinEventWrapper
virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin *node, ax::mojom::Event event)
Definition: flutter_windows_view.cc:776
flutter::FlutterWindowsEngine::ScheduleFrame
void ScheduleFrame()
Definition: flutter_windows_engine.cc:758
flutter::FlutterWindowsEngine::UpdateHighContrastMode
void UpdateHighContrastMode()
Definition: flutter_windows_engine.cc:920
flutter::FlutterWindowsView::OnEmptyFrameGenerated
bool OnEmptyFrameGenerated()
Definition: flutter_windows_view.cc:131
flutter::FlutterWindowsView::ClearSoftwareBitmap
virtual bool ClearSoftwareBitmap()
Definition: flutter_windows_view.cc:678
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:796
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:792
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:885
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:783
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:961
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:266
flutter::FlutterWindowsView::OnFramePresented
virtual void OnFramePresented()
Definition: flutter_windows_view.cc:646
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52