Bug 1249915 - Add ability to synthesize native touch events on GTK for mochitests. r?karlt
MozReview-Commit-ID: 86bU40UROEW
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -6838,13 +6838,94 @@ nsWindow::SynthesizeNativeMouseScrollEve
}
#endif
gdk_event_put(&event);
return NS_OK;
}
+#if GTK_CHECK_VERSION(3,4,0)
+nsresult
+nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
+ TouchPointerState aPointerState,
+ ScreenIntPoint aPointerScreenPoint,
+ double aPointerPressure,
+ uint32_t aPointerOrientation,
+ nsIObserver* aObserver)
+{
+ AutoObserverNotifier notifier(aObserver, "touchpoint");
+
+ if (!mGdkWindow) {
+ return NS_OK;
+ }
+
+ GdkEvent event;
+ memset(&event, 0, sizeof(GdkEvent));
+
+ static std::map<uint32_t, GdkEventSequence*> sKnownPointers;
+
+ auto result = sKnownPointers.find(aPointerId);
+ switch (aPointerState) {
+ case TOUCH_CONTACT:
+ if (result == sKnownPointers.end()) {
+ // GdkEventSequence isn't a thing we can instantiate, and never gets
+ // dereferenced in the gtk code. It's an opaque pointer, the only
+ // requirement is that it be distinct from other instances of
+ // GdkEventSequence*.
+ event.touch.sequence = (GdkEventSequence*)((size_t)aPointerId);
+ sKnownPointers[aPointerId] = event.touch.sequence;
+ event.type = GDK_TOUCH_BEGIN;
+ } else {
+ event.touch.sequence = result->second;
+ event.type = GDK_TOUCH_UPDATE;
+ }
+ break;
+ case TOUCH_REMOVE:
+ event.type = GDK_TOUCH_END;
+ if (result == sKnownPointers.end()) {
+ NS_WARNING("Tried to synthesize touch-end for unknown pointer!");
+ return NS_ERROR_UNEXPECTED;
+ }
+ event.touch.sequence = result->second;
+ sKnownPointers.erase(result);
+ break;
+ case TOUCH_CANCEL:
+ event.type = GDK_TOUCH_CANCEL;
+ if (result == sKnownPointers.end()) {
+ NS_WARNING("Tried to synthesize touch-cancel for unknown pointer!");
+ return NS_ERROR_UNEXPECTED;
+ }
+ event.touch.sequence = result->second;
+ sKnownPointers.erase(result);
+ break;
+ case TOUCH_HOVER:
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ event.touch.window = mGdkWindow;
+ event.touch.time = GDK_CURRENT_TIME;
+
+ GdkDisplay* display = gdk_window_get_display(mGdkWindow);
+ GdkDeviceManager* device_manager = gdk_display_get_device_manager(display);
+ event.touch.device = gdk_device_manager_get_client_pointer(device_manager);
+
+ event.touch.x_root = aPointerScreenPoint.x;
+ event.touch.y_root = aPointerScreenPoint.y;
+
+ ScreenIntPoint pointInWindow = aPointerScreenPoint
+ - ViewAs<ScreenPixel>(WidgetToScreenOffset(),
+ PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
+ event.touch.x = pointInWindow.x;
+ event.touch.y = pointInWindow.y;
+
+ gdk_event_put(&event);
+
+ return NS_OK;
+}
+#endif
+
int32_t
nsWindow::RoundsWidgetCoordinatesTo()
{
return GdkScaleFactor();
}
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -333,16 +333,25 @@ public:
uint32_t aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ,
uint32_t aModifierFlags,
uint32_t aAdditionalFlags,
nsIObserver* aObserver) override;
+#if GTK_CHECK_VERSION(3,4,0)
+ virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
+ TouchPointerState aPointerState,
+ ScreenIntPoint aPointerScreenPoint,
+ double aPointerPressure,
+ uint32_t aPointerOrientation,
+ nsIObserver* aObserver) override;
+#endif
+
// HiDPI scale conversion
gint GdkScaleFactor();
// To GDK
gint DevicePixelsToGdkCoordRoundUp(int pixels);
gint DevicePixelsToGdkCoordRoundDown(int pixels);
GdkPoint DevicePixelsToGdkPointRoundDown(LayoutDeviceIntPoint point);
GdkRectangle DevicePixelsToGdkSizeRoundUp(LayoutDeviceIntSize pixelSize);