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