summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2021-12-13 13:21:09 +0000
committerCarlos Garnacho <carlosg@gnome.org>2021-12-13 13:21:09 +0000
commit2800dc356bce0d478c892405b08e13d0937a93f0 (patch)
tree6d89fea2e3633af232badc255b5a9d7387b1ff27
parent068df4874ad710ee7f5d11eac33743af3dd0059a (diff)
parenta94baf4c3dab7d3533a82d7fd134303eda3d363e (diff)
downloadgtk+-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.meson3
-rw-r--r--config.h.win32.in3
-rw-r--r--configure.ac12
-rw-r--r--demos/gtk-demo/gestures.c2
-rw-r--r--gdk/gdkseatdefault.c3
-rw-r--r--gdk/gdkwindow.c2
-rw-r--r--gdk/x11/gdkdevice-xi2.c45
-rw-r--r--gdk/x11/gdkdevicemanager-x11.c5
-rw-r--r--gdk/x11/gdkdevicemanager-xi2.c161
-rw-r--r--gdk/x11/gdkprivate-x11.h5
-rw-r--r--meson.build8
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'