From 02bffcaaca7199bb6c23f5dc6a0b2bd67b5426c1 Mon Sep 17 00:00:00 2001 From: Calvin Date: Tue, 8 Mar 2022 14:06:20 -0700 Subject: [PATCH] fix: non-client mouse events on WCO-enabled windows (#32871) --- patches/chromium/.patches | 1 + ...king_and_message_bubbling_on_windows.patch | 61 +++++++++++++++++++ .../electron_desktop_window_tree_host_win.cc | 17 ------ .../electron_desktop_window_tree_host_win.h | 1 - 4 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 995bb12ffa7c7..545165e4e06ad 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -113,3 +113,4 @@ fix_crash_when_saving_edited_pdf_files.patch port_autofill_colors_to_the_color_pipeline.patch build_disable_partition_alloc_on_mac.patch build_disable_thin_lto_on_mac.patch +fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch diff --git a/patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch b/patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch new file mode 100644 index 0000000000000..86a3c0fbc97be --- /dev/null +++ b/patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: clavin +Date: Fri, 11 Feb 2022 15:05:42 -0700 +Subject: fix: non-client mouse tracking and message bubbling on windows + +It is not known why, but for some reason calling |DefWindowProc| on the parent +window handle causes a WM_NCMOUSELEAVE (non-client mouse exit) message to be +sent to the parent window, even though |TrackMouseEvent| is never called on it. + +This patch also adds some boilerplate for properly tracking non-client mouse +messages in the legacy window handle layer. + +These conditions are regularly hit with WCO-enabled windows on Windows. + +diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc +index 4a894ef70eeb1d8489049aef552c9bae4f24ae62..f5049d730a850f2947023f976b25fb772e42107a 100644 +--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc ++++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc +@@ -288,12 +288,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message, + WPARAM w_param, + LPARAM l_param, + BOOL& handled) { +- if (message == WM_MOUSEMOVE) { ++ if (message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE) { + if (!mouse_tracking_enabled_) { + mouse_tracking_enabled_ = true; + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); +- tme.dwFlags = TME_LEAVE; ++ tme.dwFlags = message == WM_NCMOUSEMOVE ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE; + tme.hwndTrack = hwnd(); + tme.dwHoverTime = 0; + TrackMouseEvent(&tme); +@@ -319,12 +319,11 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message, + message, w_param, l_param, &msg_handled); + handled = msg_handled; + // If the parent did not handle non client mouse messages, we call +- // DefWindowProc on the message with the parent window handle. This +- // ensures that WM_SYSCOMMAND is generated for the parent and we are +- // out of the picture. ++ // DefWindowProc on the message. This ensures that WM_SYSCOMMAND is ++ // generated. + if (!handled && + (message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) { +- ret = ::DefWindowProc(GetParent(), message, w_param, l_param); ++ ret = ::DefWindowProc(hwnd(), message, w_param, l_param); + handled = TRUE; + } + } +diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h +index 79dffd981f4d461f30bd3796cfba1457eda3a89d..ae378ce95f90989fd0e74c38b57f5f7dc0a1ee29 100644 +--- a/content/browser/renderer_host/legacy_render_widget_host_win.h ++++ b/content/browser/renderer_host/legacy_render_widget_host_win.h +@@ -105,6 +105,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND + MESSAGE_HANDLER_EX(WM_NCHITTEST, OnNCHitTest) + MESSAGE_RANGE_HANDLER(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, + OnMouseRange) ++ MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseLeave) + MESSAGE_HANDLER_EX(WM_NCCALCSIZE, OnNCCalcSize) + MESSAGE_HANDLER_EX(WM_SIZE, OnSize) + MESSAGE_HANDLER_EX(WM_DESTROY, OnDestroy) diff --git a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc index 3600e273ea73b..2e4e5bc9502e4 100644 --- a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc +++ b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc @@ -99,21 +99,4 @@ bool ElectronDesktopWindowTreeHostWin::GetClientAreaInsets( return false; } -bool ElectronDesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) { - // Call the default implementation of this method to get the event to its - // proper handler. - bool handled = views::DesktopWindowTreeHostWin::HandleMouseEvent(event); - - // On WCO-enabled windows, we need to mark non-client mouse moved events as - // handled so they don't incorrectly propogate back to the OS. - if (native_window_view_->IsWindowControlsOverlayEnabled() && - event->type() == ui::ET_MOUSE_MOVED && - (event->flags() & ui::EF_IS_NON_CLIENT) != 0) { - event->SetHandled(); - handled = true; - } - - return handled; -} - } // namespace electron diff --git a/shell/browser/ui/win/electron_desktop_window_tree_host_win.h b/shell/browser/ui/win/electron_desktop_window_tree_host_win.h index 8c7be1175a193..3fd831aae1ed0 100644 --- a/shell/browser/ui/win/electron_desktop_window_tree_host_win.h +++ b/shell/browser/ui/win/electron_desktop_window_tree_host_win.h @@ -36,7 +36,6 @@ class ElectronDesktopWindowTreeHostWin bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override; bool GetClientAreaInsets(gfx::Insets* insets, HMONITOR monitor) const override; - bool HandleMouseEvent(ui::MouseEvent* event) override; private: NativeWindowViews* native_window_view_; // weak ref