| Flutter Windows Embedder |

flutter_window.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_window.h"
6
7 #include <WinUser.h>
8 #include <dwmapi.h>
9
10 #include <chrono>
11 #include <map>
12
13 #include "flutter/fml/logging.h"
14 #include "flutter/shell/platform/embedder/embedder.h"
15 #include "flutter/shell/platform/windows/dpi_utils.h"
16 #include "flutter/shell/platform/windows/flutter_windows_engine.h"
17 #include "flutter/shell/platform/windows/flutter_windows_view.h"
18 #include "flutter/shell/platform/windows/keyboard_utils.h"
19
20 namespace flutter {
21
22 namespace {
23
24 // The Windows DPI system is based on this
25 // constant for machines running at 100% scaling.
26 constexpr int base_dpi = 96;
27
28 static const int kMinTouchDeviceId = 0;
29 static const int kMaxTouchDeviceId = 128;
30
31 static const int kLinesPerScrollWindowsDefault = 3;
32
33 static constexpr int32_t kDefaultPointerDeviceId = 0;
34
35 // This method is only valid during a window message related to mouse/touch
36 // input.
37 // See
38 // https://docs.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages?redirectedfrom=MSDN#distinguishing-pen-input-from-mouse-and-touch.
39 static FlutterPointerDeviceKind GetFlutterPointerDeviceKind() {
40 constexpr LPARAM kTouchOrPenSignature = 0xFF515700;
41 constexpr LPARAM kTouchSignature = kTouchOrPenSignature | 0x80;
42 constexpr LPARAM kSignatureMask = 0xFFFFFF00;
43 LPARAM info = GetMessageExtraInfo();
44 if ((info & kSignatureMask) == kTouchOrPenSignature) {
45 if ((info & kTouchSignature) == kTouchSignature) {
46 return kFlutterPointerDeviceKindTouch;
47 }
48 return kFlutterPointerDeviceKindStylus;
49 }
50 return kFlutterPointerDeviceKindMouse;
51 }
52
53 // Translates button codes from Win32 API to FlutterPointerMouseButtons.
54 static uint64_t ConvertWinButtonToFlutterButton(UINT button) {
55 switch (button) {
56 case WM_LBUTTONDOWN:
57 case WM_LBUTTONUP:
58 return kFlutterPointerButtonMousePrimary;
59 case WM_RBUTTONDOWN:
60 case WM_RBUTTONUP:
61 return kFlutterPointerButtonMouseSecondary;
62 case WM_MBUTTONDOWN:
63 case WM_MBUTTONUP:
64 return kFlutterPointerButtonMouseMiddle;
65 case XBUTTON1:
66 return kFlutterPointerButtonMouseBack;
67 case XBUTTON2:
68 return kFlutterPointerButtonMouseForward;
69 }
70 FML_LOG(WARNING) << "Mouse button not recognized: " << button;
71 return 0;
72 }
73
74 } // namespace
75
76 FlutterWindow::FlutterWindow(
77 int width,
78 int height,
79 std::shared_ptr<WindowsProcTable> windows_proc_table,
80 std::unique_ptr<TextInputManager> text_input_manager)
81 : touch_id_generator_(kMinTouchDeviceId, kMaxTouchDeviceId),
82 windows_proc_table_(std::move(windows_proc_table)),
83 text_input_manager_(std::move(text_input_manager)),
84 ax_fragment_root_(nullptr) {
85 // Get the DPI of the primary monitor as the initial DPI. If Per-Monitor V2 is
86 // supported, |current_dpi_| should be updated in the
87 // kWmDpiChangedBeforeParent message.
88 current_dpi_ = GetDpiForHWND(nullptr);
89
90 // Get initial value for wheel scroll lines
91 // TODO: Listen to changes for this value
92 // https://github.com/flutter/flutter/issues/107248
93 UpdateScrollOffsetMultiplier();
94
95 if (windows_proc_table_ == nullptr) {
96 windows_proc_table_ = std::make_unique<WindowsProcTable>();
97 }
98 if (text_input_manager_ == nullptr) {
99 text_input_manager_ = std::make_unique<TextInputManager>();
100 }
101 keyboard_manager_ = std::make_unique<KeyboardManager>(this);
102
103 InitializeChild("FLUTTERVIEW", width, height);
104 }
105
106 // Base constructor for mocks
107 FlutterWindow::FlutterWindow()
108 : touch_id_generator_(kMinTouchDeviceId, kMaxTouchDeviceId) {}
109
110 FlutterWindow::~FlutterWindow() {
111 Destroy();
112 }
113
114 void FlutterWindow::SetView(WindowBindingHandlerDelegate* window) {
115 binding_handler_delegate_ = window;
116 if (direct_manipulation_owner_) {
117 direct_manipulation_owner_->SetBindingHandlerDelegate(window);
118 }
119 if (restored_ && window) {
120 OnWindowStateEvent(WindowStateEvent::kShow);
121 }
122 if (focused_ && window) {
123 OnWindowStateEvent(WindowStateEvent::kFocus);
124 }
125 }
126
127 float FlutterWindow::GetDpiScale() {
128 return static_cast<float>(GetCurrentDPI()) / static_cast<float>(base_dpi);
129 }
130
131 PhysicalWindowBounds FlutterWindow::GetPhysicalWindowBounds() {
132 return {GetCurrentWidth(), GetCurrentHeight()};
133 }
134
135 bool FlutterWindow::Focus() {
136 auto hwnd = GetWindowHandle();
137 if (hwnd == nullptr) {
138 return false;
139 }
140
141 HWND prevFocus = ::SetFocus(hwnd);
142 if (prevFocus == nullptr) {
143 return false;
144 }
145
146 return true;
147 }
148
149 void FlutterWindow::OnDpiScale(unsigned int dpi) {};
150
151 // When DesktopWindow notifies that a WM_Size message has come in
152 // lets FlutterEngine know about the new size.
153 void FlutterWindow::OnResize(unsigned int width, unsigned int height) {
154 if (binding_handler_delegate_ != nullptr) {
155 binding_handler_delegate_->OnWindowSizeChanged(width, height);
156 }
157 }
158
159 void FlutterWindow::OnPaint() {
160 if (binding_handler_delegate_ != nullptr) {
161 binding_handler_delegate_->OnWindowRepaint();
162 }
163 }
164
165 void FlutterWindow::OnPointerMove(double x,
166 double y,
167 FlutterPointerDeviceKind device_kind,
168 int32_t device_id,
169 int modifiers_state) {
170 binding_handler_delegate_->OnPointerMove(x, y, device_kind, device_id,
171 modifiers_state);
172 }
173
174 void FlutterWindow::OnPointerDown(double x,
175 double y,
176 FlutterPointerDeviceKind device_kind,
177 int32_t device_id,
178 UINT button) {
179 uint64_t flutter_button = ConvertWinButtonToFlutterButton(button);
180 if (flutter_button != 0) {
181 binding_handler_delegate_->OnPointerDown(
182 x, y, device_kind, device_id,
183 static_cast<FlutterPointerMouseButtons>(flutter_button));
184 }
185 }
186
187 void FlutterWindow::OnPointerUp(double x,
188 double y,
189 FlutterPointerDeviceKind device_kind,
190 int32_t device_id,
191 UINT button) {
192 uint64_t flutter_button = ConvertWinButtonToFlutterButton(button);
193 if (flutter_button != 0) {
194 binding_handler_delegate_->OnPointerUp(
195 x, y, device_kind, device_id,
196 static_cast<FlutterPointerMouseButtons>(flutter_button));
197 }
198 }
199
200 void FlutterWindow::OnPointerLeave(double x,
201 double y,
202 FlutterPointerDeviceKind device_kind,
203 int32_t device_id) {
204 binding_handler_delegate_->OnPointerLeave(x, y, device_kind, device_id);
205 }
206
207 void FlutterWindow::OnText(const std::u16string& text) {
208 binding_handler_delegate_->OnText(text);
209 }
210
211 void FlutterWindow::OnKey(int key,
212 int scancode,
213 int action,
214 char32_t character,
215 bool extended,
216 bool was_down,
217 KeyEventCallback callback) {
218 binding_handler_delegate_->OnKey(key, scancode, action, character, extended,
219 was_down, std::move(callback));
220 }
221
222 void FlutterWindow::OnComposeBegin() {
223 binding_handler_delegate_->OnComposeBegin();
224 }
225
226 void FlutterWindow::OnComposeCommit() {
227 binding_handler_delegate_->OnComposeCommit();
228 }
229
230 void FlutterWindow::OnComposeEnd() {
231 binding_handler_delegate_->OnComposeEnd();
232 }
233
234 void FlutterWindow::OnComposeChange(const std::u16string& text,
235 int cursor_pos) {
236 binding_handler_delegate_->OnComposeChange(text, cursor_pos);
237 }
238
239 void FlutterWindow::OnUpdateSemanticsEnabled(bool enabled) {
240 binding_handler_delegate_->OnUpdateSemanticsEnabled(enabled);
241 }
242
243 void FlutterWindow::OnScroll(double delta_x,
244 double delta_y,
245 FlutterPointerDeviceKind device_kind,
246 int32_t device_id) {
247 POINT point;
248 GetCursorPos(&point);
249
250 ScreenToClient(GetWindowHandle(), &point);
251 binding_handler_delegate_->OnScroll(point.x, point.y, delta_x, delta_y,
252 GetScrollOffsetMultiplier(), device_kind,
253 device_id);
254 }
255
256 void FlutterWindow::OnCursorRectUpdated(const Rect& rect) {
257 // Convert the rect from Flutter logical coordinates to device coordinates.
258 auto scale = GetDpiScale();
259 Point origin(rect.left() * scale, rect.top() * scale);
260 Size size(rect.width() * scale, rect.height() * scale);
261 UpdateCursorRect(Rect(origin, size));
262 }
263
264 void FlutterWindow::OnResetImeComposing() {
265 AbortImeComposing();
266 }
267
268 bool FlutterWindow::OnBitmapSurfaceCleared() {
269 HDC dc = ::GetDC(GetWindowHandle());
270 bool result = ::PatBlt(dc, 0, 0, current_width_, current_height_, BLACKNESS);
271 ::ReleaseDC(GetWindowHandle(), dc);
272 return result;
273 }
274
275 bool FlutterWindow::OnBitmapSurfaceUpdated(const void* allocation,
276 size_t row_bytes,
277 size_t height) {
278 HDC dc = ::GetDC(GetWindowHandle());
279 BITMAPINFO bmi = {};
280 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
281 bmi.bmiHeader.biWidth = row_bytes / 4;
282 bmi.bmiHeader.biHeight = -height;
283 bmi.bmiHeader.biPlanes = 1;
284 bmi.bmiHeader.biBitCount = 32;
285 bmi.bmiHeader.biCompression = BI_RGB;
286 bmi.bmiHeader.biSizeImage = 0;
287 int ret = ::SetDIBitsToDevice(dc, 0, 0, row_bytes / 4, height, 0, 0, 0,
288 height, allocation, &bmi, DIB_RGB_COLORS);
289 ::ReleaseDC(GetWindowHandle(), dc);
290 return ret != 0;
291 }
292
293 gfx::NativeViewAccessible FlutterWindow::GetNativeViewAccessible() {
294 if (binding_handler_delegate_ == nullptr) {
295 return nullptr;
296 }
297
298 return binding_handler_delegate_->GetNativeViewAccessible();
299 }
300
301 PointerLocation FlutterWindow::GetPrimaryPointerLocation() {
302 POINT point;
303 GetCursorPos(&point);
304 ScreenToClient(GetWindowHandle(), &point);
305 return {(size_t)point.x, (size_t)point.y};
306 }
307
308 void FlutterWindow::OnThemeChange() {
309 binding_handler_delegate_->OnHighContrastChanged();
310 }
311
312 ui::AXFragmentRootDelegateWin* FlutterWindow::GetAxFragmentRootDelegate() {
313 return binding_handler_delegate_->GetAxFragmentRootDelegate();
314 }
315
316 AlertPlatformNodeDelegate* FlutterWindow::GetAlertDelegate() {
317 CreateAxFragmentRoot();
318 return alert_delegate_.get();
319 }
320
321 ui::AXPlatformNodeWin* FlutterWindow::GetAlert() {
322 CreateAxFragmentRoot();
323 return alert_node_.get();
324 }
325
326 void FlutterWindow::OnWindowStateEvent(WindowStateEvent event) {
327 switch (event) {
328 case WindowStateEvent::kShow:
329 restored_ = true;
330 break;
331 case WindowStateEvent::kHide:
332 restored_ = false;
333 focused_ = false;
334 break;
335 case WindowStateEvent::kFocus:
336 focused_ = true;
337 if (binding_handler_delegate_) {
338 binding_handler_delegate_->OnFocus(
339 FlutterViewFocusState::kFocused,
340 FlutterViewFocusDirection::kUndefined);
341 }
342 break;
343 case WindowStateEvent::kUnfocus:
344 focused_ = false;
345 if (binding_handler_delegate_) {
346 binding_handler_delegate_->OnFocus(
347 FlutterViewFocusState::kUnfocused,
348 FlutterViewFocusDirection::kUndefined);
349 }
350 break;
351 }
352 HWND hwnd = GetWindowHandle();
353 if (hwnd && binding_handler_delegate_) {
354 binding_handler_delegate_->OnWindowStateEvent(hwnd, event);
355 }
356 }
357
358 void FlutterWindow::TrackMouseLeaveEvent(HWND hwnd) {
359 if (!tracking_mouse_leave_) {
360 TRACKMOUSEEVENT tme;
361 tme.cbSize = sizeof(tme);
362 tme.hwndTrack = hwnd;
363 tme.dwFlags = TME_LEAVE;
364 TrackMouseEvent(&tme);
365 tracking_mouse_leave_ = true;
366 }
367 }
368
369 void FlutterWindow::HandleResize(UINT width, UINT height) {
370 current_width_ = width;
371 current_height_ = height;
372 if (direct_manipulation_owner_) {
373 direct_manipulation_owner_->ResizeViewport(width, height);
374 }
375 OnResize(width, height);
376 }
377
378 FlutterWindow* FlutterWindow::GetThisFromHandle(HWND const window) noexcept {
379 return reinterpret_cast<FlutterWindow*>(
380 GetWindowLongPtr(window, GWLP_USERDATA));
381 }
382
383 void FlutterWindow::UpdateScrollOffsetMultiplier() {
384 UINT lines_per_scroll = kLinesPerScrollWindowsDefault;
385
386 // Get lines per scroll wheel value from Windows
387 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines_per_scroll, 0);
388
389 // This logic is based off Chromium's implementation
390 // https://source.chromium.org/chromium/chromium/src/+/main:ui/events/blink/web_input_event_builders_win.cc;l=319-331
391 scroll_offset_multiplier_ =
392 static_cast<float>(lines_per_scroll) * 100.0 / 3.0;
393 }
394
395 void FlutterWindow::InitializeChild(const char* title,
396 unsigned int width,
397 unsigned int height) {
398 Destroy();
399 std::wstring converted_title = NarrowToWide(title);
400
401 WNDCLASS window_class = RegisterWindowClass(converted_title);
402
403 auto* result = CreateWindowEx(
404 0, window_class.lpszClassName, converted_title.c_str(),
405 WS_CHILD | WS_VISIBLE, CW_DEFAULT, CW_DEFAULT, width, height,
406 HWND_MESSAGE, nullptr, window_class.hInstance, this);
407
408 if (result == nullptr) {
409 auto error = GetLastError();
410 LPWSTR message = nullptr;
411 size_t size = FormatMessageW(
412 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
413 FORMAT_MESSAGE_IGNORE_INSERTS,
414 NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
415 reinterpret_cast<LPWSTR>(&message), 0, NULL);
416 OutputDebugString(message);
417 LocalFree(message);
418 }
419 SetUserObjectInformationA(GetCurrentProcess(),
420 UOI_TIMERPROC_EXCEPTION_SUPPRESSION, FALSE, 1);
421 // SetTimer is not precise, if a 16 ms interval is requested, it will instead
422 // often fire in an interval of 32 ms. Providing a value of 14 will ensure it
423 // runs every 16 ms, which will allow for 60 Hz trackpad gesture events, which
424 // is the maximal frequency supported by SetTimer.
425 SetTimer(result, kDirectManipulationTimer, 14, nullptr);
426 direct_manipulation_owner_ = std::make_unique<DirectManipulationOwner>(this);
427 direct_manipulation_owner_->Init(width, height);
428 }
429
430 HWND FlutterWindow::GetWindowHandle() {
431 return window_handle_;
432 }
433
434 BOOL FlutterWindow::Win32PeekMessage(LPMSG lpMsg,
435 UINT wMsgFilterMin,
436 UINT wMsgFilterMax,
437 UINT wRemoveMsg) {
438 return ::PeekMessage(lpMsg, window_handle_, wMsgFilterMin, wMsgFilterMax,
439 wRemoveMsg);
440 }
441
442 uint32_t FlutterWindow::Win32MapVkToChar(uint32_t virtual_key) {
443 return ::MapVirtualKey(virtual_key, MAPVK_VK_TO_CHAR);
444 }
445
446 UINT FlutterWindow::Win32DispatchMessage(UINT Msg,
447 WPARAM wParam,
448 LPARAM lParam) {
449 return ::SendMessage(window_handle_, Msg, wParam, lParam);
450 }
451
452 std::wstring FlutterWindow::NarrowToWide(const char* source) {
453 size_t length = strlen(source);
454 size_t outlen = 0;
455 std::wstring wideTitle(length, L'#');
456 mbstowcs_s(&outlen, &wideTitle[0], length + 1, source, length);
457 return wideTitle;
458 }
459
460 WNDCLASS FlutterWindow::RegisterWindowClass(std::wstring& title) {
461 window_class_name_ = title;
462
463 WNDCLASS window_class{};
464 window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
465 window_class.lpszClassName = title.c_str();
466 window_class.style = CS_HREDRAW | CS_VREDRAW;
467 window_class.cbClsExtra = 0;
468 window_class.cbWndExtra = 0;
469 window_class.hInstance = GetModuleHandle(nullptr);
470 window_class.hIcon = nullptr;
471 window_class.hbrBackground = 0;
472 window_class.lpszMenuName = nullptr;
473 window_class.lpfnWndProc = WndProc;
474 RegisterClass(&window_class);
475 return window_class;
476 }
477
478 LRESULT CALLBACK FlutterWindow::WndProc(HWND const window,
479 UINT const message,
480 WPARAM const wparam,
481 LPARAM const lparam) noexcept {
482 if (message == WM_NCCREATE) {
483 auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
484 SetWindowLongPtr(window, GWLP_USERDATA,
485 reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
486
487 auto that = static_cast<FlutterWindow*>(cs->lpCreateParams);
488 that->window_handle_ = window;
489 that->text_input_manager_->SetWindowHandle(window);
490 RegisterTouchWindow(window, 0);
491 } else if (FlutterWindow* that = GetThisFromHandle(window)) {
492 return that->HandleMessage(message, wparam, lparam);
493 }
494
495 return DefWindowProc(window, message, wparam, lparam);
496 }
497
498 LRESULT
499 FlutterWindow::HandleMessage(UINT const message,
500 WPARAM const wparam,
501 LPARAM const lparam) noexcept {
502 LPARAM result_lparam = lparam;
503 int xPos = 0, yPos = 0;
504 UINT width = 0, height = 0;
505 UINT button_pressed = 0;
506 FlutterPointerDeviceKind device_kind;
507
508 switch (message) {
509 case kWmDpiChangedBeforeParent:
510 current_dpi_ = GetDpiForHWND(window_handle_);
511 OnDpiScale(current_dpi_);
512 return 0;
513 case WM_SIZE:
514 width = LOWORD(lparam);
515 height = HIWORD(lparam);
516
517 current_width_ = width;
518 current_height_ = height;
519 HandleResize(width, height);
520
521 OnWindowStateEvent(width == 0 && height == 0 ? WindowStateEvent::kHide
522 : WindowStateEvent::kShow);
523 break;
524 case WM_PAINT:
525 OnPaint();
526 break;
527 case WM_TOUCH: {
528 UINT num_points = LOWORD(wparam);
529 touch_points_.resize(num_points);
530 auto touch_input_handle = reinterpret_cast<HTOUCHINPUT>(lparam);
531 if (GetTouchInputInfo(touch_input_handle, num_points,
532 touch_points_.data(), sizeof(TOUCHINPUT))) {
533 for (const auto& touch : touch_points_) {
534 // Generate a mapped ID for the Windows-provided touch ID
535 auto touch_id = touch_id_generator_.GetGeneratedId(touch.dwID);
536
537 POINT pt = {TOUCH_COORD_TO_PIXEL(touch.x),
538 TOUCH_COORD_TO_PIXEL(touch.y)};
539 ScreenToClient(window_handle_, &pt);
540 auto x = static_cast<double>(pt.x);
541 auto y = static_cast<double>(pt.y);
542
543 if (touch.dwFlags & TOUCHEVENTF_DOWN) {
544 OnPointerDown(x, y, kFlutterPointerDeviceKindTouch, touch_id,
545 WM_LBUTTONDOWN);
546 } else if (touch.dwFlags & TOUCHEVENTF_MOVE) {
547 OnPointerMove(x, y, kFlutterPointerDeviceKindTouch, touch_id, 0);
548 } else if (touch.dwFlags & TOUCHEVENTF_UP) {
549 OnPointerUp(x, y, kFlutterPointerDeviceKindTouch, touch_id,
550 WM_LBUTTONDOWN);
551 OnPointerLeave(x, y, kFlutterPointerDeviceKindTouch, touch_id);
552 touch_id_generator_.ReleaseNumber(touch.dwID);
553 }
554 }
555 CloseTouchInputHandle(touch_input_handle);
556 }
557 return 0;
558 }
559 case WM_MOUSEMOVE:
560 device_kind = GetFlutterPointerDeviceKind();
561 if (device_kind == kFlutterPointerDeviceKindMouse) {
562 TrackMouseLeaveEvent(window_handle_);
563
564 xPos = GET_X_LPARAM(lparam);
565 yPos = GET_Y_LPARAM(lparam);
566 mouse_x_ = static_cast<double>(xPos);
567 mouse_y_ = static_cast<double>(yPos);
568
569 int mods = 0;
570 if (wparam & MK_CONTROL) {
571 mods |= kControl;
572 }
573 if (wparam & MK_SHIFT) {
574 mods |= kShift;
575 }
576 OnPointerMove(mouse_x_, mouse_y_, device_kind, kDefaultPointerDeviceId,
577 mods);
578 }
579 break;
580 case WM_MOUSELEAVE:
581 device_kind = GetFlutterPointerDeviceKind();
582 if (device_kind == kFlutterPointerDeviceKindMouse) {
583 OnPointerLeave(mouse_x_, mouse_y_, device_kind,
584 kDefaultPointerDeviceId);
585 }
586
587 // Once the tracked event is received, the TrackMouseEvent function
588 // resets. Set to false to make sure it's called once mouse movement is
589 // detected again.
590 tracking_mouse_leave_ = false;
591 break;
592 case WM_SETCURSOR: {
593 UINT hit_test_result = LOWORD(lparam);
594 if (hit_test_result == HTCLIENT) {
595 // Halt further processing to prevent DefWindowProc from setting the
596 // cursor back to the registered class cursor.
597 return TRUE;
598 }
599 break;
600 }
601 case WM_SETFOCUS:
602 OnWindowStateEvent(WindowStateEvent::kFocus);
603 ::CreateCaret(window_handle_, nullptr, 1, 1);
604 break;
605 case WM_KILLFOCUS:
606 OnWindowStateEvent(WindowStateEvent::kUnfocus);
607 ::DestroyCaret();
608 break;
609 case WM_LBUTTONDOWN:
610 case WM_RBUTTONDOWN:
611 case WM_MBUTTONDOWN:
612 case WM_XBUTTONDOWN:
613 device_kind = GetFlutterPointerDeviceKind();
614 if (device_kind != kFlutterPointerDeviceKindMouse) {
615 break;
616 }
617
618 if (message == WM_LBUTTONDOWN) {
619 // Capture the pointer in case the user drags outside the client area.
620 // In this case, the "mouse leave" event is delayed until the user
621 // releases the button. It's only activated on left click given that
622 // it's more common for apps to handle dragging with only the left
623 // button.
624 SetCapture(window_handle_);
625 }
626 button_pressed = message;
627 if (message == WM_XBUTTONDOWN) {
628 button_pressed = GET_XBUTTON_WPARAM(wparam);
629 }
630 xPos = GET_X_LPARAM(lparam);
631 yPos = GET_Y_LPARAM(lparam);
632 OnPointerDown(static_cast<double>(xPos), static_cast<double>(yPos),
633 device_kind, kDefaultPointerDeviceId, button_pressed);
634 break;
635 case WM_LBUTTONUP:
636 case WM_RBUTTONUP:
637 case WM_MBUTTONUP:
638 case WM_XBUTTONUP:
639 device_kind = GetFlutterPointerDeviceKind();
640 if (device_kind != kFlutterPointerDeviceKindMouse) {
641 break;
642 }
643
644 if (message == WM_LBUTTONUP) {
645 ReleaseCapture();
646 }
647 button_pressed = message;
648 if (message == WM_XBUTTONUP) {
649 button_pressed = GET_XBUTTON_WPARAM(wparam);
650 }
651 xPos = GET_X_LPARAM(lparam);
652 yPos = GET_Y_LPARAM(lparam);
653 OnPointerUp(static_cast<double>(xPos), static_cast<double>(yPos),
654 device_kind, kDefaultPointerDeviceId, button_pressed);
655 break;
656 case WM_MOUSEWHEEL:
657 OnScroll(0.0,
658 -(static_cast<short>(HIWORD(wparam)) /
659 static_cast<double>(WHEEL_DELTA)),
660 kFlutterPointerDeviceKindMouse, kDefaultPointerDeviceId);
661 break;
662 case WM_MOUSEHWHEEL:
663 OnScroll((static_cast<short>(HIWORD(wparam)) /
664 static_cast<double>(WHEEL_DELTA)),
665 0.0, kFlutterPointerDeviceKindMouse, kDefaultPointerDeviceId);
666 break;
667 case WM_GETOBJECT: {
668 LRESULT lresult = OnGetObject(message, wparam, lparam);
669 if (lresult) {
670 return lresult;
671 }
672 break;
673 }
674 case WM_TIMER:
675 if (wparam == kDirectManipulationTimer) {
676 direct_manipulation_owner_->Update();
677 return 0;
678 }
679 break;
680 case DM_POINTERHITTEST: {
681 if (direct_manipulation_owner_) {
682 UINT contact_id = GET_POINTERID_WPARAM(wparam);
683 POINTER_INPUT_TYPE pointer_type;
684 if (windows_proc_table_->GetPointerType(contact_id, &pointer_type) &&
685 pointer_type == PT_TOUCHPAD) {
686 direct_manipulation_owner_->SetContact(contact_id);
687 }
688 }
689 break;
690 }
691 case WM_INPUTLANGCHANGE:
692 // TODO(cbracken): pass this to TextInputManager to aid with
693 // language-specific issues.
694 break;
695 case WM_IME_SETCONTEXT:
696 OnImeSetContext(message, wparam, lparam);
697 // Strip the ISC_SHOWUICOMPOSITIONWINDOW bit from lparam before passing it
698 // to DefWindowProc() so that the composition window is hidden since
699 // Flutter renders the composing string itself.
700 result_lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
701 break;
702 case WM_IME_STARTCOMPOSITION:
703 OnImeStartComposition(message, wparam, lparam);
704 // Suppress further processing by DefWindowProc() so that the default
705 // system IME style isn't used, but rather the one set in the
706 // WM_IME_SETCONTEXT handler.
707 return TRUE;
708 case WM_IME_COMPOSITION:
709 OnImeComposition(message, wparam, lparam);
710 if (lparam & GCS_RESULTSTR || lparam & GCS_COMPSTR) {
711 // Suppress further processing by DefWindowProc() since otherwise it
712 // will emit the result string as WM_CHAR messages on commit. Instead,
713 // committing the composing text to the EditableText string is handled
714 // in TextInputModel::CommitComposing, triggered by
715 // OnImeEndComposition().
716 return TRUE;
717 }
718 break;
719 case WM_IME_ENDCOMPOSITION:
720 OnImeEndComposition(message, wparam, lparam);
721 return TRUE;
722 case WM_IME_REQUEST:
723 OnImeRequest(message, wparam, lparam);
724 break;
725 case WM_UNICHAR: {
726 // Tell third-pary app, we can support Unicode.
727 if (wparam == UNICODE_NOCHAR)
728 return TRUE;
729 // DefWindowProc will send WM_CHAR for this WM_UNICHAR.
730 break;
731 }
732 case WM_THEMECHANGED:
733 OnThemeChange();
734 break;
735 case WM_DEADCHAR:
736 case WM_SYSDEADCHAR:
737 case WM_CHAR:
738 case WM_SYSCHAR:
739 case WM_KEYDOWN:
740 case WM_SYSKEYDOWN:
741 case WM_KEYUP:
742 case WM_SYSKEYUP:
743 if (keyboard_manager_->HandleMessage(message, wparam, lparam)) {
744 return 0;
745 }
746 break;
747 }
748
749 return Win32DefWindowProc(window_handle_, message, wparam, result_lparam);
750 }
751
752 LRESULT FlutterWindow::OnGetObject(UINT const message,
753 WPARAM const wparam,
754 LPARAM const lparam) {
755 LRESULT reference_result = static_cast<LRESULT>(0L);
756
757 // Only the lower 32 bits of lparam are valid when checking the object id
758 // because it sometimes gets sign-extended incorrectly (but not always).
759 DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(lparam));
760
761 bool is_uia_request = static_cast<DWORD>(UiaRootObjectId) == obj_id;
762 bool is_msaa_request = static_cast<DWORD>(OBJID_CLIENT) == obj_id;
763
764 if (is_uia_request || is_msaa_request) {
765 // On Windows, we don't get a notification that the screen reader has been
766 // enabled or disabled. There is an API to query for screen reader state,
767 // but that state isn't set by all screen readers, including by Narrator,
768 // the screen reader that ships with Windows:
769 // https://docs.microsoft.com/en-us/windows/win32/winauto/screen-reader-parameter
770 //
771 // Instead, we enable semantics in Flutter if Windows issues queries for
772 // Microsoft Active Accessibility (MSAA) COM objects.
773 OnUpdateSemanticsEnabled(true);
774 }
775
776 gfx::NativeViewAccessible root_view = GetNativeViewAccessible();
777 // TODO(schectman): UIA is currently disabled by default.
778 // https://github.com/flutter/flutter/issues/114547
779 if (root_view) {
780 CreateAxFragmentRoot();
781 if (is_uia_request) {
782 #ifdef FLUTTER_ENGINE_USE_UIA
783 // Retrieve UIA object for the root view.
784 Microsoft::WRL::ComPtr<IRawElementProviderSimple> root;
785 if (SUCCEEDED(
786 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
787 IID_PPV_ARGS(&root)))) {
788 // Return the UIA object via UiaReturnRawElementProvider(). See:
789 // https://docs.microsoft.com/en-us/windows/win32/winauto/wm-getobject
790 reference_result = UiaReturnRawElementProvider(window_handle_, wparam,
791 lparam, root.Get());
792 } else {
793 FML_LOG(ERROR) << "Failed to query AX fragment root.";
794 }
795 #endif // FLUTTER_ENGINE_USE_UIA
796 } else if (is_msaa_request) {
797 // Create the accessibility root if it does not already exist.
798 // Return the IAccessible for the root view.
799 Microsoft::WRL::ComPtr<IAccessible> root;
800 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
801 IID_PPV_ARGS(&root));
802 reference_result = LresultFromObject(IID_IAccessible, wparam, root.Get());
803 }
804 }
805 return reference_result;
806 }
807
808 void FlutterWindow::OnImeSetContext(UINT const message,
809 WPARAM const wparam,
810 LPARAM const lparam) {
811 if (wparam != 0) {
812 text_input_manager_->CreateImeWindow();
813 }
814 }
815
816 void FlutterWindow::OnImeStartComposition(UINT const message,
817 WPARAM const wparam,
818 LPARAM const lparam) {
819 text_input_manager_->CreateImeWindow();
820 OnComposeBegin();
821 }
822
823 void FlutterWindow::OnImeComposition(UINT const message,
824 WPARAM const wparam,
825 LPARAM const lparam) {
826 // Update the IME window position.
827 text_input_manager_->UpdateImeWindow();
828
829 if (lparam == 0) {
830 OnComposeChange(u"", 0);
831 OnComposeCommit();
832 }
833
834 // Process GCS_RESULTSTR at fisrt, because Google Japanese Input and ATOK send
835 // both GCS_RESULTSTR and GCS_COMPSTR to commit composed text and send new
836 // composing text.
837 if (lparam & GCS_RESULTSTR) {
838 // Commit but don't end composing.
839 // Read the committed composing string.
840 long pos = text_input_manager_->GetComposingCursorPosition();
841 std::optional<std::u16string> text = text_input_manager_->GetResultString();
842 if (text) {
843 OnComposeChange(text.value(), pos);
844 OnComposeCommit();
845 }
846 }
847 if (lparam & GCS_COMPSTR) {
848 // Read the in-progress composing string.
849 long pos = text_input_manager_->GetComposingCursorPosition();
850 std::optional<std::u16string> text =
851 text_input_manager_->GetComposingString();
852 if (text) {
853 OnComposeChange(text.value(), pos);
854 }
855 }
856 }
857
858 void FlutterWindow::OnImeEndComposition(UINT const message,
859 WPARAM const wparam,
860 LPARAM const lparam) {
861 text_input_manager_->DestroyImeWindow();
862 OnComposeEnd();
863 }
864
865 void FlutterWindow::OnImeRequest(UINT const message,
866 WPARAM const wparam,
867 LPARAM const lparam) {
868 // TODO(cbracken): Handle IMR_RECONVERTSTRING, IMR_DOCUMENTFEED,
869 // and IMR_QUERYCHARPOSITION messages.
870 // https://github.com/flutter/flutter/issues/74547
871 }
872
873 void FlutterWindow::AbortImeComposing() {
874 text_input_manager_->AbortComposing();
875 }
876
877 void FlutterWindow::UpdateCursorRect(const Rect& rect) {
878 text_input_manager_->UpdateCaretRect(rect);
879 }
880
881 UINT FlutterWindow::GetCurrentDPI() {
882 return current_dpi_;
883 }
884
885 UINT FlutterWindow::GetCurrentWidth() {
886 return current_width_;
887 }
888
889 UINT FlutterWindow::GetCurrentHeight() {
890 return current_height_;
891 }
892
893 float FlutterWindow::GetScrollOffsetMultiplier() {
894 return scroll_offset_multiplier_;
895 }
896
897 LRESULT FlutterWindow::Win32DefWindowProc(HWND hWnd,
898 UINT Msg,
899 WPARAM wParam,
900 LPARAM lParam) {
901 return ::DefWindowProc(hWnd, Msg, wParam, lParam);
902 }
903
904 void FlutterWindow::Destroy() {
905 if (window_handle_) {
906 text_input_manager_->SetWindowHandle(nullptr);
907 DestroyWindow(window_handle_);
908 window_handle_ = nullptr;
909 }
910
911 UnregisterClass(window_class_name_.c_str(), nullptr);
912 }
913
914 void FlutterWindow::CreateAxFragmentRoot() {
915 if (ax_fragment_root_) {
916 return;
917 }
918 ax_fragment_root_ = std::make_unique<ui::AXFragmentRootWin>(
919 window_handle_, GetAxFragmentRootDelegate());
920 alert_delegate_ =
921 std::make_unique<AlertPlatformNodeDelegate>(*ax_fragment_root_);
922 ui::AXPlatformNode* alert_node =
923 ui::AXPlatformNodeWin::Create(alert_delegate_.get());
924 alert_node_.reset(static_cast<ui::AXPlatformNodeWin*>(alert_node));
925 ax_fragment_root_->SetAlertNode(alert_node_.get());
926 }
927
928 } // namespace flutter
flutter::AlertPlatformNodeDelegate
Definition: alert_platform_node_delegate.h:18
flutter::FlutterWindow::OnCursorRectUpdated
virtual void OnCursorRectUpdated(const Rect &rect) override
Definition: flutter_window.cc:256
flutter::FlutterWindow::OnPointerLeave
virtual void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id)
Definition: flutter_window.cc:200
flutter::FlutterWindow::FlutterWindow
FlutterWindow()
Definition: flutter_window.cc:107
flutter::FlutterWindow::GetScrollOffsetMultiplier
virtual float GetScrollOffsetMultiplier()
Definition: flutter_window.cc:893
flutter::FlutterWindow::Focus
virtual bool Focus() override
Definition: flutter_window.cc:135
flutter::FlutterWindow::GetAlert
virtual ui::AXPlatformNodeWin * GetAlert() override
Definition: flutter_window.cc:321
flutter::FlutterWindow::OnText
virtual void OnText(const std::u16string &text) override
Definition: flutter_window.cc:207
flutter::FlutterWindow::Win32DispatchMessage
virtual UINT Win32DispatchMessage(UINT Msg, WPARAM wParam, LPARAM lParam) override
Definition: flutter_window.cc:446
flutter::FlutterWindow::Win32PeekMessage
virtual BOOL Win32PeekMessage(LPMSG lpMsg, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) override
Definition: flutter_window.cc:434
flutter::FlutterWindow::OnThemeChange
virtual void OnThemeChange()
Definition: flutter_window.cc:308
flutter::FlutterWindow::alert_delegate_
std::unique_ptr< AlertPlatformNodeDelegate > alert_delegate_
Definition: flutter_window.h:268
flutter::FlutterWindow::OnBitmapSurfaceUpdated
virtual bool OnBitmapSurfaceUpdated(const void *allocation, size_t row_bytes, size_t height) override
Definition: flutter_window.cc:275
flutter::FlutterWindow::OnImeRequest
virtual void OnImeRequest(UINT const message, WPARAM const wparam, LPARAM const lparam)
Definition: flutter_window.cc:865
flutter::FlutterWindow::Win32DefWindowProc
virtual LRESULT Win32DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: flutter_window.cc:897
flutter::FlutterWindow::OnImeStartComposition
virtual void OnImeStartComposition(UINT const message, WPARAM const wparam, LPARAM const lparam)
Definition: flutter_window.cc:816
flutter::FlutterWindow::NarrowToWide
std::wstring NarrowToWide(const char *source)
Definition: flutter_window.cc:452
flutter::FlutterWindow::GetAxFragmentRootDelegate
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate()
Definition: flutter_window.cc:312
flutter::FlutterWindow::OnScroll
virtual void OnScroll(double delta_x, double delta_y, FlutterPointerDeviceKind device_kind, int32_t device_id)
Definition: flutter_window.cc:243
flutter::FlutterWindow::OnPointerUp
virtual void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, UINT button)
Definition: flutter_window.cc:187
flutter::FlutterWindow::InitializeChild
void InitializeChild(const char *title, unsigned int width, unsigned int height)
Definition: flutter_window.cc:395
flutter::FlutterWindow::OnPaint
virtual void OnPaint()
Definition: flutter_window.cc:159
flutter::FlutterWindow::GetAlertDelegate
virtual AlertPlatformNodeDelegate * GetAlertDelegate() override
Definition: flutter_window.cc:316
flutter::FlutterWindow::direct_manipulation_owner_
std::unique_ptr< DirectManipulationOwner > direct_manipulation_owner_
Definition: flutter_window.h:275
flutter::FlutterWindow::GetWindowHandle
virtual HWND GetWindowHandle() override
Definition: flutter_window.cc:430
flutter::FlutterWindow::OnPointerDown
virtual void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, UINT button)
Definition: flutter_window.cc:174
flutter::FlutterWindow::GetCurrentWidth
UINT GetCurrentWidth()
Definition: flutter_window.cc:885
flutter::FlutterWindow::OnComposeCommit
virtual void OnComposeCommit()
Definition: flutter_window.cc:226
flutter::FlutterWindow::UpdateCursorRect
virtual void UpdateCursorRect(const Rect &rect)
Definition: flutter_window.cc:877
flutter::FlutterWindow::GetPhysicalWindowBounds
virtual PhysicalWindowBounds GetPhysicalWindowBounds() override
Definition: flutter_window.cc:131
flutter::FlutterWindow::OnImeSetContext
virtual void OnImeSetContext(UINT const message, WPARAM const wparam, LPARAM const lparam)
Definition: flutter_window.cc:808
flutter::FlutterWindow::OnWindowStateEvent
virtual void OnWindowStateEvent(WindowStateEvent event)
Definition: flutter_window.cc:326
flutter::FlutterWindow::OnKey
virtual void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
Definition: flutter_window.cc:211
flutter::FlutterWindow::OnPointerMove
virtual void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state)
Definition: flutter_window.cc:165
flutter::FlutterWindow::alert_node_
std::unique_ptr< ui::AXPlatformNodeWin > alert_node_
Definition: flutter_window.h:271
flutter::FlutterWindow::GetPrimaryPointerLocation
virtual PointerLocation GetPrimaryPointerLocation() override
Definition: flutter_window.cc:301
flutter::FlutterWindow::GetCurrentHeight
UINT GetCurrentHeight()
Definition: flutter_window.cc:889
flutter::FlutterWindow::OnComposeEnd
virtual void OnComposeEnd()
Definition: flutter_window.cc:230
flutter::FlutterWindow::SetView
virtual void SetView(WindowBindingHandlerDelegate *view) override
Definition: flutter_window.cc:114
flutter::FlutterWindow::~FlutterWindow
virtual ~FlutterWindow()
Definition: flutter_window.cc:110
flutter::FlutterWindow::HandleMessage
LRESULT HandleMessage(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
Definition: flutter_window.cc:499
flutter::FlutterWindow::OnComposeChange
virtual void OnComposeChange(const std::u16string &text, int cursor_pos)
Definition: flutter_window.cc:234
flutter::FlutterWindow::OnResetImeComposing
virtual void OnResetImeComposing() override
Definition: flutter_window.cc:264
flutter::FlutterWindow::Win32MapVkToChar
virtual uint32_t Win32MapVkToChar(uint32_t virtual_key) override
Definition: flutter_window.cc:442
flutter::FlutterWindow::OnImeComposition
virtual void OnImeComposition(UINT const message, WPARAM const wparam, LPARAM const lparam)
Definition: flutter_window.cc:823
flutter::FlutterWindow::GetCurrentDPI
UINT GetCurrentDPI()
Definition: flutter_window.cc:881
flutter::FlutterWindow::OnDpiScale
virtual void OnDpiScale(unsigned int dpi)
Definition: flutter_window.cc:149
flutter::FlutterWindow::AbortImeComposing
virtual void AbortImeComposing()
Definition: flutter_window.cc:873
flutter::FlutterWindow::GetDpiScale
virtual float GetDpiScale() override
Definition: flutter_window.cc:127
flutter::FlutterWindow::OnUpdateSemanticsEnabled
virtual void OnUpdateSemanticsEnabled(bool enabled)
Definition: flutter_window.cc:239
flutter::FlutterWindow::OnGetObject
virtual LRESULT OnGetObject(UINT const message, WPARAM const wparam, LPARAM const lparam)
Definition: flutter_window.cc:752
flutter::FlutterWindow::GetNativeViewAccessible
virtual gfx::NativeViewAccessible GetNativeViewAccessible()
Definition: flutter_window.cc:293
flutter::FlutterWindow::OnComposeBegin
virtual void OnComposeBegin()
Definition: flutter_window.cc:222
flutter::FlutterWindow::OnBitmapSurfaceCleared
virtual bool OnBitmapSurfaceCleared() override
Definition: flutter_window.cc:268
flutter::FlutterWindow::OnResize
virtual void OnResize(unsigned int width, unsigned int height)
Definition: flutter_window.cc:153
flutter::FlutterWindow::OnImeEndComposition
virtual void OnImeEndComposition(UINT const message, WPARAM const wparam, LPARAM const lparam)
Definition: flutter_window.cc:858
flutter::KeyboardManager::WindowDelegate::KeyEventCallback
std::function< void(bool)> KeyEventCallback
Definition: keyboard_manager.h:54
flutter::Point
Definition: geometry.h:15
flutter::Rect
Definition: geometry.h:59
flutter::Rect::top
double top() const
Definition: geometry.h:67
flutter::Rect::height
double height() const
Definition: geometry.h:71
flutter::Rect::left
double left() const
Definition: geometry.h:66
flutter::Rect::width
double width() const
Definition: geometry.h:70
flutter::Size
Definition: geometry.h:35
flutter::WindowBindingHandlerDelegate
Definition: window_binding_handler_delegate.h:18
flutter::WindowBindingHandlerDelegate::OnPointerDown
virtual void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button)=0
flutter::WindowBindingHandlerDelegate::OnPointerMove
virtual void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state)=0
flutter::WindowBindingHandlerDelegate::OnComposeChange
virtual void OnComposeChange(const std::u16string &text, int cursor_pos)=0
flutter::WindowBindingHandlerDelegate::OnHighContrastChanged
virtual void OnHighContrastChanged()=0
flutter::WindowBindingHandlerDelegate::OnText
virtual void OnText(const std::u16string &)=0
flutter::WindowBindingHandlerDelegate::OnPointerLeave
virtual void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id)=0
flutter::WindowBindingHandlerDelegate::OnKey
virtual void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback)=0
flutter::WindowBindingHandlerDelegate::OnUpdateSemanticsEnabled
virtual void OnUpdateSemanticsEnabled(bool enabled)=0
flutter::WindowBindingHandlerDelegate::OnPointerUp
virtual void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button)=0
flutter::WindowBindingHandlerDelegate::OnWindowStateEvent
virtual void OnWindowStateEvent(HWND hwnd, WindowStateEvent event)=0
flutter::WindowBindingHandlerDelegate::GetAxFragmentRootDelegate
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate()=0
flutter::WindowBindingHandlerDelegate::OnComposeEnd
virtual void OnComposeEnd()=0
flutter::WindowBindingHandlerDelegate::OnWindowRepaint
virtual void OnWindowRepaint()=0
flutter::WindowBindingHandlerDelegate::GetNativeViewAccessible
virtual gfx::NativeViewAccessible GetNativeViewAccessible()=0
flutter::WindowBindingHandlerDelegate::OnWindowSizeChanged
virtual bool OnWindowSizeChanged(size_t width, size_t height)=0
flutter::WindowBindingHandlerDelegate::OnComposeBegin
virtual void OnComposeBegin()=0
flutter::WindowBindingHandlerDelegate::OnFocus
virtual void OnFocus(FlutterViewFocusState focus_state, FlutterViewFocusDirection direction)=0
flutter::WindowBindingHandlerDelegate::OnScroll
virtual void OnScroll(double x, double y, double delta_x, double delta_y, int scroll_offset_multiplier, FlutterPointerDeviceKind device_kind, int32_t device_id)=0
flutter::WindowBindingHandlerDelegate::OnComposeCommit
virtual void OnComposeCommit()=0
dpi_utils.h
flutter_window.h
flutter_windows_engine.h
flutter_windows_view.h
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52
extended
bool extended
Definition: keyboard_key_handler_unittests.cc:118
key
int key
Definition: keyboard_key_handler_unittests.cc:114
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
action
int action
Definition: keyboard_key_handler_unittests.cc:116
scancode
int scancode
Definition: keyboard_key_handler_unittests.cc:115
was_down
bool was_down
Definition: keyboard_key_handler_unittests.cc:119
text
std::u16string text
Definition: keyboard_unittests.cc:332
message
Win32Message message
Definition: keyboard_unittests.cc:137
keyboard_utils.h
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::kShift
constexpr int kShift
Definition: keyboard_utils.h:14
flutter::GetDpiForHWND
UINT GetDpiForHWND(HWND hwnd)
Definition: dpi_utils.cc:130
flutter::WindowStateEvent
WindowStateEvent
An event representing a change in window state that may update the.
Definition: windows_lifecycle_manager.h:24
flutter::WindowStateEvent::kHide
@ kHide
flutter::WindowStateEvent::kUnfocus
@ kUnfocus
flutter::WindowStateEvent::kShow
@ kShow
flutter::WindowStateEvent::kFocus
@ kFocus
flutter::kControl
constexpr int kControl
Definition: keyboard_utils.h:15
flutter::PhysicalWindowBounds
Definition: window_binding_handler.h:27
flutter::PointerLocation
Definition: window_binding_handler.h:34