Bug 1264017 - Add an APZ test API to synthesize a mouse click. r=botond
MozReview-Commit-ID: EWp4BtdAHZz
--- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
@@ -39,25 +39,41 @@ function nativeScrollUnits(aElement, aDi
var targetWindow = aElement.ownerDocument.defaultView;
var lineHeight = targetWindow.getComputedStyle(aElement)["font-size"];
return aDimen / (parseInt(lineHeight) * 3);
}
}
return aDimen;
}
+function nativeMouseDownEventMsg() {
+ switch (getPlatform()) {
+ case "windows": return 2; // MOUSEEVENTF_LEFTDOWN
+ case "mac": return 1; // NSLeftMouseDown
+ case "linux": return 4; // GDK_BUTTON_PRESS
+ }
+}
+
function nativeMouseMoveEventMsg() {
switch (getPlatform()) {
case "windows": return 1; // MOUSEEVENTF_MOVE
case "mac": return 5; // NSMouseMoved
case "linux": return 3; // GDK_MOTION_NOTIFY
}
throw "Native wheel events not supported on platform " + getPlatform();
}
+function nativeMouseUpEventMsg() {
+ switch (getPlatform()) {
+ case "windows": return 4; // MOUSEEVENTF_LEFTUP
+ case "mac": return 2; // NSLeftMouseUp
+ case "linux": return 7; // GDK_BUTTON_RELEASE
+ }
+}
+
// Convert (aX, aY), in CSS pixels relative to aElement's bounding rect,
// to device pixels relative to aElement's containing window.
function coordinatesRelativeToWindow(aX, aY, aElement) {
var targetWindow = aElement.ownerDocument.defaultView;
var scale = targetWindow.devicePixelRatio;
var rect = aElement.getBoundingClientRect();
return {
x: (targetWindow.mozInnerScreenX + rect.left + aX) * scale,
@@ -172,8 +188,17 @@ function synthesizeNativeDrag(aElement,
}
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
return true;
}
+
+function synthesizeNativeClick(aElement, aX, aY, aObserver = null) {
+ var pt = coordinatesRelativeToWindow(aX, aY, aElement);
+ var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
+ utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseDownEventMsg(), 0, aElement, function() {
+ utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseUpEventMsg(), 0, aElement, aObserver);
+ });
+ return true;
+}
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -6806,40 +6806,47 @@ nsWindow::SynthesizeNativeMouseEvent(Lay
AutoObserverNotifier notifier(aObserver, "mouseevent");
if (!mGdkWindow) {
return NS_OK;
}
GdkDisplay* display = gdk_window_get_display(mGdkWindow);
- // When a button-release event is requested, create it here and put it in the
+ // When a button-press/release event is requested, create it here and put it in the
// event queue. This will not emit a motion event - this needs to be done
- // explicitly *before* requesting a button-release. You will also need to wait
- // for the motion event to be dispatched before requesting a button-release
+ // 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_RELEASE) {
+ 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.window = mGdkWindow;
event.button.time = GDK_CURRENT_TIME;
#if (MOZ_WIDGET_GTK == 3)
// 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);
#endif
+ 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);
+
gdk_event_put(&event);
} else {
- // We don't support specific events other than button-release. In case
- // aNativeMessage != GDK_BUTTON_RELEASE we'll synthesize a motion event
- // that will be emitted by gdk_display_warp_pointer().
+ // 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().
GdkScreen* screen = gdk_window_get_screen(mGdkWindow);
GdkPoint point = DevicePixelsToGdkPointRoundDown(aPoint);
gdk_display_warp_pointer(display, screen, point.x, point.y);
}
return NS_OK;
}