From ef2253b4a13ec0f51f438651a236706abf53733b Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Wed, 24 Feb 2021 01:27:10 +0000 Subject: [PATCH] Bug 1691622 - part 9: Make `nsIWidget::SynthesizeNativeMouseEvent` take an XP button ID and abstract message value r=smaug,geckoview-reviewers,agi,m_kato Currently, it takes a raw native message value, but it makes JS content too complicated. And on Linux, it cannot synthesize non-primary button events because GDK has only button press and release messages which dont' include mouse button information. For solving these problems, this patch creates a new abstract native message as `nsIWidget::NativeMouseMessage` and makes each widget converts it to a platform native message. Additionally, this patch adds an argument to make it possible its callers to specify pressing or releasing mouse button with a DOM mouse button value. Note that the following patch adds new argument to `synthesizeNativeEventMouse*` for mochitests and which will be tested by new tests. Differential Revision: https://phabricator.services.mozilla.com/D105763 --- accessible/mac/mozAccessible.mm | 6 +- .../browser/browser_touch_event_iframes.js | 60 +------------ dom/base/nsDOMWindowUtils.cpp | 40 +++++++-- dom/interfaces/base/nsIDOMWindowUtils.idl | 22 +++-- dom/ipc/BrowserParent.cpp | 6 +- dom/ipc/BrowserParent.h | 3 +- dom/ipc/PBrowser.ipdl | 1 + .../mochitest/apz_test_native_event_utils.js | 61 ++----------- ...popup_position_in_out_of_process_iframe.js | 6 +- layout/xul/test/test_bug987230.xhtml | 13 +-- .../mozilla/geckoview/PanZoomController.java | 32 +++++-- .../mochitest/tests/SimpleTest/EventUtils.js | 61 ++----------- widget/EventForwards.h | 6 +- widget/PuppetWidget.cpp | 8 +- widget/PuppetWidget.h | 5 +- widget/android/nsWindow.cpp | 73 +++++++++++----- widget/android/nsWindow.h | 3 +- widget/cocoa/nsChildView.h | 7 +- widget/cocoa/nsChildView.mm | 53 ++++++++++-- widget/cocoa/nsCocoaWindow.h | 4 +- widget/cocoa/nsCocoaWindow.mm | 8 +- widget/gtk/nsWindow.cpp | 85 ++++++++++++------- widget/gtk/nsWindow.h | 11 +-- widget/headless/HeadlessWidget.cpp | 16 ++-- widget/headless/HeadlessWidget.h | 26 ++---- widget/nsBaseWidget.h | 5 +- widget/nsIWidget.h | 17 ++-- widget/tests/test_bug596600.xhtml | 10 ++- widget/tests/test_panel_mouse_coords.xhtml | 33 ++++--- widget/windows/nsWindow.cpp | 57 ++++++++++--- widget/windows/nsWindow.h | 11 +-- 31 files changed, 405 insertions(+), 344 deletions(-) diff --git a/accessible/mac/mozAccessible.mm b/accessible/mac/mozAccessible.mm index fbf0d114ebd5..f818564312a0 100644 --- a/accessible/mac/mozAccessible.mm +++ b/accessible/mac/mozAccessible.mm @@ -935,9 +935,9 @@ struct RoleDescrComparator { LayoutDeviceIntPoint(geckoRect.X() + (geckoRect.Width() / 2), geckoRect.Y() + (geckoRect.Height() / 2)); nsIWidget* widget = [objOrView widget]; - widget->SynthesizeNativeMouseEvent(p, NSEventTypeRightMouseDown, - nsIWidget::Modifiers::NO_MODIFIERS, - nullptr); + widget->SynthesizeNativeMouseEvent( + p, nsIWidget::NativeMouseMessage::ButtonDown, MouseButton::eSecondary, + nsIWidget::Modifiers::NO_MODIFIERS, nullptr); } - (void)moxPerformPress { diff --git a/devtools/client/responsive/test/browser/browser_touch_event_iframes.js b/devtools/client/responsive/test/browser/browser_touch_event_iframes.js index ff00a49afbc7..9527f9891823 100644 --- a/devtools/client/responsive/test/browser/browser_touch_event_iframes.js +++ b/devtools/client/responsive/test/browser/browser_touch_event_iframes.js @@ -152,60 +152,6 @@ for (const mvcontent of META_VIEWPORT_CONTENTS) { } } - // Lift a set of functions out of apz_test_native_event_utils.js - // to use for sending native mouse events. Bug 1126772 would instead - // allow us to use a method in EventUtils. - function getPlatform() { - if (content.navigator.platform.indexOf("Win") == 0) { - return "windows"; - } - if (content.navigator.platform.indexOf("Mac") == 0) { - return "mac"; - } - // Check for Android before Linux - if (content.navigator.appVersion.includes("Android")) { - return "android"; - } - if (content.navigator.platform.indexOf("Linux") == 0) { - return "linux"; - } - return "unknown"; - } - - function nativeMouseDownEventMsg() { - switch (getPlatform()) { - case "windows": - return 2; // MOUSEEVENTF_LEFTDOWN - case "mac": - return 1; // NSEventTypeLeftMouseDown - case "linux": - return 4; // GDK_BUTTON_PRESS - case "android": - return 5; // ACTION_POINTER_DOWN - } - throw new Error( - "Native mouse-down events not supported on platform " + - getPlatform() - ); - } - - function nativeMouseUpEventMsg() { - switch (getPlatform()) { - case "windows": - return 4; // MOUSEEVENTF_LEFTUP - case "mac": - return 2; // NSEventTypeLeftMouseUp - case "linux": - return 7; // GDK_BUTTON_RELEASE - case "android": - return 6; // ACTION_POINTER_UP - } - throw new Error( - "Native mouse-up events not supported on platform " + - getPlatform() - ); - } - // This function takes screen coordinates in css pixels. function synthesizeNativeMouseClick(win, screenX, screenY) { const utils = win.windowUtils; @@ -215,14 +161,16 @@ for (const mvcontent of META_VIEWPORT_CONTENTS) { utils.sendNativeMouseEvent( screenX * scale, screenY * scale, - nativeMouseDownEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_DOWN, + 0, 0, win.document.documentElement, () => { utils.sendNativeMouseEvent( screenX * scale, screenY * scale, - nativeMouseUpEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_UP, + 0, 0, win.document.documentElement, resolve diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 8606729d3839..c9d90eba3e80 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1029,21 +1029,45 @@ nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout, NS_IMETHODIMP nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX, int32_t aScreenY, - int32_t aNativeMessage, + uint32_t aNativeMessage, int16_t aButton, uint32_t aModifierFlags, - Element* aElement, + Element* aElementOnWidget, nsIObserver* aObserver) { // get the widget to send the event to - nsCOMPtr widget = GetWidgetForElement(aElement); - if (!widget) return NS_ERROR_FAILURE; + nsCOMPtr widget = GetWidgetForElement(aElementOnWidget); + if (!widget) { + return NS_ERROR_FAILURE; + } + + nsIWidget::NativeMouseMessage message; + switch (aNativeMessage) { + case NATIVE_MOUSE_MESSAGE_BUTTON_DOWN: + message = nsIWidget::NativeMouseMessage::ButtonDown; + break; + case NATIVE_MOUSE_MESSAGE_BUTTON_UP: + message = nsIWidget::NativeMouseMessage::ButtonUp; + break; + case NATIVE_MOUSE_MESSAGE_MOVE: + message = nsIWidget::NativeMouseMessage::Move; + break; + case NATIVE_MOUSE_MESSAGE_ENTER_WINDOW: + message = nsIWidget::NativeMouseMessage::EnterWindow; + break; + case NATIVE_MOUSE_MESSAGE_LEAVE_WINDOW: + message = nsIWidget::NativeMouseMessage::LeaveWindow; + break; + default: + return NS_ERROR_INVALID_ARG; + } NS_DispatchToMainThread(NativeInputRunnable::Create( - NewRunnableMethod( + NewRunnableMethod( "nsIWidget::SynthesizeNativeMouseEvent", widget, &nsIWidget::SynthesizeNativeMouseEvent, - LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, - GetWidgetModifiers(aModifierFlags), aObserver))); + LayoutDeviceIntPoint(aScreenX, aScreenY), message, + static_cast(aButton), GetWidgetModifiers(aModifierFlags), + aObserver))); return NS_OK; } diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index dd8cbeaa3dd0..c38c2ea582cf 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -525,15 +525,27 @@ interface nsIDOMWindowUtils : nsISupports { * Cannot be accessed from unprivileged context (not content-accessible) * Will throw a DOM security error if called without chrome privileges. * - * NOTE: The synthesized native event will be fired asynchronously, and upon - * completion the observer, if provided, will be notified with a "mouseevent" - * topic. + * @param aScreenX X offset in the screen in device pixels. + * @param aScreenY Y offset in the screen in derive pixels. + * @param aNativeMessage One of NATIVE_MOUSE_MESSAGE_* + * @param aButton Same as `MouseEvent.button` value. + * @param aModifierFlags See nsIWidget's native modifier flags. + * @param aElementOnWidget An element which is on a widget. + * @param aObserver The synthesized native event will be fired + * asynchronously, and upon completion the observer, if + * provided, will be notified with a "mouseevent" topic. */ + const unsigned long NATIVE_MOUSE_MESSAGE_BUTTON_DOWN = 0x00000001; + const unsigned long NATIVE_MOUSE_MESSAGE_BUTTON_UP = 0x00000002; + const unsigned long NATIVE_MOUSE_MESSAGE_MOVE = 0x00000003; + const unsigned long NATIVE_MOUSE_MESSAGE_ENTER_WINDOW = 0x00000004; + const unsigned long NATIVE_MOUSE_MESSAGE_LEAVE_WINDOW = 0x00000005; void sendNativeMouseEvent(in long aScreenX, in long aScreenY, - in long aNativeMessage, + in unsigned long aNativeMessage, + in short aButton, in unsigned long aModifierFlags, - in Element aElement, + in Element aElementOnWidget, [optional] in nsIObserver aObserver); /** diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 81a9033779a7..6b3632a81fda 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -1780,12 +1780,14 @@ mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeKeyEvent( mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseEvent( const LayoutDeviceIntPoint& aPoint, const uint32_t& aNativeMessage, - const uint32_t& aModifierFlags, const uint64_t& aObserverId) { + const int16_t& aButton, const uint32_t& aModifierFlags, + const uint64_t& aObserverId) { AutoSynthesizedEventResponder responder(this, aObserverId, "mouseevent"); nsCOMPtr widget = GetWidget(); if (widget) { widget->SynthesizeNativeMouseEvent( - aPoint, aNativeMessage, + aPoint, static_cast(aNativeMessage), + static_cast(aButton), static_cast(aModifierFlags), responder.GetObserver()); } diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index c4b8057d9078..d6623e55497e 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -516,7 +516,8 @@ class BrowserParent final : public PBrowserParent, mozilla::ipc::IPCResult RecvSynthesizeNativeMouseEvent( const LayoutDeviceIntPoint& aPoint, const uint32_t& aNativeMessage, - const uint32_t& aModifierFlags, const uint64_t& aObserverId); + const int16_t& aButton, const uint32_t& aModifierFlags, + const uint64_t& aObserverId); mozilla::ipc::IPCResult RecvSynthesizeNativeMouseMove( const LayoutDeviceIntPoint& aPoint, const uint64_t& aObserverId); diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 63094469e3c8..f172618b7d36 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -507,6 +507,7 @@ parent: uint64_t aObserverId); async SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, + int16_t aButton, uint32_t aModifierFlags, uint64_t aObserverId); async SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, diff --git a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js index 1763a5a5979c..bf9dab6330a3 100644 --- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js +++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js @@ -100,54 +100,6 @@ function nativeScrollUnits(aTarget, aDimen) { return aDimen; } -function nativeMouseDownEventMsg() { - switch (getPlatform()) { - case "windows": - return 2; // MOUSEEVENTF_LEFTDOWN - case "mac": - return 1; // NSEventTypeLeftMouseDown - case "linux": - return 4; // GDK_BUTTON_PRESS - case "android": - return 5; // ACTION_POINTER_DOWN - } - throw new Error( - "Native mouse-down events not supported on platform " + getPlatform() - ); -} - -function nativeMouseMoveEventMsg() { - switch (getPlatform()) { - case "windows": - return 1; // MOUSEEVENTF_MOVE - case "mac": - return 5; // NSEventTypeMouseMoved - case "linux": - return 3; // GDK_MOTION_NOTIFY - case "android": - return 7; // ACTION_HOVER_MOVE - } - throw new Error( - "Native mouse-move events not supported on platform " + getPlatform() - ); -} - -function nativeMouseUpEventMsg() { - switch (getPlatform()) { - case "windows": - return 4; // MOUSEEVENTF_LEFTUP - case "mac": - return 2; // NSEventTypeLeftMouseUp - case "linux": - return 7; // GDK_BUTTON_RELEASE - case "android": - return 6; // ACTION_POINTER_UP - } - throw new Error( - "Native mouse-up events not supported on platform " + getPlatform() - ); -} - function parseNativeModifiers(aModifiers, aWindow = window) { let modifiers = 0; if (aModifiers.capsLockKey) { @@ -794,14 +746,16 @@ function synthesizeNativeMouseEventWithAPZ(aParams, aObserver = null) { utils.sendNativeMouseEvent( pt.x, pt.y, - nativeMouseDownEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_DOWN, + 0, modifierFlags, element, function() { utils.sendNativeMouseEvent( pt.x, pt.y, - nativeMouseUpEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_UP, + 0, modifierFlags, element, aObserver @@ -817,15 +771,16 @@ function synthesizeNativeMouseEventWithAPZ(aParams, aObserver = null) { (() => { switch (type) { case "mousedown": - return nativeMouseDownEventMsg(); + return utils.NATIVE_MOUSE_MESSAGE_BUTTON_DOWN; case "mouseup": - return nativeMouseUpEventMsg(); + return utils.NATIVE_MOUSE_MESSAGE_BUTTON_UP; case "mousemove": - return nativeMouseMoveEventMsg(); + return utils.NATIVE_MOUSE_MESSAGE_MOVE; default: throw Error(`Invalid type is specified: ${type}`); } })(), + 0, modifierFlags, element, aObserver diff --git a/layout/base/tests/browser_select_popup_position_in_out_of_process_iframe.js b/layout/base/tests/browser_select_popup_position_in_out_of_process_iframe.js index 44898dbfe895..631c77438cd6 100644 --- a/layout/base/tests/browser_select_popup_position_in_out_of_process_iframe.js +++ b/layout/base/tests/browser_select_popup_position_in_out_of_process_iframe.js @@ -23,14 +23,16 @@ function synthesizeNativeMouseClick(aWin, aScreenX, aScreenY) { utils.sendNativeMouseEvent( aScreenX * scale, aScreenY * scale, - nativeMouseDownEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_DOWN, + 0, 0, aWin.document.documentElement, () => { utils.sendNativeMouseEvent( aScreenX * scale, aScreenY * scale, - nativeMouseUpEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_UP, + 0, 0, aWin.document.documentElement ); diff --git a/layout/xul/test/test_bug987230.xhtml b/layout/xul/test/test_bug987230.xhtml index 2d406dc8e0d6..78c94806db9e 100644 --- a/layout/xul/test/test_bug987230.xhtml +++ b/layout/xul/test/test_bug987230.xhtml @@ -51,10 +51,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=987230 SimpleTest.requestCompleteLog(); - let platform = navigator.platform.toLowerCase(); - let isWindows = platform.startsWith("win"); - let mouseMove = isWindows ? 1 : 5; - function onMyPopupHidden(e) { ok(true, "Popup hidden"); if (outerAnchor.id == "toolbarbutton-anchor") { @@ -73,7 +69,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=987230 info("Mousemove: " + outsideOfFrameX + ", " + outsideOfFrameY + " (from innerscreen " + window.mozInnerScreenX + ", " + window.mozInnerScreenY + " and rect width " + frameRect.width + " and scale " + scale + ")"); - utils.sendNativeMouseEvent(outsideOfFrameX, outsideOfFrameY, mouseMove, 0, null); + utils.sendNativeMouseEvent( + outsideOfFrameX, + outsideOfFrameY, + utils.NATIVE_MOUSE_MESSAGE_MOVE, + 0, + 0, + null + ); SimpleTest.finish(); } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java index 7c3054baa28c..1d1cd567aa3a 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java @@ -214,15 +214,15 @@ public class PanZoomController { throw new IllegalArgumentException("Pointer ID reserved for mouse"); } synthesizeNativePointer(InputDevice.SOURCE_TOUCHSCREEN, pointerId, - eventType, clientX, clientY, pressure, orientation); + eventType, clientX, clientY, pressure, orientation, 0); } @WrapForJNI(calledFrom = "ui") private void synthesizeNativeMouseEvent(final int eventType, final int clientX, - final int clientY) { + final int clientY, final int button) { synthesizeNativePointer(InputDevice.SOURCE_MOUSE, PointerInfo.RESERVED_MOUSE_POINTER_ID, - eventType, clientX, clientY, 0, 0); + eventType, clientX, clientY, 0, 0, button); } @WrapForJNI(calledFrom = "ui") @@ -527,6 +527,7 @@ public class PanZoomController { public int surfaceY; public double pressure; public int orientation; + public int buttonState; public MotionEvent.PointerCoords getCoords() { MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords(); @@ -573,6 +574,15 @@ public class PanZoomController { return count; } + int getPointerButtonState(final int source) { + for (int i = 0; i < pointers.size(); i++) { + if (pointers.get(i).source == source) { + return pointers.get(i).buttonState; + } + } + return 0; + } + MotionEvent.PointerProperties[] getPointerProperties(final int source) { MotionEvent.PointerProperties[] props = new MotionEvent.PointerProperties[getPointerCount(source)]; @@ -611,7 +621,8 @@ public class PanZoomController { private void synthesizeNativePointer(final int source, final int pointerId, final int originalEventType, final int clientX, final int clientY, - final double pressure, final int orientation) { + final double pressure, final int orientation, + final int button) { if (mPointerState == null) { mPointerState = new SynthesizedEventState(); } @@ -677,6 +688,14 @@ public class PanZoomController { info.surfaceY = surfaceY; info.pressure = pressure; info.orientation = orientation; + if (source == InputDevice.SOURCE_MOUSE) { + if (eventType == MotionEvent.ACTION_DOWN || + eventType == MotionEvent.ACTION_MOVE) { + info.buttonState |= button; + } else if (eventType == MotionEvent.ACTION_UP) { + info.buttonState &= button; + } + } // Dispatch the event int action = 0; @@ -688,9 +707,6 @@ public class PanZoomController { action &= MotionEvent.ACTION_POINTER_INDEX_MASK; } action |= (eventType & MotionEvent.ACTION_MASK); - boolean isButtonDown = (source == InputDevice.SOURCE_MOUSE) && - (eventType == MotionEvent.ACTION_DOWN || - eventType == MotionEvent.ACTION_MOVE); final MotionEvent event = MotionEvent.obtain( /*downTime*/ mPointerState.downTime, /*eventTime*/ SystemClock.uptimeMillis(), @@ -699,7 +715,7 @@ public class PanZoomController { /*pointerProperties*/ mPointerState.getPointerProperties(source), /*pointerCoords*/ mPointerState.getPointerCoords(source), /*metaState*/ 0, - /*buttonState*/ (isButtonDown ? MotionEvent.BUTTON_PRIMARY : 0), + /*buttonState*/ mPointerState.getPointerButtonState(source), /*xPrecision*/ 0, /*yPrecision*/ 0, /*deviceId*/ 0, diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js index 0a2b7ec36f84..b291aa9d9a38 100644 --- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -155,54 +155,6 @@ function _EU_getPlatform() { return "unknown"; } -function _EU_nativeMouseDownEventMsg() { - switch (_EU_getPlatform()) { - case "windows": - return 2; // MOUSEEVENTF_LEFTDOWN - case "mac": - return 1; // NSEventTypeLeftMouseDown - case "linux": - return 4; // GDK_BUTTON_PRESS - case "android": - return 5; // ACTION_POINTER_DOWN - } - throw new Error( - "Native mouse-down events not supported on platform " + _EU_getPlatform() - ); -} - -function _EU_nativeMouseMoveEventMsg() { - switch (_EU_getPlatform()) { - case "windows": - return 1; // MOUSEEVENTF_MOVE - case "mac": - return 5; // NSEventTypeMouseMoved - case "linux": - return 3; // GDK_MOTION_NOTIFY - case "android": - return 7; // ACTION_HOVER_MOVE - } - throw new Error( - "Native mouse-move events not supported on platform " + _EU_getPlatform() - ); -} - -function _EU_nativeMouseUpEventMsg() { - switch (_EU_getPlatform()) { - case "windows": - return 4; // MOUSEEVENTF_LEFTUP - case "mac": - return 2; // NSEventTypeLeftMouseUp - case "linux": - return 7; // GDK_BUTTON_RELEASE - case "android": - return 6; // ACTION_POINTER_UP - } - throw new Error( - "Native mouse-up events not supported on platform " + _EU_getPlatform() - ); -} - /** * Send a mouse event to the node aTarget (aTarget can be an id, or an * actual node) . The "event" passed in to aEvent is just a JavaScript @@ -1120,14 +1072,16 @@ function synthesizeNativeMouseEvent(aParams, aCallback = null) { utils.sendNativeMouseEvent( x, y, - _EU_nativeMouseDownEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_DOWN, + 0, modifierFlags, null, function() { utils.sendNativeMouseEvent( x, y, - _EU_nativeMouseUpEventMsg(), + utils.NATIVE_MOUSE_MESSAGE_BUTTON_UP, + 0, modifierFlags, null, observer @@ -1142,15 +1096,16 @@ function synthesizeNativeMouseEvent(aParams, aCallback = null) { (() => { switch (type) { case "mousedown": - return _EU_nativeMouseDownEventMsg(); + return utils.NATIVE_MOUSE_MESSAGE_BUTTON_DOWN; case "mouseup": - return _EU_nativeMouseUpEventMsg(); + return utils.NATIVE_MOUSE_MESSAGE_BUTTON_UP; case "mousemove": - return _EU_nativeMouseMoveEventMsg(); + return utils.NATIVE_MOUSE_MESSAGE_MOVE; default: throw Error(`Invalid type is specified: ${type}`); } })(), + 0, modifierFlags, null, observer diff --git a/widget/EventForwards.h b/widget/EventForwards.h index cfb90940efba..203af156ac6c 100644 --- a/widget/EventForwards.h +++ b/widget/EventForwards.h @@ -438,11 +438,13 @@ typedef nsTArray> OwningNonNullStaticRangeArray; // FontRange.h struct FontRange; -enum MouseButton { +enum MouseButton : int16_t { eNotPressed = -1, ePrimary = 0, eMiddle = 1, - eSecondary = 2 + eSecondary = 2, + eX1 = 3, // Typically, "back" button + eX2 = 4, // Typically, "forward" button }; enum MouseButtonsFlag { diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index a57ab1746265..e5d75d58c4e7 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -427,14 +427,16 @@ nsresult PuppetWidget::SynthesizeNativeKeyEvent( } nsresult PuppetWidget::SynthesizeNativeMouseEvent( - mozilla::LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) { + mozilla::LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) { AutoObserverNotifier notifier(aObserver, "mouseevent"); if (!mBrowserChild) { return NS_ERROR_FAILURE; } mBrowserChild->SendSynthesizeNativeMouseEvent( - aPoint, aNativeMessage, static_cast(aModifierFlags), + aPoint, static_cast(aNativeMessage), + static_cast(aButton), static_cast(aModifierFlags), notifier.SaveObserver()); return NS_OK; } diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index 828c58af9201..31c35c3e3fe3 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -252,8 +252,9 @@ class PuppetWidget : public nsBaseWidget, uint32_t aModifierFlags, const nsAString& aCharacters, const nsAString& aUnmodifiedCharacters, nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override; + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseScrollEvent( diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 3244f9850ec4..b094113b3965 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2439,8 +2439,9 @@ nsresult nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId, } nsresult nsWindow::SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) { + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) { mozilla::widget::AutoObserverNotifier notifier(aObserver, "mouseevent"); MOZ_ASSERT(mNPZCSupport.IsAttached()); @@ -2452,37 +2453,63 @@ nsresult nsWindow::SynthesizeNativeMouseEvent( aPoint.x -= bounds.x; aPoint.y -= bounds.y; + int32_t nativeMessage; + switch (aNativeMessage) { + case NativeMouseMessage::ButtonDown: + nativeMessage = java::sdk::MotionEvent::ACTION_POINTER_DOWN; + break; + case NativeMouseMessage::ButtonUp: + nativeMessage = java::sdk::MotionEvent::ACTION_POINTER_UP; + break; + case NativeMouseMessage::Move: + nativeMessage = java::sdk::MotionEvent::ACTION_HOVER_MOVE; + break; + default: + MOZ_ASSERT_UNREACHABLE("Non supported mouse event on Android"); + return NS_ERROR_INVALID_ARG; + } + int32_t button; + switch (aButton) { + case MouseButton::ePrimary: + button = java::sdk::MotionEvent::BUTTON_PRIMARY; + break; + case MouseButton::eMiddle: + button = java::sdk::MotionEvent::BUTTON_TERTIARY; + break; + case MouseButton::eSecondary: + button = java::sdk::MotionEvent::BUTTON_SECONDARY; + break; + case MouseButton::eX1: + button = java::sdk::MotionEvent::BUTTON_BACK; + break; + case MouseButton::eX2: + button = java::sdk::MotionEvent::BUTTON_FORWARD; + break; + default: + if (aNativeMessage != NativeMouseMessage::ButtonDown && + aNativeMessage != NativeMouseMessage::ButtonUp) { + button = 0; + break; + } + return NS_ERROR_INVALID_ARG; + } + // TODO (bug 1693237): Handle aModifierFlags. DispatchToUiThread( "nsWindow::SynthesizeNativeMouseEvent", [npzc = java::PanZoomController::NativeProvider::GlobalRef(npzc), - aNativeMessage, aPoint] { - npzc->SynthesizeNativeMouseEvent(aNativeMessage, aPoint.x, aPoint.y); + nativeMessage, aPoint, button] { + npzc->SynthesizeNativeMouseEvent(nativeMessage, aPoint.x, aPoint.y, + button); }); return NS_OK; } nsresult nsWindow::SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, nsIObserver* aObserver) { - mozilla::widget::AutoObserverNotifier notifier(aObserver, "mouseevent"); - - MOZ_ASSERT(mNPZCSupport.IsAttached()); - auto npzcSup(mNPZCSupport.Access()); - MOZ_ASSERT(!!npzcSup); - - const auto& npzc = npzcSup->GetJavaNPZC(); - const auto& bounds = FindTopLevel()->mBounds; - aPoint.x -= bounds.x; - aPoint.y -= bounds.y; - - DispatchToUiThread( - "nsWindow::SynthesizeNativeMouseMove", - [npzc = java::PanZoomController::NativeProvider::GlobalRef(npzc), - aPoint] { - npzc->SynthesizeNativeMouseEvent( - java::sdk::MotionEvent::ACTION_HOVER_MOVE, aPoint.x, aPoint.y); - }); - return NS_OK; + return SynthesizeNativeMouseEvent( + aPoint, NativeMouseMessage::Move, MouseButton::eNotPressed, + nsIWidget::Modifiers::NO_MODIFIERS, aObserver); } bool nsWindow::WidgetPaintsBackground() { diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 183bca8546f9..52f4bce29b5c 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -201,7 +201,8 @@ class nsWindow final : public nsBaseWidget { uint32_t aPointerOrientation, nsIObserver* aObserver) override; nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, + NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override; nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index 2ba4ebe3404f..c2adbc21f8cb 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -386,13 +386,16 @@ class nsChildView final : public nsBaseWidget { const nsAString& aUnmodifiedCharacters, nsIObserver* aObserver) override; - virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, + virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, + NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, nsIObserver* aObserver) override { - return SynthesizeNativeMouseEvent(aPoint, NSEventTypeMouseMoved, + return SynthesizeNativeMouseEvent(aPoint, NativeMouseMessage::Move, + mozilla::MouseButton::eNotPressed, nsIWidget::Modifiers::NO_MODIFIERS, aObserver); } virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint, diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index cf94282cfaef..7e60e582e2e3 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -868,7 +868,8 @@ nsresult nsChildView::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, } nsresult nsChildView::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, + NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) { NS_OBJC_BEGIN_TRY_BLOCK_RETURN; @@ -888,7 +889,49 @@ nsresult nsChildView::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, NSEventModifierFlags modifierFlags = nsCocoaUtils::ConvertWidgetModifiersToMacModifierFlags(aModifierFlags); - NSEvent* event = [NSEvent mouseEventWithType:(NSEventType)aNativeMessage + if (aButton == MouseButton::eX1 || aButton == MouseButton::eX2) { + // NSEvent has `buttonNumber` for `NSEventTypeOther*`. However, it seems that + // there is no way to specify it. Therefore, we should return error for now. + return NS_ERROR_INVALID_ARG; + } + + NSEventType nativeEventType; + switch (aNativeMessage) { + case NativeMouseMessage::ButtonDown: + case NativeMouseMessage::ButtonUp: { + switch (aButton) { + case MouseButton::ePrimary: + nativeEventType = aNativeMessage == NativeMouseMessage::ButtonDown + ? NSEventTypeLeftMouseDown + : NSEventTypeLeftMouseUp; + break; + case MouseButton::eMiddle: + nativeEventType = aNativeMessage == NativeMouseMessage::ButtonDown + ? NSEventTypeOtherMouseDown + : NSEventTypeOtherMouseUp; + break; + case MouseButton::eSecondary: + nativeEventType = aNativeMessage == NativeMouseMessage::ButtonDown + ? NSEventTypeRightMouseDown + : NSEventTypeRightMouseUp; + break; + default: + return NS_ERROR_INVALID_ARG; + } + break; + } + case NativeMouseMessage::Move: + nativeEventType = NSEventTypeMouseMoved; + break; + case NativeMouseMessage::EnterWindow: + nativeEventType = NSEventTypeMouseEntered; + break; + case NativeMouseMessage::LeaveWindow: + nativeEventType = NSEventTypeMouseExited; + break; + } + + NSEvent* event = [NSEvent mouseEventWithType:nativeEventType location:windowPoint modifierFlags:modifierFlags timestamp:[[NSProcessInfo processInfo] systemUptime] @@ -904,15 +947,15 @@ nsresult nsChildView::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, // Tracking area events don't end up in their tracking areas when sent // through [NSApp sendEvent:], so pass them directly to the right methods. BaseWindow* window = (BaseWindow*)[mView window]; - if (aNativeMessage == NSEventTypeMouseEntered) { + if (nativeEventType == NSEventTypeMouseEntered) { [window mouseEntered:event]; return NS_OK; } - if (aNativeMessage == NSEventTypeMouseExited) { + if (nativeEventType == NSEventTypeMouseExited) { [window mouseExited:event]; return NS_OK; } - if (aNativeMessage == NSEventTypeMouseMoved) { + if (nativeEventType == NSEventTypeMouseMoved) { [window mouseMoved:event]; return NS_OK; } diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index f0faa21a8b92..bd341bd2f0f8 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -304,7 +304,9 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa { virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; virtual void SetDrawsInTitlebar(bool aState) override; virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) override; - virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, + virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, + NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint, diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 30d941c6440c..183193725647 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2442,16 +2442,18 @@ void nsCocoaWindow::SetDrawsInTitlebar(bool aState) { } NS_IMETHODIMP nsCocoaWindow::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, + NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) { NS_OBJC_BEGIN_TRY_BLOCK_RETURN; AutoObserverNotifier notifier(aObserver, "mouseevent"); if (mPopupContentView) { - return mPopupContentView->SynthesizeNativeMouseEvent(aPoint, aNativeMessage, aModifierFlags, - nullptr); + return mPopupContentView->SynthesizeNativeMouseEvent(aPoint, aNativeMessage, aButton, + aModifierFlags, nullptr); } + return NS_OK; NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE); diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index b063c46a3e90..8dc9d3eac8e1 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -7869,8 +7869,9 @@ LayoutDeviceIntRect nsWindow::GdkRectToDevicePixels(GdkRectangle rect) { } nsresult nsWindow::SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) { + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) { AutoObserverNotifier notifier(aObserver, "mouseevent"); if (!mGdkWindow) { @@ -7884,40 +7885,62 @@ nsresult nsWindow::SynthesizeNativeMouseEvent( // done explicitly *before* requesting a button-press/release. You will also // need to wait for the motion event to be dispatched before requesting a // button-press/release event to maintain the desired event order. - if (aNativeMessage == GDK_BUTTON_PRESS || - aNativeMessage == GDK_BUTTON_RELEASE) { - GdkEvent event; - memset(&event, 0, sizeof(GdkEvent)); - event.type = (GdkEventType)aNativeMessage; - event.button.button = 1; - event.button.state = - KeymapWrapper::ConvertWidgetModifierToGdkState(aModifierFlags); - event.button.window = mGdkWindow; - event.button.time = GDK_CURRENT_TIME; + switch (aNativeMessage) { + case NativeMouseMessage::ButtonDown: + case NativeMouseMessage::ButtonUp: { + GdkEvent event; + memset(&event, 0, sizeof(GdkEvent)); + event.type = aNativeMessage == NativeMouseMessage::ButtonDown + ? GDK_BUTTON_PRESS + : GDK_BUTTON_RELEASE; + switch (aButton) { + case MouseButton::ePrimary: + case MouseButton::eMiddle: + case MouseButton::eSecondary: + case MouseButton::eX1: + case MouseButton::eX2: + event.button.button = aButton + 1; + break; + default: + return NS_ERROR_INVALID_ARG; + } + event.button.state = + KeymapWrapper::ConvertWidgetModifierToGdkState(aModifierFlags); + event.button.window = mGdkWindow; + event.button.time = GDK_CURRENT_TIME; - // Get device for event source - GdkDeviceManager* device_manager = gdk_display_get_device_manager(display); - event.button.device = gdk_device_manager_get_client_pointer(device_manager); + // Get device for event source + GdkDeviceManager* device_manager = + gdk_display_get_device_manager(display); + event.button.device = + gdk_device_manager_get_client_pointer(device_manager); - event.button.x_root = DevicePixelsToGdkCoordRoundDown(aPoint.x); - event.button.y_root = DevicePixelsToGdkCoordRoundDown(aPoint.y); + event.button.x_root = DevicePixelsToGdkCoordRoundDown(aPoint.x); + event.button.y_root = DevicePixelsToGdkCoordRoundDown(aPoint.y); - LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset(); - event.button.x = DevicePixelsToGdkCoordRoundDown(pointInWindow.x); - event.button.y = DevicePixelsToGdkCoordRoundDown(pointInWindow.y); + LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset(); + event.button.x = DevicePixelsToGdkCoordRoundDown(pointInWindow.x); + event.button.y = DevicePixelsToGdkCoordRoundDown(pointInWindow.y); - gdk_event_put(&event); - } else { - // We don't support specific events other than button-press/release. In all - // other cases we'll synthesize a motion event that will be emitted by - // gdk_display_warp_pointer(). - // XXX How to activate native modifier for the other events? - GdkScreen* screen = gdk_window_get_screen(mGdkWindow); - GdkPoint point = DevicePixelsToGdkPointRoundDown(aPoint); - gdk_display_warp_pointer(display, screen, point.x, point.y); + gdk_event_put(&event); + return NS_OK; + } + case NativeMouseMessage::Move: { + // We don't support specific events other than button-press/release. In + // all other cases we'll synthesize a motion event that will be emitted by + // gdk_display_warp_pointer(). + // XXX How to activate native modifier for the other events? + GdkScreen* screen = gdk_window_get_screen(mGdkWindow); + GdkPoint point = DevicePixelsToGdkPointRoundDown(aPoint); + gdk_display_warp_pointer(display, screen, point.x, point.y); + return NS_OK; + } + case NativeMouseMessage::EnterWindow: + case NativeMouseMessage::LeaveWindow: + MOZ_ASSERT_UNREACHABLE("Non supported mouse event on Linux"); + return NS_ERROR_INVALID_ARG; } - - return NS_OK; + return NS_ERROR_UNEXPECTED; } nsresult nsWindow::SynthesizeNativeMouseScrollEvent( diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index c61c68300145..37a2f2df4d89 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -342,14 +342,15 @@ class nsWindow final : public nsBaseWidget { virtual void ReparentNativeWidget(nsIWidget* aNewParent) override; virtual nsresult SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override; + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, nsIObserver* aObserver) override { - return SynthesizeNativeMouseEvent(aPoint, GDK_MOTION_NOTIFY, - nsIWidget::Modifiers::NO_MODIFIERS, - aObserver); + return SynthesizeNativeMouseEvent( + aPoint, NativeMouseMessage::Move, mozilla::MouseButton::eNotPressed, + nsIWidget::Modifiers::NO_MODIFIERS, aObserver); } virtual nsresult SynthesizeNativeMouseScrollEvent( diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp index 20ae275e1b83..b92ac317b054 100644 --- a/widget/headless/HeadlessWidget.cpp +++ b/widget/headless/HeadlessWidget.cpp @@ -433,28 +433,30 @@ nsresult HeadlessWidget::DispatchEvent(WidgetGUIEvent* aEvent, } nsresult HeadlessWidget::SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) { + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) { AutoObserverNotifier notifier(aObserver, "mouseevent"); EventMessage msg; switch (aNativeMessage) { - case MOZ_HEADLESS_MOUSE_MOVE: + case NativeMouseMessage::Move: msg = eMouseMove; break; - case MOZ_HEADLESS_MOUSE_DOWN: + case NativeMouseMessage::ButtonDown: msg = eMouseDown; break; - case MOZ_HEADLESS_MOUSE_UP: + case NativeMouseMessage::ButtonUp: msg = eMouseUp; break; - default: + case NativeMouseMessage::EnterWindow: + case NativeMouseMessage::LeaveWindow: MOZ_ASSERT_UNREACHABLE("Unsupported synthesized mouse event"); return NS_ERROR_UNEXPECTED; } WidgetMouseEvent event(true, msg, this, WidgetMouseEvent::eReal); event.mRefPoint = aPoint - WidgetToScreenOffset(); if (msg == eMouseDown || msg == eMouseUp) { - event.mButton = MouseButton::ePrimary; + event.mButton = aButton; } if (msg == eMouseDown) { event.mClickCount = 1; diff --git a/widget/headless/HeadlessWidget.h b/widget/headless/HeadlessWidget.h index 8ae9a0059575..225f9636dd5c 100644 --- a/widget/headless/HeadlessWidget.h +++ b/widget/headless/HeadlessWidget.h @@ -14,38 +14,23 @@ // The various synthesized event values are hardcoded to avoid pulling // in the platform specific widget code. #if defined(MOZ_WIDGET_GTK) -# define MOZ_HEADLESS_MOUSE_MOVE 3 // GDK_MOTION_NOTIFY -# define MOZ_HEADLESS_MOUSE_DOWN 4 // GDK_BUTTON_PRESS -# define MOZ_HEADLESS_MOUSE_UP 7 // GDK_BUTTON_RELEASE # define MOZ_HEADLESS_SCROLL_MULTIPLIER 3 # define MOZ_HEADLESS_SCROLL_DELTA_MODE \ mozilla::dom::WheelEvent_Binding::DOM_DELTA_LINE #elif defined(XP_WIN) -# define MOZ_HEADLESS_MOUSE_MOVE 1 // MOUSEEVENTF_MOVE -# define MOZ_HEADLESS_MOUSE_DOWN 2 // MOUSEEVENTF_LEFTDOWN -# define MOZ_HEADLESS_MOUSE_UP 4 // MOUSEEVENTF_LEFTUP # define MOZ_HEADLESS_SCROLL_MULTIPLIER \ .025 // default scroll lines (3) / WHEEL_DELTA (120) # define MOZ_HEADLESS_SCROLL_DELTA_MODE \ mozilla::dom::WheelEvent_Binding::DOM_DELTA_LINE #elif defined(XP_MACOSX) -# define MOZ_HEADLESS_MOUSE_MOVE 5 // NSEventTypeMouseMoved -# define MOZ_HEADLESS_MOUSE_DOWN 1 // NSEventTypeLeftMouseDown -# define MOZ_HEADLESS_MOUSE_UP 2 // NSEventTypeLeftMouseUp # define MOZ_HEADLESS_SCROLL_MULTIPLIER 1 # define MOZ_HEADLESS_SCROLL_DELTA_MODE \ mozilla::dom::WheelEvent_Binding::DOM_DELTA_PIXEL #elif defined(ANDROID) -# define MOZ_HEADLESS_MOUSE_MOVE 7 // ACTION_HOVER_MOVE -# define MOZ_HEADLESS_MOUSE_DOWN 5 // ACTION_POINTER_DOWN -# define MOZ_HEADLESS_MOUSE_UP 6 // ACTION_POINTER_UP # define MOZ_HEADLESS_SCROLL_MULTIPLIER 1 # define MOZ_HEADLESS_SCROLL_DELTA_MODE \ mozilla::dom::WheelEvent_Binding::DOM_DELTA_LINE #else -# define MOZ_HEADLESS_MOUSE_MOVE -1 -# define MOZ_HEADLESS_MOUSE_DOWN -1 -# define MOZ_HEADLESS_MOUSE_UP -1 # define MOZ_HEADLESS_SCROLL_MULTIPLIER -1 # define MOZ_HEADLESS_SCROLL_DELTA_MODE -1 #endif @@ -132,13 +117,14 @@ class HeadlessWidget : public nsBaseWidget { nsEventStatus& aStatus) override; virtual nsresult SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override; + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) override; virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, nsIObserver* aObserver) override { - return SynthesizeNativeMouseEvent(aPoint, MOZ_HEADLESS_MOUSE_MOVE, - nsIWidget::Modifiers::NO_MODIFIERS, - aObserver); + return SynthesizeNativeMouseEvent( + aPoint, NativeMouseMessage::Move, mozilla::MouseButton::eNotPressed, + nsIWidget::Modifiers::NO_MODIFIERS, aObserver); }; virtual nsresult SynthesizeNativeMouseScrollEvent( diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index c06af15d5795..0b0f7e29d63c 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -488,8 +488,9 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { } virtual nsresult SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) override { + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) override { mozilla::widget::AutoObserverNotifier notifier(aObserver, "mouseevent"); return NS_ERROR_UNEXPECTED; } diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 388322c31649..42913bd0b2be 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1576,18 +1576,25 @@ class nsIWidget : public nsISupports { * z-order. * @param aPoint screen location of the mouse, in device * pixels, with origin at the top left - * @param aNativeMessage *platform-specific* event type (e.g. on Mac, - * NSEventTypeMouseMoved; on Windows, MOUSEEVENTF_MOVE, MOUSEEVENTF_LEFTDOWN - * etc) + * @param aNativeMessage abstract native message. + * @param aButton Mouse button defined by DOM UI Events. * @param aModifierFlags Some values of nsIWidget::Modifiers. * FYI: On Windows, Android and Headless widget on all * platroms, this hasn't been handled yet. * @param aObserver the observer that will get notified once the events * have been dispatched. */ + enum class NativeMouseMessage : uint32_t { + ButtonDown, // button down + ButtonUp, // button up + Move, // mouse cursor move + EnterWindow, // mouse cursor comes into a window + LeaveWindow, // mouse cursor leaves from a window + }; virtual nsresult SynthesizeNativeMouseEvent( - LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, - nsIWidget::Modifiers aModifierFlags, nsIObserver* aObserver) = 0; + LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) = 0; /** * A shortcut to SynthesizeNativeMouseEvent, abstracting away the native diff --git a/widget/tests/test_bug596600.xhtml b/widget/tests/test_bug596600.xhtml index 6312590876fe..d31299dfe164 100644 --- a/widget/tests/test_bug596600.xhtml +++ b/widget/tests/test_bug596600.xhtml @@ -20,14 +20,20 @@