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