13 #include "flutter/fml/logging.h"
14 #include "flutter/shell/platform/embedder/embedder.h"
26 constexpr
int base_dpi = 96;
28 static const int kMinTouchDeviceId = 0;
29 static const int kMaxTouchDeviceId = 128;
31 static const int kLinesPerScrollWindowsDefault = 3;
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},
44 {
"forbidden", IDC_NO},
46 {
"move", IDC_SIZEALL},
49 {
"precise", IDC_CROSS},
50 {
"progress", IDC_APPSTARTING},
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},
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;
73 return ::LoadCursor(
nullptr, idc_name);
76 static constexpr int32_t kDefaultPointerDeviceId = 0;
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;
91 return kFlutterPointerDeviceKindStylus;
93 return kFlutterPointerDeviceKindMouse;
97 static uint64_t ConvertWinButtonToFlutterButton(UINT button) {
101 return kFlutterPointerButtonMousePrimary;
104 return kFlutterPointerButtonMouseSecondary;
107 return kFlutterPointerButtonMouseMiddle;
109 return kFlutterPointerButtonMouseBack;
111 return kFlutterPointerButtonMouseForward;
113 FML_LOG(WARNING) <<
"Mouse button not recognized: " << button;
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) {
136 UpdateScrollOffsetMultiplier();
138 if (windows_proc_table_ ==
nullptr) {
139 windows_proc_table_ = std::make_unique<WindowsProcTable>();
141 if (text_input_manager_ ==
nullptr) {
142 text_input_manager_ = std::make_unique<TextInputManager>();
144 keyboard_manager_ = std::make_unique<KeyboardManager>(
this);
147 current_cursor_ = ::LoadCursor(
nullptr, IDC_ARROW);
152 : touch_id_generator_(kMinTouchDeviceId, kMaxTouchDeviceId) {}
159 binding_handler_delegate_ = window;
163 if (restored_ && window) {
166 if (focused_ && window) {
172 return static_cast<float>(
GetCurrentDPI()) /
static_cast<float>(base_dpi);
184 current_cursor_ = cursor;
185 ::SetCursor(current_cursor_);
193 if (binding_handler_delegate_ !=
nullptr) {
199 if (binding_handler_delegate_ !=
nullptr) {
206 FlutterPointerDeviceKind device_kind,
208 int modifiers_state) {
209 binding_handler_delegate_->
OnPointerMove(x, y, device_kind, device_id,
215 FlutterPointerDeviceKind device_kind,
218 uint64_t flutter_button = ConvertWinButtonToFlutterButton(button);
219 if (flutter_button != 0) {
221 x, y, device_kind, device_id,
222 static_cast<FlutterPointerMouseButtons
>(flutter_button));
228 FlutterPointerDeviceKind device_kind,
231 uint64_t flutter_button = ConvertWinButtonToFlutterButton(button);
232 if (flutter_button != 0) {
234 x, y, device_kind, device_id,
235 static_cast<FlutterPointerMouseButtons
>(flutter_button));
241 FlutterPointerDeviceKind device_kind,
243 binding_handler_delegate_->
OnPointerLeave(x, y, device_kind, device_id);
247 ::SetCursor(current_cursor_);
288 FlutterPointerDeviceKind device_kind,
291 GetCursorPos(&point);
294 binding_handler_delegate_->
OnScroll(point.x, point.y, delta_x, delta_y,
313 bool result = ::PatBlt(dc, 0, 0, current_width_, current_height_, BLACKNESS);
323 bmi.bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
324 bmi.bmiHeader.biWidth = row_bytes / 4;
325 bmi.bmiHeader.biHeight = -height;
326 bmi.bmiHeader.biPlanes = 1;
327 bmi.bmiHeader.biBitCount = 32;
328 bmi.bmiHeader.biCompression = BI_RGB;
329 bmi.bmiHeader.biSizeImage = 0;
330 int ret = ::SetDIBitsToDevice(dc, 0, 0, row_bytes / 4, height, 0, 0, 0,
331 height, allocation, &bmi, DIB_RGB_COLORS);
337 if (binding_handler_delegate_ ==
nullptr) {
346 GetCursorPos(&point);
348 return {(size_t)point.x, (
size_t)point.y};
360 CreateAxFragmentRoot();
365 CreateAxFragmentRoot();
386 if (hwnd && binding_handler_delegate_) {
391 void FlutterWindow::TrackMouseLeaveEvent(HWND hwnd) {
392 if (!tracking_mouse_leave_) {
394 tme.cbSize =
sizeof(tme);
395 tme.hwndTrack = hwnd;
396 tme.dwFlags = TME_LEAVE;
397 TrackMouseEvent(&tme);
398 tracking_mouse_leave_ =
true;
402 void FlutterWindow::HandleResize(UINT width, UINT height) {
403 current_width_ = width;
404 current_height_ = height;
411 FlutterWindow* FlutterWindow::GetThisFromHandle(HWND
const window) noexcept {
412 return reinterpret_cast<FlutterWindow*
>(
413 GetWindowLongPtr(window, GWLP_USERDATA));
416 void FlutterWindow::UpdateScrollOffsetMultiplier() {
417 UINT lines_per_scroll = kLinesPerScrollWindowsDefault;
420 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines_per_scroll, 0);
424 scroll_offset_multiplier_ =
425 static_cast<float>(lines_per_scroll) * 100.0 / 3.0;
430 unsigned int height) {
434 WNDCLASS window_class = RegisterWindowClass(converted_title);
436 auto* result = CreateWindowEx(
437 0, window_class.lpszClassName, converted_title.c_str(),
438 WS_CHILD | WS_VISIBLE, CW_DEFAULT, CW_DEFAULT, width, height,
439 HWND_MESSAGE,
nullptr, window_class.hInstance,
this);
441 if (result ==
nullptr) {
442 auto error = GetLastError();
444 size_t size = FormatMessageW(
445 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
446 FORMAT_MESSAGE_IGNORE_INSERTS,
447 NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
448 reinterpret_cast<LPWSTR
>(&
message), 0, NULL);
452 SetUserObjectInformationA(GetCurrentProcess(),
453 UOI_TIMERPROC_EXCEPTION_SUPPRESSION, FALSE, 1);
458 SetTimer(result, kDirectManipulationTimer, 14,
nullptr);
464 return window_handle_;
471 return ::PeekMessage(lpMsg, window_handle_, wMsgFilterMin, wMsgFilterMax,
476 return ::MapVirtualKey(virtual_key, MAPVK_VK_TO_CHAR);
482 return ::SendMessage(window_handle_, Msg, wParam, lParam);
486 size_t length = strlen(source);
488 std::wstring wideTitle(length, L
'#');
489 mbstowcs_s(&outlen, &wideTitle[0], length + 1, source, length);
493 WNDCLASS FlutterWindow::RegisterWindowClass(std::wstring& title) {
494 window_class_name_ = title;
496 WNDCLASS window_class{};
497 window_class.hCursor = LoadCursor(
nullptr, IDC_ARROW);
498 window_class.lpszClassName = title.c_str();
499 window_class.style = CS_HREDRAW | CS_VREDRAW;
500 window_class.cbClsExtra = 0;
501 window_class.cbWndExtra = 0;
502 window_class.hInstance = GetModuleHandle(
nullptr);
503 window_class.hIcon =
nullptr;
504 window_class.hbrBackground = 0;
505 window_class.lpszMenuName =
nullptr;
506 window_class.lpfnWndProc = WndProc;
507 RegisterClass(&window_class);
511 LRESULT CALLBACK FlutterWindow::WndProc(HWND
const window,
514 LPARAM
const lparam) noexcept {
516 auto cs =
reinterpret_cast<CREATESTRUCT*
>(lparam);
517 SetWindowLongPtr(window, GWLP_USERDATA,
518 reinterpret_cast<LONG_PTR
>(cs->lpCreateParams));
520 auto that =
static_cast<FlutterWindow*
>(cs->lpCreateParams);
521 that->window_handle_ = window;
522 that->text_input_manager_->SetWindowHandle(window);
523 RegisterTouchWindow(window, 0);
524 }
else if (FlutterWindow* that = GetThisFromHandle(window)) {
525 return that->HandleMessage(
message, wparam, lparam);
528 return DefWindowProc(window,
message, wparam, lparam);
534 LPARAM
const lparam) noexcept {
535 LPARAM result_lparam = lparam;
536 int xPos = 0, yPos = 0;
537 UINT width = 0, height = 0;
538 UINT button_pressed = 0;
539 FlutterPointerDeviceKind device_kind;
542 case kWmDpiChangedBeforeParent:
544 OnDpiScale(current_dpi_);
547 width = LOWORD(lparam);
548 height = HIWORD(lparam);
550 current_width_ = width;
551 current_height_ = height;
552 HandleResize(width, height);
561 UINT num_points = LOWORD(wparam);
562 touch_points_.resize(num_points);
563 auto touch_input_handle =
reinterpret_cast<HTOUCHINPUT
>(lparam);
564 if (GetTouchInputInfo(touch_input_handle, num_points,
565 touch_points_.data(),
sizeof(TOUCHINPUT))) {
566 for (
const auto& touch : touch_points_) {
568 auto touch_id = touch_id_generator_.GetGeneratedId(touch.dwID);
570 POINT pt = {TOUCH_COORD_TO_PIXEL(touch.x),
571 TOUCH_COORD_TO_PIXEL(touch.y)};
572 ScreenToClient(window_handle_, &pt);
573 auto x =
static_cast<double>(pt.x);
574 auto y =
static_cast<double>(pt.y);
576 if (touch.dwFlags & TOUCHEVENTF_DOWN) {
577 OnPointerDown(x, y, kFlutterPointerDeviceKindTouch, touch_id,
579 }
else if (touch.dwFlags & TOUCHEVENTF_MOVE) {
580 OnPointerMove(x, y, kFlutterPointerDeviceKindTouch, touch_id, 0);
581 }
else if (touch.dwFlags & TOUCHEVENTF_UP) {
582 OnPointerUp(x, y, kFlutterPointerDeviceKindTouch, touch_id,
584 OnPointerLeave(x, y, kFlutterPointerDeviceKindTouch, touch_id);
585 touch_id_generator_.ReleaseNumber(touch.dwID);
588 CloseTouchInputHandle(touch_input_handle);
593 device_kind = GetFlutterPointerDeviceKind();
594 if (device_kind == kFlutterPointerDeviceKindMouse) {
595 TrackMouseLeaveEvent(window_handle_);
597 xPos = GET_X_LPARAM(lparam);
598 yPos = GET_Y_LPARAM(lparam);
599 mouse_x_ =
static_cast<double>(xPos);
600 mouse_y_ =
static_cast<double>(yPos);
603 if (wparam & MK_CONTROL) {
606 if (wparam & MK_SHIFT) {
609 OnPointerMove(mouse_x_, mouse_y_, device_kind, kDefaultPointerDeviceId,
614 device_kind = GetFlutterPointerDeviceKind();
615 if (device_kind == kFlutterPointerDeviceKindMouse) {
616 OnPointerLeave(mouse_x_, mouse_y_, device_kind,
617 kDefaultPointerDeviceId);
623 tracking_mouse_leave_ =
false;
626 UINT hit_test_result = LOWORD(lparam);
627 if (hit_test_result == HTCLIENT) {
635 ::CreateCaret(window_handle_,
nullptr, 1, 1);
645 device_kind = GetFlutterPointerDeviceKind();
646 if (device_kind != kFlutterPointerDeviceKindMouse) {
650 if (
message == WM_LBUTTONDOWN) {
656 SetCapture(window_handle_);
659 if (
message == WM_XBUTTONDOWN) {
660 button_pressed = GET_XBUTTON_WPARAM(wparam);
662 xPos = GET_X_LPARAM(lparam);
663 yPos = GET_Y_LPARAM(lparam);
664 OnPointerDown(
static_cast<double>(xPos),
static_cast<double>(yPos),
665 device_kind, kDefaultPointerDeviceId, button_pressed);
671 device_kind = GetFlutterPointerDeviceKind();
672 if (device_kind != kFlutterPointerDeviceKindMouse) {
681 button_pressed = GET_XBUTTON_WPARAM(wparam);
683 xPos = GET_X_LPARAM(lparam);
684 yPos = GET_Y_LPARAM(lparam);
685 OnPointerUp(
static_cast<double>(xPos),
static_cast<double>(yPos),
686 device_kind, kDefaultPointerDeviceId, button_pressed);
690 -(
static_cast<short>(HIWORD(wparam)) /
691 static_cast<double>(WHEEL_DELTA)),
692 kFlutterPointerDeviceKindMouse, kDefaultPointerDeviceId);
695 OnScroll((
static_cast<short>(HIWORD(wparam)) /
696 static_cast<double>(WHEEL_DELTA)),
697 0.0, kFlutterPointerDeviceKindMouse, kDefaultPointerDeviceId);
700 LRESULT lresult = OnGetObject(
message, wparam, lparam);
707 if (wparam == kDirectManipulationTimer) {
708 direct_manipulation_owner_->Update();
712 case DM_POINTERHITTEST: {
713 if (direct_manipulation_owner_) {
714 UINT contact_id = GET_POINTERID_WPARAM(wparam);
715 POINTER_INPUT_TYPE pointer_type;
716 if (windows_proc_table_->GetPointerType(contact_id, &pointer_type) &&
717 pointer_type == PT_TOUCHPAD) {
718 direct_manipulation_owner_->SetContact(contact_id);
723 case WM_INPUTLANGCHANGE:
727 case WM_IME_SETCONTEXT:
728 OnImeSetContext(
message, wparam, lparam);
732 result_lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
734 case WM_IME_STARTCOMPOSITION:
735 OnImeStartComposition(
message, wparam, lparam);
740 case WM_IME_COMPOSITION:
741 OnImeComposition(
message, wparam, lparam);
742 if (lparam & GCS_RESULTSTR || lparam & GCS_COMPSTR) {
751 case WM_IME_ENDCOMPOSITION:
752 OnImeEndComposition(
message, wparam, lparam);
755 OnImeRequest(
message, wparam, lparam);
759 if (wparam == UNICODE_NOCHAR)
764 case WM_THEMECHANGED:
775 if (keyboard_manager_->HandleMessage(
message, wparam, lparam)) {
781 return Win32DefWindowProc(window_handle_,
message, wparam, result_lparam);
786 LPARAM
const lparam) {
787 LRESULT reference_result =
static_cast<LRESULT
>(0L);
791 DWORD obj_id =
static_cast<DWORD
>(
static_cast<DWORD_PTR
>(lparam));
793 bool is_uia_request =
static_cast<DWORD
>(UiaRootObjectId) == obj_id;
794 bool is_msaa_request =
static_cast<DWORD
>(OBJID_CLIENT) == obj_id;
796 if (is_uia_request || is_msaa_request) {
812 CreateAxFragmentRoot();
813 if (is_uia_request) {
814 #ifdef FLUTTER_ENGINE_USE_UIA
816 Microsoft::WRL::ComPtr<IRawElementProviderSimple> root;
818 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
819 IID_PPV_ARGS(&root)))) {
822 reference_result = UiaReturnRawElementProvider(window_handle_, wparam,
825 FML_LOG(ERROR) <<
"Failed to query AX fragment root.";
828 }
else if (is_msaa_request) {
831 Microsoft::WRL::ComPtr<IAccessible> root;
832 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
833 IID_PPV_ARGS(&root));
834 reference_result = LresultFromObject(IID_IAccessible, wparam, root.Get());
837 return reference_result;
842 LPARAM
const lparam) {
844 text_input_manager_->CreateImeWindow();
850 LPARAM
const lparam) {
851 text_input_manager_->CreateImeWindow();
857 LPARAM
const lparam) {
859 text_input_manager_->UpdateImeWindow();
869 if (lparam & GCS_RESULTSTR) {
872 long pos = text_input_manager_->GetComposingCursorPosition();
873 std::optional<std::u16string>
text = text_input_manager_->GetResultString();
879 if (lparam & GCS_COMPSTR) {
881 long pos = text_input_manager_->GetComposingCursorPosition();
882 std::optional<std::u16string>
text =
883 text_input_manager_->GetComposingString();
892 LPARAM
const lparam) {
893 text_input_manager_->DestroyImeWindow();
899 LPARAM
const lparam) {
906 text_input_manager_->AbortComposing();
910 text_input_manager_->UpdateCaretRect(rect);
918 return current_width_;
922 return current_height_;
926 return scroll_offset_multiplier_;
933 return ::DefWindowProc(hWnd, Msg, wParam, lParam);
936 void FlutterWindow::Destroy() {
937 if (window_handle_) {
938 text_input_manager_->SetWindowHandle(
nullptr);
939 DestroyWindow(window_handle_);
940 window_handle_ =
nullptr;
943 UnregisterClass(window_class_name_.c_str(),
nullptr);
946 void FlutterWindow::CreateAxFragmentRoot() {
947 if (ax_fragment_root_) {
950 ax_fragment_root_ = std::make_unique<ui::AXFragmentRootWin>(
953 std::make_unique<AlertPlatformNodeDelegate>(*ax_fragment_root_);
954 ui::AXPlatformNode* alert_node =
956 alert_node_.reset(
static_cast<ui::AXPlatformNodeWin*
>(alert_node));
957 ax_fragment_root_->SetAlertNode(
alert_node_.get());
virtual void OnCursorRectUpdated(const Rect &rect) override
virtual void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id)
virtual float GetScrollOffsetMultiplier()
virtual ui::AXPlatformNodeWin * GetAlert() override
virtual void OnText(const std::u16string &text) override
virtual UINT Win32DispatchMessage(UINT Msg, WPARAM wParam, LPARAM lParam) override
virtual BOOL Win32PeekMessage(LPMSG lpMsg, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) override
virtual void OnThemeChange()
std::unique_ptr< AlertPlatformNodeDelegate > alert_delegate_
virtual bool OnBitmapSurfaceUpdated(const void *allocation, size_t row_bytes, size_t height) override
virtual void OnImeRequest(UINT const message, WPARAM const wparam, LPARAM const lparam)
virtual LRESULT Win32DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
virtual void OnImeStartComposition(UINT const message, WPARAM const wparam, LPARAM const lparam)
std::wstring NarrowToWide(const char *source)
virtual void OnSetCursor()
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate()
virtual void OnScroll(double delta_x, double delta_y, FlutterPointerDeviceKind device_kind, int32_t device_id)
virtual void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, UINT button)
void InitializeChild(const char *title, unsigned int width, unsigned int height)
virtual AlertPlatformNodeDelegate * GetAlertDelegate() override
virtual void SetFlutterCursor(HCURSOR cursor) override
std::unique_ptr< DirectManipulationOwner > direct_manipulation_owner_
virtual HWND GetWindowHandle() override
virtual void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, UINT button)
virtual void OnComposeCommit()
virtual void UpdateCursorRect(const Rect &rect)
virtual PhysicalWindowBounds GetPhysicalWindowBounds() override
virtual void OnImeSetContext(UINT const message, WPARAM const wparam, LPARAM const lparam)
virtual void OnWindowStateEvent(WindowStateEvent event)
virtual void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
virtual void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state)
std::unique_ptr< ui::AXPlatformNodeWin > alert_node_
virtual PointerLocation GetPrimaryPointerLocation() override
virtual void OnComposeEnd()
virtual void SetView(WindowBindingHandlerDelegate *view) override
LRESULT HandleMessage(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
virtual void OnComposeChange(const std::u16string &text, int cursor_pos)
virtual void OnResetImeComposing() override
virtual uint32_t Win32MapVkToChar(uint32_t virtual_key) override
virtual void OnImeComposition(UINT const message, WPARAM const wparam, LPARAM const lparam)
virtual void OnDpiScale(unsigned int dpi)
virtual void AbortImeComposing()
virtual float GetDpiScale() override
virtual void OnUpdateSemanticsEnabled(bool enabled)
virtual LRESULT OnGetObject(UINT const message, WPARAM const wparam, LPARAM const lparam)
virtual gfx::NativeViewAccessible GetNativeViewAccessible()
virtual void OnComposeBegin()
virtual bool OnBitmapSurfaceCleared() override
virtual void OnResize(unsigned int width, unsigned int height)
virtual void UpdateFlutterCursor(const std::string &cursor_name) override
virtual void OnImeEndComposition(UINT const message, WPARAM const wparam, LPARAM const lparam)
std::function< void(bool)> KeyEventCallback
virtual void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button)=0
virtual void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state)=0
virtual void OnComposeChange(const std::u16string &text, int cursor_pos)=0
virtual void OnHighContrastChanged()=0
virtual void OnText(const std::u16string &)=0
virtual void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id)=0
virtual void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback)=0
virtual void OnUpdateSemanticsEnabled(bool enabled)=0
virtual void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button)=0
virtual void OnWindowStateEvent(HWND hwnd, WindowStateEvent event)=0
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate()=0
virtual void OnComposeEnd()=0
virtual void OnWindowRepaint()=0
virtual gfx::NativeViewAccessible GetNativeViewAccessible()=0
virtual bool OnWindowSizeChanged(size_t width, size_t height)=0
virtual void OnComposeBegin()=0
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
virtual void OnComposeCommit()=0
FlutterDesktopBinaryReply callback
UINT GetDpiForHWND(HWND hwnd)
WindowStateEvent
An event representing a change in window state that may update the.