mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
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
This commit is contained in:
parent
e675c8343f
commit
ef2253b4a1
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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<nsIWidget> widget = GetWidgetForElement(aElement);
|
||||
if (!widget) return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIWidget> 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<LayoutDeviceIntPoint, int32_t, nsIWidget::Modifiers,
|
||||
nsIObserver*>(
|
||||
NewRunnableMethod<LayoutDeviceIntPoint, nsIWidget::NativeMouseMessage,
|
||||
MouseButton, nsIWidget::Modifiers, nsIObserver*>(
|
||||
"nsIWidget::SynthesizeNativeMouseEvent", widget,
|
||||
&nsIWidget::SynthesizeNativeMouseEvent,
|
||||
LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage,
|
||||
GetWidgetModifiers(aModifierFlags), aObserver)));
|
||||
LayoutDeviceIntPoint(aScreenX, aScreenY), message,
|
||||
static_cast<MouseButton>(aButton), GetWidgetModifiers(aModifierFlags),
|
||||
aObserver)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
|
@ -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<nsIWidget> widget = GetWidget();
|
||||
if (widget) {
|
||||
widget->SynthesizeNativeMouseEvent(
|
||||
aPoint, aNativeMessage,
|
||||
aPoint, static_cast<nsIWidget::NativeMouseMessage>(aNativeMessage),
|
||||
static_cast<mozilla::MouseButton>(aButton),
|
||||
static_cast<nsIWidget::Modifiers>(aModifierFlags),
|
||||
responder.GetObserver());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -438,11 +438,13 @@ typedef nsTArray<OwningNonNull<dom::StaticRange>> 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 {
|
||||
|
@ -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<uint32_t>(aModifierFlags),
|
||||
aPoint, static_cast<uint32_t>(aNativeMessage),
|
||||
static_cast<int16_t>(aButton), static_cast<uint32_t>(aModifierFlags),
|
||||
notifier.SaveObserver());
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -2439,30 +2439,8 @@ nsresult nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
|
||||
}
|
||||
|
||||
nsresult nsWindow::SynthesizeNativeMouseEvent(
|
||||
LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage,
|
||||
nsIWidget::Modifiers aModifierFlags, 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;
|
||||
|
||||
// TODO (bug 1693237): Handle aModifierFlags.
|
||||
DispatchToUiThread(
|
||||
"nsWindow::SynthesizeNativeMouseEvent",
|
||||
[npzc = java::PanZoomController::NativeProvider::GlobalRef(npzc),
|
||||
aNativeMessage, aPoint] {
|
||||
npzc->SynthesizeNativeMouseEvent(aNativeMessage, aPoint.x, aPoint.y);
|
||||
});
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsWindow::SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
|
||||
LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage,
|
||||
MouseButton aButton, nsIWidget::Modifiers aModifierFlags,
|
||||
nsIObserver* aObserver) {
|
||||
mozilla::widget::AutoObserverNotifier notifier(aObserver, "mouseevent");
|
||||
|
||||
@ -2475,16 +2453,65 @@ nsresult nsWindow::SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
|
||||
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::SynthesizeNativeMouseMove",
|
||||
"nsWindow::SynthesizeNativeMouseEvent",
|
||||
[npzc = java::PanZoomController::NativeProvider::GlobalRef(npzc),
|
||||
aPoint] {
|
||||
npzc->SynthesizeNativeMouseEvent(
|
||||
java::sdk::MotionEvent::ACTION_HOVER_MOVE, 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) {
|
||||
return SynthesizeNativeMouseEvent(
|
||||
aPoint, NativeMouseMessage::Move, MouseButton::eNotPressed,
|
||||
nsIWidget::Modifiers::NO_MODIFIERS, aObserver);
|
||||
}
|
||||
|
||||
bool nsWindow::WidgetPaintsBackground() {
|
||||
return StaticPrefs::android_widget_paints_background();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<ThemeGeometry>& 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,
|
||||
|
@ -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);
|
||||
|
@ -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,20 +7885,35 @@ 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) {
|
||||
switch (aNativeMessage) {
|
||||
case NativeMouseMessage::ButtonDown:
|
||||
case NativeMouseMessage::ButtonUp: {
|
||||
GdkEvent event;
|
||||
memset(&event, 0, sizeof(GdkEvent));
|
||||
event.type = (GdkEventType)aNativeMessage;
|
||||
event.button.button = 1;
|
||||
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);
|
||||
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);
|
||||
@ -7907,17 +7923,24 @@ nsresult nsWindow::SynthesizeNativeMouseEvent(
|
||||
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
|
||||
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_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult nsWindow::SynthesizeNativeMouseScrollEvent(
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -20,14 +20,20 @@
|
||||
<![CDATA[
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const NSEventTypeMouseMoved = 5;
|
||||
|
||||
var gLeftWindow, gRightWindow, gBrowserElement;
|
||||
var gExpectedEvents = [];
|
||||
|
||||
function moveMouseTo(x, y, andThen) {
|
||||
var utils = gLeftWindow.windowUtils;
|
||||
utils.sendNativeMouseEvent(x, y, NSEventTypeMouseMoved, 0, gLeftWindow.documentElement);
|
||||
utils.sendNativeMouseEvent(
|
||||
x,
|
||||
y,
|
||||
utils.NATIVE_MOUSE_MESSAGE_MOVE,
|
||||
0,
|
||||
0,
|
||||
gLeftWindow.documentElement
|
||||
);
|
||||
SimpleTest.executeSoon(andThen);
|
||||
}
|
||||
|
||||
|
@ -29,29 +29,21 @@ SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let utils = window.windowUtils;
|
||||
let panel = document.getElementById('thepanel');
|
||||
let nativeMouseMove;
|
||||
let rect;
|
||||
|
||||
function startTest() {
|
||||
let widgetToolkit = SpecialPowers.Services.appinfo.widgetToolkit;
|
||||
|
||||
if (widgetToolkit == "cocoa") {
|
||||
nativeMouseMove = 5; // NSEventTypeMouseMoved
|
||||
} else if (widgetToolkit == "windows") {
|
||||
nativeMouseMove = 1; // MOUSEEVENTF_MOVE
|
||||
} else if (/^gtk/.test(widgetToolkit)) {
|
||||
nativeMouseMove = 3; // GDK_MOTION_NOTIFY
|
||||
} else {
|
||||
todo_is("widgetToolkit", widgetToolkit, "Platform not supported");
|
||||
done();
|
||||
}
|
||||
|
||||
// This first event is to ensure that the next event will have different
|
||||
// coordinates to the previous mouse position, and so actually generates
|
||||
// mouse events. The mouse is not moved off the window, as that might
|
||||
// move focus to another application.
|
||||
utils.sendNativeMouseEvent(window.mozInnerScreenX, window.mozInnerScreenY,
|
||||
nativeMouseMove, 0, window.documentElement);
|
||||
utils.sendNativeMouseEvent(
|
||||
window.mozInnerScreenX,
|
||||
window.mozInnerScreenY,
|
||||
utils.NATIVE_MOUSE_MESSAGE_MOVE,
|
||||
0,
|
||||
0,
|
||||
window.documentElement
|
||||
);
|
||||
|
||||
panel.openPopup(document.getElementById("anchor"), "after_start");
|
||||
}
|
||||
@ -60,7 +52,12 @@ function sendMouseEvent() {
|
||||
rect = panel.getBoundingClientRect();
|
||||
let x = window.mozInnerScreenX + rect.left + 1;
|
||||
let y = window.mozInnerScreenY + rect.top + 2;
|
||||
utils.sendNativeMouseEvent(x, y, nativeMouseMove, 0,
|
||||
utils.sendNativeMouseEvent(
|
||||
x,
|
||||
y,
|
||||
utils.NATIVE_MOUSE_MESSAGE_MOVE,
|
||||
0,
|
||||
0,
|
||||
window.documentElement);
|
||||
}
|
||||
|
||||
|
@ -6605,18 +6605,11 @@ nsresult nsWindow::SynthesizeNativeKeyEvent(
|
||||
}
|
||||
|
||||
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 (aNativeMessage == MOUSEEVENTF_MOVE) {
|
||||
// Reset sLastMouseMovePoint so that even if we're moving the mouse
|
||||
// to the position it's already at, we still dispatch a mousemove
|
||||
// event, because the callers of this function expect that.
|
||||
sLastMouseMovePoint = {0};
|
||||
}
|
||||
::SetCursorPos(aPoint.x, aPoint.y);
|
||||
|
||||
INPUT input;
|
||||
memset(&input, 0, sizeof(input));
|
||||
|
||||
@ -6627,8 +6620,50 @@ nsresult nsWindow::SynthesizeNativeMouseEvent(
|
||||
// being handled, and MOUSEEVENTF_MOVE may be coalesced by Windows. So, we
|
||||
// need a trick for handling it.
|
||||
|
||||
switch (aNativeMessage) {
|
||||
case NativeMouseMessage::Move:
|
||||
input.mi.dwFlags = MOUSEEVENTF_MOVE;
|
||||
// Reset sLastMouseMovePoint so that even if we're moving the mouse
|
||||
// to the position it's already at, we still dispatch a mousemove
|
||||
// event, because the callers of this function expect that.
|
||||
sLastMouseMovePoint = {0};
|
||||
break;
|
||||
case NativeMouseMessage::ButtonDown:
|
||||
case NativeMouseMessage::ButtonUp: {
|
||||
const bool isDown = aNativeMessage == NativeMouseMessage::ButtonDown;
|
||||
switch (aButton) {
|
||||
case MouseButton::ePrimary:
|
||||
input.mi.dwFlags = isDown ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
|
||||
break;
|
||||
case MouseButton::eMiddle:
|
||||
input.mi.dwFlags =
|
||||
isDown ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
|
||||
break;
|
||||
case MouseButton::eSecondary:
|
||||
input.mi.dwFlags =
|
||||
isDown ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
|
||||
break;
|
||||
case MouseButton::eX1:
|
||||
input.mi.dwFlags = isDown ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
|
||||
input.mi.mouseData = XBUTTON1;
|
||||
break;
|
||||
case MouseButton::eX2:
|
||||
input.mi.dwFlags = isDown ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
|
||||
input.mi.mouseData = XBUTTON2;
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NativeMouseMessage::EnterWindow:
|
||||
case NativeMouseMessage::LeaveWindow:
|
||||
MOZ_ASSERT_UNREACHABLE("Non supported mouse event on Windows");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
input.type = INPUT_MOUSE;
|
||||
input.mi.dwFlags = aNativeMessage;
|
||||
::SetCursorPos(aPoint.x, aPoint.y);
|
||||
::SendInput(1, &input, sizeof(INPUT));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -223,14 +223,15 @@ class nsWindow final : public nsWindowBase {
|
||||
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,
|
||||
mozilla::MouseButton aButton, nsIWidget::Modifiers aModifierFlags,
|
||||
nsIObserver* aObserver) override;
|
||||
|
||||
virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
|
||||
nsIObserver* aObserver) override {
|
||||
return SynthesizeNativeMouseEvent(aPoint, MOUSEEVENTF_MOVE,
|
||||
nsIWidget::Modifiers::NO_MODIFIERS,
|
||||
aObserver);
|
||||
return SynthesizeNativeMouseEvent(
|
||||
aPoint, NativeMouseMessage::Move, mozilla::MouseButton::eNotPressed,
|
||||
nsIWidget::Modifiers::NO_MODIFIERS, aObserver);
|
||||
}
|
||||
|
||||
virtual nsresult SynthesizeNativeMouseScrollEvent(
|
||||
|
Loading…
Reference in New Issue
Block a user