diff --git a/gdk/gdkseatdefault.c b/gdk/gdkseatdefault.c index ce47df8230e3f5c16a10ab0ee060f8e0f3aa6c83..18d44662ec1e1472ddc14195c7f85cd66c38e971 100644 --- a/gdk/gdkseatdefault.c +++ b/gdk/gdkseatdefault.c @@ -43,7 +43,8 @@ struct _GdkSeatDefaultPrivate GDK_ENTER_NOTIFY_MASK | \ GDK_LEAVE_NOTIFY_MASK | \ GDK_PROXIMITY_IN_MASK | \ - GDK_PROXIMITY_OUT_MASK) + GDK_PROXIMITY_OUT_MASK | \ + GDK_TOUCHPAD_GESTURE_MASK) G_DEFINE_TYPE_WITH_PRIVATE (GdkSeatDefault, gdk_seat_default, GDK_TYPE_SEAT) diff --git a/gdk/x11/gdkdevice-xi2.c b/gdk/x11/gdkdevice-xi2.c index 5976dfafc486dcdb9f47b39a85bd37c77f95dcee..7062a7330a9a50675bb2beca4c77f003c4c58f17 100644 --- a/gdk/x11/gdkdevice-xi2.c +++ b/gdk/x11/gdkdevice-xi2.c @@ -619,6 +619,20 @@ _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager } #endif /* XINPUT_2_2 */ +#ifdef XINPUT_2_4 + /* XInput 2.4 includes touchpad gesture support */ + if (minor >= 4 && + event_mask & GDK_TOUCHPAD_GESTURE_MASK) + { + XISetMask (mask, XI_GesturePinchBegin); + XISetMask (mask, XI_GesturePinchUpdate); + XISetMask (mask, XI_GesturePinchEnd); + XISetMask (mask, XI_GestureSwipeBegin); + XISetMask (mask, XI_GestureSwipeUpdate); + XISetMask (mask, XI_GestureSwipeEnd); + } +#endif + return mask; } @@ -667,6 +681,36 @@ _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state, return state; } +#ifdef XINPUT_2_4 +guint +_gdk_x11_device_xi2_gesture_type_to_phase (int evtype, int flags) +{ + switch (evtype) + { + case XI_GesturePinchBegin: + case XI_GestureSwipeBegin: + return GDK_TOUCHPAD_GESTURE_PHASE_BEGIN; + + case XI_GesturePinchUpdate: + case XI_GestureSwipeUpdate: + return GDK_TOUCHPAD_GESTURE_PHASE_UPDATE; + + case XI_GesturePinchEnd: + if (flags & XIGesturePinchEventCancelled) + return GDK_TOUCHPAD_GESTURE_PHASE_CANCEL; + return GDK_TOUCHPAD_GESTURE_PHASE_END; + + case XI_GestureSwipeEnd: + if (flags & XIGestureSwipeEventCancelled) + return GDK_TOUCHPAD_GESTURE_PHASE_CANCEL; + return GDK_TOUCHPAD_GESTURE_PHASE_END; + default: + g_assert_not_reached (); + return GDK_TOUCHPAD_GESTURE_PHASE_END; + } +} +#endif /* XINPUT_2_4 */ + void _gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device, guint n_valuator, diff --git a/gdk/x11/gdkdevicemanager-x11.c b/gdk/x11/gdkdevicemanager-x11.c index c7b9743be016cf40dc1bb99609be33da2330b9f4..27a7d2007bc2e53b489320943e524284d0b21d2f 100644 --- a/gdk/x11/gdkdevicemanager-x11.c +++ b/gdk/x11/gdkdevicemanager-x11.c @@ -41,13 +41,15 @@ _gdk_x11_device_manager_new (GdkDisplay *display) int major, minor; major = 2; - minor = 3; + minor = 4; if (XIQueryVersion (xdisplay, &major, &minor) != BadRequest) { GdkX11DeviceManagerXI2 *device_manager_xi2; - GDK_DISPLAY_NOTE (display, INPUT, g_message ("Creating XI2 device manager")); + GDK_DISPLAY_NOTE (display, INPUT, + g_message ("Creating XI2 (version %d.%d) device manager", + major, minor)); device_manager_xi2 = g_object_new (GDK_TYPE_X11_DEVICE_MANAGER_XI2, "display", display, diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c index e4114e52796ae99ce504f016fa3df7c795870c21..9eb4e9bc560ade9247be92659263b14f45ddc861 100644 --- a/gdk/x11/gdkdevicemanager-xi2.c +++ b/gdk/x11/gdkdevicemanager-xi2.c @@ -1275,6 +1275,26 @@ get_event_surface (GdkEventTranslator *translator, } } break; +#ifdef XINPUT_2_4 + case XI_GesturePinchBegin: + case XI_GesturePinchUpdate: + case XI_GesturePinchEnd: + { + XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev; + + surface = gdk_x11_surface_lookup_for_display (display, xev->event); + } + break; + case XI_GestureSwipeBegin: + case XI_GestureSwipeUpdate: + case XI_GestureSwipeEnd: + { + XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev; + + surface = gdk_x11_surface_lookup_for_display (display, xev->event); + } + break; +#endif /* XINPUT_2_4 */ case XI_Enter: case XI_Leave: case XI_FocusIn: @@ -1881,6 +1901,126 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, break; #endif /* XINPUT_2_2 */ +#ifdef XINPUT_2_4 + case XI_GesturePinchBegin: + case XI_GesturePinchUpdate: + case XI_GesturePinchEnd: + { + XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev; + GdkModifierType state; + GdkTouchpadGesturePhase phase; + double x, y; + +#ifdef G_ENABLE_DEBUG + const char *event_name = ""; + switch (xev->evtype) + { + case XI_GesturePinchBegin: + event_name = "begin"; + break; + case XI_GesturePinchUpdate: + event_name = "update"; + break; + case XI_GesturePinchEnd: + event_name = "end"; + break; + default: + break; + } +#endif + + GDK_NOTE (EVENTS, + g_message ("pinch gesture %s:\twindow %ld\n\tfinger_count: %u%s", + event_name, + xev->event, + xev->detail, + xev->flags & XIGesturePinchEventCancelled ? "\n\tcancelled" : "")); + + device = g_hash_table_lookup (device_manager->id_table, + GINT_TO_POINTER (xev->deviceid)); + + state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group); + phase = _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags); + + x = (double) xev->event_x / scale; + y = (double) xev->event_y / scale; + + event = gdk_touchpad_event_new_pinch (surface, + device, + xev->time, + state, + phase, + x, y, + xev->detail, + xev->delta_x, + xev->delta_y, + xev->scale, + xev->delta_angle * G_PI / 180); + + if (ev->evtype == XI_GesturePinchBegin) + set_user_time (event); + } + break; + + case XI_GestureSwipeBegin: + case XI_GestureSwipeUpdate: + case XI_GestureSwipeEnd: + { + XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev; + GdkModifierType state; + GdkTouchpadGesturePhase phase; + double x, y; + +#ifdef G_ENABLE_DEBUG + const char *event_name = ""; + switch (xev->evtype) + { + case XI_GestureSwipeBegin: + event_name = "begin"; + break; + case XI_GestureSwipeUpdate: + event_name = "update"; + break; + case XI_GestureSwipeEnd: + event_name = "end"; + break; + default: + break; + } +#endif + + GDK_NOTE (EVENTS, + g_message ("swipe gesture %s:\twindow %ld\n\tfinger_count: %u%s", + event_name, + xev->event, + xev->detail, + xev->flags & XIGestureSwipeEventCancelled ? "\n\tcancelled" : "")); + + device = g_hash_table_lookup (device_manager->id_table, + GINT_TO_POINTER (xev->deviceid)); + + state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group); + phase = _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags); + + x = (double) xev->event_x / scale; + y = (double) xev->event_y / scale; + + event = gdk_touchpad_event_new_swipe (surface, + device, + xev->time, + state, + phase, + x, y, + xev->detail, + xev->delta_x, + xev->delta_y); + + if (ev->evtype == XI_GestureSwipeBegin) + set_user_time (event); + } + break; +#endif /* XINPUT_2_4 */ + case XI_Enter: case XI_Leave: { @@ -1992,7 +2132,8 @@ gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator) GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_FOCUS_CHANGE_MASK | - GDK_TOUCH_MASK); + GDK_TOUCH_MASK | + GDK_TOUCHPAD_GESTURE_MASK); } static void diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 4461f15e6b3a3ad7315dcab3a09f43ace73d1d28..74a5155096641c2abbfd75af1cf0460a686c3dfc 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -140,6 +140,7 @@ guchar * _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *devic guint _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state, XIButtonState *buttons_state, XIGroupState *group_state); +guint _gdk_x11_device_xi2_gesture_type_to_phase (int evtype, int flags); int _gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device); void _gdk_device_xi2_unset_scroll_valuators (GdkX11DeviceXI2 *device); diff --git a/meson.build b/meson.build index e85daf88f5b7d69b27e3b4cd4c3c4252b37ceae4..0965a2f113bf6de1a8da7086d981cb62474f66e2 100644 --- a/meson.build +++ b/meson.build @@ -557,6 +557,13 @@ if x11_enabled endif cdata.set('XINPUT_2_2', 1) + has_gesture_pinch_event = cc.has_member('XIGesturePinchEvent', 'type', dependencies: xi_dep, + prefix: '''#include + #include ''') + if has_gesture_pinch_event + cdata.set('XINPUT_2_4', 1) + endif + xinerama_dep = dependency('xinerama') if not cc.has_header_symbol('X11/extensions/Xinerama.h', 'XineramaQueryExtension', dependencies: xinerama_dep) error('X11 backend enabled, but Xinerama extension does not work.')