[gtk: 2/3] gdk/x11: Implement XI2.4 touchpad gesture support




commit 68bd94fa254ec4488e746d6e0616719a4896ef0d
Author: Povilas Kanapickas <povilas radix lt>
Date:   Mon Sep 6 01:32:16 2021 +0300

    gdk/x11: Implement XI2.4 touchpad gesture support

 gdk/gdkseatdefault.c           |   3 +-
 gdk/x11/gdkdevice-xi2.c        |  44 +++++++++++++
 gdk/x11/gdkdevicemanager-x11.c |   2 +-
 gdk/x11/gdkdevicemanager-xi2.c | 143 ++++++++++++++++++++++++++++++++++++++++-
 gdk/x11/gdkprivate-x11.h       |   1 +
 meson.build                    |   7 ++
 6 files changed, 197 insertions(+), 3 deletions(-)
---
diff --git a/gdk/gdkseatdefault.c b/gdk/gdkseatdefault.c
index ce47df8230..18d44662ec 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 5976dfafc4..7062a7330a 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 d01a5db24b..27a7d2007b 100644
--- a/gdk/x11/gdkdevicemanager-x11.c
+++ b/gdk/x11/gdkdevicemanager-x11.c
@@ -41,7 +41,7 @@ _gdk_x11_device_manager_new (GdkDisplay *display)
       int major, minor;
 
       major = 2;
-      minor = 3;
+      minor = 4;
 
       if (XIQueryVersion (xdisplay, &major, &minor) != BadRequest)
         {
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index e4114e5279..9eb4e9bc56 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 4461f15e6b..74a5155096 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 e85daf88f5..0965a2f113 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 <X11/Xlib.h>
+                                                     #include <X11/extensions/XInput2.h>''')
+  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.')


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]