diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2021-12-13 13:21:09 +0000 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2021-12-13 13:21:09 +0000 |
commit | 2800dc356bce0d478c892405b08e13d0937a93f0 (patch) | |
tree | 6d89fea2e3633af232badc255b5a9d7387b1ff27 | |
parent | 068df4874ad710ee7f5d11eac33743af3dd0059a (diff) | |
parent | a94baf4c3dab7d3533a82d7fd134303eda3d363e (diff) | |
download | gtk+-2800dc356bce0d478c892405b08e13d0937a93f0.tar.gz |
Merge branch 'gtk-3-24-x11-xi2.4-gestures' into 'gtk-3-24'
[GTK3] Touchpad gestures for X11 (XInput 2.4, X Server 21.1)
See merge request GNOME/gtk!4212
-rw-r--r-- | config.h.meson | 3 | ||||
-rw-r--r-- | config.h.win32.in | 3 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | demos/gtk-demo/gestures.c | 2 | ||||
-rw-r--r-- | gdk/gdkseatdefault.c | 3 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 2 | ||||
-rw-r--r-- | gdk/x11/gdkdevice-xi2.c | 45 | ||||
-rw-r--r-- | gdk/x11/gdkdevicemanager-x11.c | 5 | ||||
-rw-r--r-- | gdk/x11/gdkdevicemanager-xi2.c | 161 | ||||
-rw-r--r-- | gdk/x11/gdkprivate-x11.h | 5 | ||||
-rw-r--r-- | meson.build | 8 |
11 files changed, 241 insertions, 8 deletions
diff --git a/config.h.meson b/config.h.meson index eb347ae538..ce2aeb2946 100644 --- a/config.h.meson +++ b/config.h.meson @@ -244,6 +244,9 @@ /* Define to 1 if XInput 2.2 is available */ #mesondefine XINPUT_2_2 +/* Define to 1 if XInput 2.4 is available */ +#mesondefine XINPUT_2_4 + /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 diff --git a/config.h.win32.in b/config.h.win32.in index 9bbf65fe10..9666b1b872 100644 --- a/config.h.win32.in +++ b/config.h.win32.in @@ -300,6 +300,9 @@ /* Define to 1 if XInput 2.2 is available */ /* #undef XINPUT_2_2 */ +/* Define to 1 if XInput 2.4 is available */ +/* #undef XINPUT_2_4 */ + /* Define to 1 if the X Window System is missing or not being used. */ /* #undef X_DISPLAY_MISSING */ diff --git a/configure.ac b/configure.ac index 412ddbf6d7..cc141e04ea 100644 --- a/configure.ac +++ b/configure.ac @@ -1167,13 +1167,23 @@ if test "x$enable_x11_backend" = xyes; then AC_DEFINE(XINPUT_2_2, 1, [Define to 1 if XInput 2.2 is available]), have_xinput2_2=no, [[#include <X11/extensions/XInput2.h>]])]) - LIBS="$gtk_save_LIBS" if test "x$have_xinput2_2" = "xyes"; then X_EXTENSIONS="$X_EXTENSIONS XI2.2" else X_EXTENSIONS="$X_EXTENSIONS XI2" fi + + AC_CHECK_MEMBER([XIGesturePinchEvent.type], + have_xinput2_4=yes + AC_DEFINE(XINPUT_2_4, 1, [Define to 1 if XInput 2.4 is available]), + have_xinput2_4=no, + [[#include <X11/extensions/XInput2.h>]]) + + if test "x$have_xinput2_4" = "xyes"; then + X_EXTENSIONS="$X_EXTENSIONS XI2.4" + fi + LIBS="$gtk_save_LIBS" fi AS_IF([test "x$have_xinput2" != "xyes"], diff --git a/demos/gtk-demo/gestures.c b/demos/gtk-demo/gestures.c index 9632e7d665..6d3ceca521 100644 --- a/demos/gtk-demo/gestures.c +++ b/demos/gtk-demo/gestures.c @@ -160,7 +160,7 @@ do_gestures (GtkWidget *do_widget) gtk_container_add (GTK_CONTAINER (window), drawing_area); gtk_widget_add_events (drawing_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK); + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_TOUCHPAD_GESTURE_MASK); g_signal_connect (drawing_area, "draw", G_CALLBACK (drawing_area_draw), NULL); diff --git a/gdk/gdkseatdefault.c b/gdk/gdkseatdefault.c index 98ea6335fa..4dd4dca99b 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/gdkwindow.c b/gdk/gdkwindow.c index 2de8ba4a09..2d0ed0f963 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1286,7 +1286,7 @@ get_native_device_event_mask (GdkWindow *private, if (gdk_window_is_toplevel (private) || mask & GDK_BUTTON_PRESS_MASK) mask |= - GDK_TOUCH_MASK | + GDK_TOUCH_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK; diff --git a/gdk/x11/gdkdevice-xi2.c b/gdk/x11/gdkdevice-xi2.c index cd1849c51e..f089a56b5e 100644 --- a/gdk/x11/gdkdevice-xi2.c +++ b/gdk/x11/gdkdevice-xi2.c @@ -61,7 +61,6 @@ struct _GdkX11DeviceXI2Class G_DEFINE_TYPE (GdkX11DeviceXI2, gdk_x11_device_xi2, GDK_TYPE_DEVICE) - static void gdk_x11_device_xi2_finalize (GObject *object); static void gdk_x11_device_xi2_get_property (GObject *object, guint prop_id, @@ -762,6 +761,20 @@ _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager } #endif /* XINPUT_2_2 */ +#ifdef XINPUT_2_4 + /* XInput 2.4 includes multitouch 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; } @@ -810,6 +823,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 2e7ea1f41b..c649ec6ddf 100644 --- a/gdk/x11/gdkdevicemanager-x11.c +++ b/gdk/x11/gdkdevicemanager-x11.c @@ -48,14 +48,15 @@ _gdk_x11_device_manager_new (GdkDisplay *display) int major, minor; major = 2; - minor = 3; + minor = 4; if (!_gdk_disable_multidevice && XIQueryVersion (xdisplay, &major, &minor) != BadRequest) { GdkX11DeviceManagerXI2 *device_manager_xi2; - GDK_NOTE (INPUT, g_message ("Creating XI2 device manager")); + GDK_NOTE (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 00e64d2a84..193dd47beb 100644 --- a/gdk/x11/gdkdevicemanager-xi2.c +++ b/gdk/x11/gdkdevicemanager-xi2.c @@ -1335,6 +1335,26 @@ get_event_window (GdkEventTranslator *translator, } } break; +#ifdef XINPUT_2_4 + case XI_GesturePinchBegin: + case XI_GesturePinchUpdate: + case XI_GesturePinchEnd: + { + XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev; + + window = gdk_x11_window_lookup_for_display (display, xev->event); + } + break; + case XI_GestureSwipeBegin: + case XI_GestureSwipeUpdate: + case XI_GestureSwipeEnd: + { + XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev; + + window = gdk_x11_window_lookup_for_display (display, xev->event); + } + break; +#endif /* XINPUT_2_4 */ case XI_Enter: case XI_Leave: case XI_FocusIn: @@ -1950,6 +1970,144 @@ 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; + +#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; + } +#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" : "")); + + event->touchpad_pinch.type = GDK_TOUCHPAD_PINCH; + event->touchpad_pinch.phase = + _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags); + event->touchpad_pinch.window = window; + event->touchpad_pinch.time = xev->time; + event->touchpad_pinch.x = (gdouble) xev->event_x / scale; + event->touchpad_pinch.y = (gdouble) xev->event_y / scale; + event->touchpad_pinch.x_root = (gdouble) xev->root_x / scale; + event->touchpad_pinch.y_root = (gdouble) xev->root_y / scale; + event->touchpad_pinch.dx = xev->delta_x; + event->touchpad_pinch.dy = xev->delta_y; + event->touchpad_pinch.scale = xev->scale; + event->touchpad_pinch.angle_delta = xev->delta_angle * G_PI / 180; + event->touchpad_pinch.n_fingers = xev->detail; + + device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->deviceid)); + gdk_event_set_device (event, device); + + source_device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->sourceid)); + gdk_event_set_source_device (event, source_device); + gdk_event_set_seat (event, gdk_device_get_seat (device)); + + event->touchpad_pinch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group); + + if (xev->evtype == XI_GesturePinchBegin || xev->evtype == XI_GesturePinchEnd) + { + if (!set_screen_from_root (display, event, xev->root)) + { + return_val = FALSE; + break; + } + } + + if (ev->evtype == XI_GesturePinchBegin) + set_user_time (event); + } + break; + + case XI_GestureSwipeBegin: + case XI_GestureSwipeUpdate: + case XI_GestureSwipeEnd: + { + XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev; + +#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; + } +#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" : "")); + + event->touchpad_swipe.type = GDK_TOUCHPAD_SWIPE; + event->touchpad_pinch.phase = + _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags); + event->touchpad_swipe.window = window; + event->touchpad_swipe.time = xev->time; + event->touchpad_swipe.x = (gdouble) xev->event_x / scale; + event->touchpad_swipe.y = (gdouble) xev->event_y / scale; + event->touchpad_swipe.x_root = (gdouble) xev->root_x / scale; + event->touchpad_swipe.y_root = (gdouble) xev->root_y / scale; + event->touchpad_swipe.dx = xev->delta_x; + event->touchpad_swipe.dy = xev->delta_y; + event->touchpad_swipe.n_fingers = xev->detail; + + device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->deviceid)); + gdk_event_set_device (event, device); + + source_device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->sourceid)); + gdk_event_set_source_device (event, source_device); + gdk_event_set_seat (event, gdk_device_get_seat (device)); + + event->touchpad_swipe.state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group); + + if (xev->evtype == XI_GestureSwipeBegin || xev->evtype == XI_GestureSwipeEnd) + { + if (!set_screen_from_root (display, event, xev->root)) + { + return_val = FALSE; + break; + } + } + + if (ev->evtype == XI_GestureSwipeBegin) + set_user_time (event); + } + break; +#endif /* XINPUT_2_4 */ + case XI_Enter: case XI_Leave: { @@ -2078,7 +2236,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 beb84c2ab5..72039585e4 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -230,6 +230,11 @@ 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); + +#ifdef XINPUT_2_4 +guint _gdk_x11_device_xi2_gesture_type_to_phase (int evtype, int flags); +#endif + gint _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 82123e7a61..8e4c224436 100644 --- a/meson.build +++ b/meson.build @@ -629,6 +629,14 @@ if x11_enabled endif endif + has_gesture_pinch_event = cc.has_member('XIGesturePinchEvent', 'type', dependencies: xi_dep, + prefix: '''#include <X11/Xlib.h> + #include <X11/extensions/XInput2.h>''') + if has_gesture_pinch_event + cdata.set('XINPUT_2_4', 1) + endif + + enable_xinerama = get_option('xinerama') if enable_xinerama != 'no' want_xinerama = enable_xinerama == 'yes' |