From 65e6de2b59ed290c2fddfdd58eb1156cc0ea92b0 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Tue, 30 Aug 2022 06:49:59 +0000 Subject: [PATCH] Bug 1704978 - Prevent opening context menu in the case the user did right click in the overscroll gutter on Windows. r=botond,handyman Differential Revision: https://phabricator.services.mozilla.com/D155039 --- ...helper_hittest_overscroll_contextmenu.html | 5 ---- widget/windows/nsWindow.cpp | 24 ++++++++++++++++++- widget/windows/nsWindow.h | 23 ++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html index c6b80103392d..8aff3103ddc9 100644 --- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html +++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html @@ -78,11 +78,6 @@ async function test() { var config = getHitTestConfig(); var utils = config.utils; - if (config.isWindows) { - todo(false, "This test does not yet work on Windows"); - return; - } - // Overscroll the root scroll frame at the top, creating a gutter. // Note that the size of the gutter will only be 8px, because // setAsyncScrollOffset() applies the overscroll as a single delta, diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 76eeeade02d7..615b671badaa 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -4479,6 +4479,7 @@ bool nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam, int16_t aButton, uint16_t aInputSource, WinPointerInfo* aPointerInfo, bool aIgnoreAPZ) { + ContextMenuPreventer contextMenuPreventer(this); bool result = false; UserActivity(); @@ -4695,7 +4696,10 @@ bool nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam, } } - return ConvertStatus(DispatchInputEvent(&event).mContentStatus); + nsIWidget::ContentAndAPZEventStatus eventStatus = + DispatchInputEvent(&event); + contextMenuPreventer.Update(event, eventStatus); + return ConvertStatus(eventStatus.mContentStatus); } return result; @@ -5787,6 +5791,14 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam, break; } + // If this WM_CONTEXTMENU is triggered by a mouse's secondary button up + // event in overscroll gutter, we shouldn't open context menu. + if (MOUSE_INPUT_SOURCE() == MouseEvent_Binding::MOZ_SOURCE_MOUSE && + mNeedsToPreventContextMenu) { + result = true; + break; + } + // if the context menu is brought up from the keyboard, |lParam| // will be -1. LPARAM pos; @@ -9435,3 +9447,13 @@ void nsWindow::FrameState::SetSizeModeInternal(nsSizeMode aMode) { mWindow->DispatchFocusToTopLevelWindow(true); } } + +void nsWindow::ContextMenuPreventer::Update( + const WidgetMouseEvent& aEvent, + const nsIWidget::ContentAndAPZEventStatus& aEventStatus) { + mNeedsToPreventContextMenu = + aEvent.mMessage == eMouseUp && + aEvent.mButton == MouseButton::eSecondary && + aEvent.mInputSource == MouseEvent_Binding::MOZ_SOURCE_MOUSE && + aEventStatus.mApzStatus == nsEventStatus_eConsumeNoDefault; +} diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index 42747415971c..93f8d88ab0b4 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -64,6 +64,7 @@ class nsIRollupListener; class imgIContainer; namespace mozilla { +class WidgetMouseEvent; namespace widget { class NativeKey; class InProcessWinCompositorWidget; @@ -876,6 +877,28 @@ class nsWindow final : public nsBaseWidget { // process after the Compositor is created bool mRequestFxrOutputPending = false; + // A stack based class used in DispatchMouseEvent() to tell whether we should + // NOT open context menu when we receives WM_CONTEXTMENU after the + // DispatchMouseEvent calls. + // This class now works only in the case where a mouse up event happened in + // the overscroll gutter. + class MOZ_STACK_CLASS ContextMenuPreventer final { + public: + explicit ContextMenuPreventer(nsWindow* aWindow) + : mWindow(aWindow), mNeedsToPreventContextMenu(false){}; + ~ContextMenuPreventer() { + mWindow->mNeedsToPreventContextMenu = mNeedsToPreventContextMenu; + } + void Update(const mozilla::WidgetMouseEvent& aEvent, + const nsIWidget::ContentAndAPZEventStatus& aEventStatus); + + private: + nsWindow* mWindow; + bool mNeedsToPreventContextMenu = false; + }; + friend class ContextMenuPreventer; + bool mNeedsToPreventContextMenu = false; + mozilla::UniquePtr mDmOwner; // Client rect for minimize, maximize and close buttons.