[gtk+] xi2: Translate touch events



commit f7b7cc22e61cc700b9bceb5c6552701f6e3e0cd2
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Mar 1 00:56:51 2012 -0500

    xi2: Translate touch events
    
    Translate XI_TouchBegin/Update/End to GDK_TOUCH_BEGIN/UPDATE/END
    events.
    
    At the same time,
    set pointer-emulated flags on button events with XIPointerEmulated
    and on touch events emulating the pointer.

 gdk/x11/gdkdevice-xi2.c        |   34 +++++-
 gdk/x11/gdkdevicemanager-x11.c |    4 +
 gdk/x11/gdkdevicemanager-xi2.c |  250 +++++++++++++++++++++++++++++----------
 gdk/x11/gdkprivate-x11.h       |    5 +-
 4 files changed, 223 insertions(+), 70 deletions(-)
---
diff --git a/gdk/x11/gdkdevice-xi2.c b/gdk/x11/gdkdevice-xi2.c
index 96fd2c5..4b37a7a 100644
--- a/gdk/x11/gdkdevice-xi2.c
+++ b/gdk/x11/gdkdevice-xi2.c
@@ -386,6 +386,7 @@ gdk_x11_device_xi2_grab (GdkDevice    *device,
                          guint32       time_)
 {
   GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device);
+  GdkX11DeviceManagerXI2 *device_manager_xi2;
   GdkDisplay *display;
   XIEventMask mask;
   Window xwindow;
@@ -393,6 +394,7 @@ gdk_x11_device_xi2_grab (GdkDevice    *device,
   gint status;
 
   display = gdk_device_get_display (device);
+  device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (gdk_display_get_device_manager (display));
 
   /* FIXME: confine_to is actually unused */
 
@@ -407,7 +409,9 @@ gdk_x11_device_xi2_grab (GdkDevice    *device,
     }
 
   mask.deviceid = device_xi2->device_id;
-  mask.mask = _gdk_x11_device_xi2_translate_event_mask (event_mask, &mask.mask_len);
+  mask.mask = _gdk_x11_device_xi2_translate_event_mask (device_manager_xi2,
+                                                        event_mask,
+                                                        &mask.mask_len);
 
 #ifdef G_ENABLE_DEBUG
   if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
@@ -623,10 +627,17 @@ gdk_x11_device_xi2_select_window_events (GdkDevice    *device,
                                          GdkEventMask  event_mask)
 {
   GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device);
+  GdkX11DeviceManagerXI2 *device_manager_xi2;
+  GdkDisplay *display;
   XIEventMask evmask;
 
+  display = gdk_device_get_display (device);
+  device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (gdk_display_get_device_manager (display));
+
   evmask.deviceid = device_xi2->device_id;
-  evmask.mask = _gdk_x11_device_xi2_translate_event_mask (event_mask, &evmask.mask_len);
+  evmask.mask = _gdk_x11_device_xi2_translate_event_mask (device_manager_xi2,
+                                                          event_mask,
+                                                          &evmask.mask_len);
 
   XISelectEvents (GDK_WINDOW_XDISPLAY (window),
                   GDK_WINDOW_XID (window),
@@ -636,10 +647,14 @@ gdk_x11_device_xi2_select_window_events (GdkDevice    *device,
 }
 
 guchar *
-_gdk_x11_device_xi2_translate_event_mask (GdkEventMask  event_mask,
-                                          gint         *len)
+_gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager_xi2,
+                                          GdkEventMask            event_mask,
+                                          gint                   *len)
 {
   guchar *mask;
+  gint minor;
+
+  g_object_get (device_manager_xi2, "minor", &minor, NULL);
 
   *len = XIMaskLen (XI_LASTEVENT);
   mask = g_new0 (guchar, *len);
@@ -688,6 +703,17 @@ _gdk_x11_device_xi2_translate_event_mask (GdkEventMask  event_mask,
       XISetMask (mask, XI_FocusOut);
     }
 
+#ifdef XINPUT_2_2
+  /* XInput 2.2 includes multitouch support */
+  if (minor >= 2 &&
+      event_mask & GDK_TOUCH_MASK)
+    {
+      XISetMask (mask, XI_TouchBegin);
+      XISetMask (mask, XI_TouchUpdate);
+      XISetMask (mask, XI_TouchEnd);
+    }
+#endif /* XINPUT_2_2 */
+
   return mask;
 }
 
diff --git a/gdk/x11/gdkdevicemanager-x11.c b/gdk/x11/gdkdevicemanager-x11.c
index 0fff0eb..7547063 100644
--- a/gdk/x11/gdkdevicemanager-x11.c
+++ b/gdk/x11/gdkdevicemanager-x11.c
@@ -52,7 +52,11 @@ _gdk_x11_device_manager_new (GdkDisplay *display)
           int major, minor;
 
           major = 2;
+#ifdef XINPUT_2_2
+	  minor = 2;
+#else
           minor = 0;
+#endif /* XINPUT_2_2 */
 
           if (!_gdk_disable_multidevice &&
               XIQueryVersion (xdisplay, &major, &minor) != BadRequest)
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index 7b66d92..ecd1a4f 100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -27,6 +27,7 @@
 #include "gdkprivate-x11.h"
 #include "gdkintl.h"
 #include "gdkkeysyms.h"
+#include "gdkinternals.h"
 
 #ifdef XINPUT_2
 
@@ -164,8 +165,10 @@ _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
 static void
 translate_valuator_class (GdkDisplay          *display,
                           GdkDevice           *device,
-                          XIValuatorClassInfo *info,
-                          gint                 n_valuator)
+                          Atom                 valuator_label,
+                          gdouble              min,
+                          gdouble              max,
+                          gdouble              resolution)
 {
   static gboolean initialized = FALSE;
   static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
@@ -186,24 +189,19 @@ translate_valuator_class (GdkDisplay          *display,
 
   for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
     {
-      if (label_atoms[i] == info->label)
+      if (label_atoms[i] == valuator_label)
         {
           use = i;
           break;
         }
     }
 
-  if (info->label != None)
-    label = gdk_x11_xatom_to_atom_for_display (display, info->label);
+  if (valuator_label != None)
+    label = gdk_x11_xatom_to_atom_for_display (display, valuator_label);
   else
     label = GDK_NONE;
 
-  _gdk_device_add_axis (device,
-                        label,
-                        use,
-                        info->min,
-                        info->max,
-                        info->resolution);
+  _gdk_device_add_axis (device, label, use, min, max, resolution);
 }
 
 static void
@@ -212,7 +210,7 @@ translate_device_classes (GdkDisplay      *display,
                           XIAnyClassInfo **classes,
                           guint            n_classes)
 {
-  gint i, n_valuator = 0;
+  gint i;
 
   g_object_freeze_notify (G_OBJECT (device));
 
@@ -234,10 +232,14 @@ translate_device_classes (GdkDisplay      *display,
           }
           break;
         case XIValuatorClass:
-          translate_valuator_class (display, device,
-                                    (XIValuatorClassInfo *) class_info,
-                                    n_valuator);
-          n_valuator++;
+          {
+            XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info;
+            translate_valuator_class (display, device,
+                                      valuator_info->label,
+                                      valuator_info->min,
+                                      valuator_info->max,
+                                      valuator_info->resolution);
+          }
           break;
         default:
           /* Ignore */
@@ -893,6 +895,11 @@ get_event_window (GdkEventTranslator *translator,
     case XI_ButtonPress:
     case XI_ButtonRelease:
     case XI_Motion:
+#ifdef XINPUT_2_2
+    case XI_TouchUpdate:
+    case XI_TouchBegin:
+    case XI_TouchEnd:
+#endif /* XINPUT_2_2 */
       {
         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
 
@@ -1117,51 +1124,39 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
         GdkDevice *source_device;
 
-        switch (xev->detail)
+        if (ev->evtype == XI_ButtonPress &&
+            (xev->detail >= 4 && xev->detail <= 7))
+          {
+            /* Button presses of button 4-7 are scroll events */
+            event->scroll.type = GDK_SCROLL;
+
+            if (xev->detail == 4)
+              event->scroll.direction = GDK_SCROLL_UP;
+            else if (xev->detail == 5)
+              event->scroll.direction = GDK_SCROLL_DOWN;
+            else if (xev->detail == 6)
+              event->scroll.direction = GDK_SCROLL_LEFT;
+            else
+              event->scroll.direction = GDK_SCROLL_RIGHT;
+
+            event->scroll.window = window;
+            event->scroll.time = xev->time;
+            event->scroll.x = (gdouble) xev->event_x;
+            event->scroll.y = (gdouble) xev->event_y;
+            event->scroll.x_root = (gdouble) xev->root_x;
+            event->scroll.y_root = (gdouble) xev->root_y;
+
+            event->scroll.device = g_hash_table_lookup (device_manager->id_table,
+                                                        GUINT_TO_POINTER (xev->deviceid));
+
+            source_device = g_hash_table_lookup (device_manager->id_table,
+                                                 GUINT_TO_POINTER (xev->sourceid));
+            gdk_event_set_source_device (event, source_device);
+
+            event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+          }
+        else
           {
-          case 4:
-          case 5:
-          case 6:
-          case 7:
-             /* Button presses of button 4-7 are scroll events */
-            if (ev->evtype == XI_ButtonPress)
-              {
-                event->scroll.type = GDK_SCROLL;
-
-                if (xev->detail == 4)
-                  event->scroll.direction = GDK_SCROLL_UP;
-                else if (xev->detail == 5)
-                  event->scroll.direction = GDK_SCROLL_DOWN;
-                else if (xev->detail == 6)
-                  event->scroll.direction = GDK_SCROLL_LEFT;
-                else
-                  event->scroll.direction = GDK_SCROLL_RIGHT;
-
-                event->scroll.window = window;
-                event->scroll.time = xev->time;
-                event->scroll.x = (gdouble) xev->event_x;
-                event->scroll.y = (gdouble) xev->event_y;
-                event->scroll.x_root = (gdouble) xev->root_x;
-                event->scroll.y_root = (gdouble) xev->root_y;
-
-                event->scroll.device = g_hash_table_lookup (device_manager->id_table,
-                                                            GUINT_TO_POINTER (xev->deviceid));
-
-                source_device = g_hash_table_lookup (device_manager->id_table,
-                                                     GUINT_TO_POINTER (xev->sourceid));
-                gdk_event_set_source_device (event, source_device);
-
-                event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
-                break;
-              }
-            /* Button presses of button 4-7 are scroll events, so ignore the release */
-            else if (ev->evtype == XI_ButtonRelease)
-              {
-                return_val = FALSE;
-                break;
-              }
-            /* else (XI_ButtonRelease) fall thru */
-          default:
             event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
 
             event->button.window = window;
@@ -1194,9 +1189,13 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
               }
 
             event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+
             event->button.button = xev->detail;
           }
 
+        if (xev->flags & (XIPointerEmulated | XITouchEmulatingPointer))
+          _gdk_event_set_pointer_emulated (event, TRUE);
+
         if (return_val == FALSE)
           break;
 
@@ -1211,15 +1210,14 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
 
         break;
       }
+
     case XI_Motion:
       {
         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
         GdkDevice *source_device;
 
         event->motion.type = GDK_MOTION_NOTIFY;
-
         event->motion.window = window;
-
         event->motion.time = xev->time;
         event->motion.x = (gdouble) xev->event_x;
         event->motion.y = (gdouble) xev->event_y;
@@ -1235,6 +1233,9 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
 
         event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
 
+        if (xev->flags & (XIPointerEmulated | XITouchEmulatingPointer))
+          _gdk_event_set_pointer_emulated (event, TRUE);
+
         /* There doesn't seem to be motion hints in XI */
         event->motion.is_hint = FALSE;
 
@@ -1254,6 +1255,124 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
           }
       }
       break;
+
+#ifdef XINPUT_2_2
+    case XI_TouchBegin:
+    case XI_TouchEnd:
+      {
+        XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+        GdkDevice *source_device;
+
+        if (ev->evtype == XI_TouchBegin)
+          event->touch.type = GDK_TOUCH_BEGIN;
+        else if (ev->evtype == XI_TouchEnd)
+          event->touch.type = GDK_TOUCH_END;
+
+        event->touch.window = window;
+        event->touch.time = xev->time;
+        event->touch.x = (gdouble) xev->event_x;
+        event->touch.y = (gdouble) xev->event_y;
+        event->touch.x_root = (gdouble) xev->root_x;
+        event->touch.y_root = (gdouble) xev->root_y;
+
+        event->touch.device = g_hash_table_lookup (device_manager->id_table,
+                                                   GUINT_TO_POINTER (xev->deviceid));
+
+        source_device = g_hash_table_lookup (device_manager->id_table,
+                                             GUINT_TO_POINTER (xev->sourceid));
+        gdk_event_set_source_device (event, source_device);
+
+        event->touch.axes = translate_axes (event->touch.device,
+                                            event->touch.x,
+                                            event->touch.y,
+                                            event->touch.window,
+                                            &xev->valuators);
+
+        if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW)
+          {
+            GdkDevice *device = event->touch.device;
+
+            /* Update event coordinates from axes */
+            gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x);
+            gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
+          }
+
+        event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+
+        if (ev->evtype == XI_TouchBegin)
+          event->touch.state |= GDK_BUTTON1_MASK;
+
+        event->touch.sequence = GUINT_TO_POINTER (xev->detail);
+
+        if (xev->flags & XITouchEmulatingPointer)
+          {
+            event->touch.emulating_pointer = TRUE;
+            _gdk_event_set_pointer_emulated (event, TRUE);
+          }
+
+        if (return_val == FALSE)
+          break;
+
+        if (!set_screen_from_root (display, event, xev->root))
+          {
+            return_val = FALSE;
+            break;
+          }
+
+        if (ev->evtype == XI_TouchBegin)
+          set_user_time (event);
+      }
+      break;
+
+    case XI_TouchUpdate:
+      {
+        XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+        GdkDevice *source_device;
+
+        event->touch.window = window;
+        event->touch.sequence = GUINT_TO_POINTER (xev->detail);
+        event->touch.type = GDK_TOUCH_UPDATE;
+        event->touch.time = xev->time;
+        event->touch.x = (gdouble) xev->event_x;
+        event->touch.y = (gdouble) xev->event_y;
+        event->touch.x_root = (gdouble) xev->root_x;
+        event->touch.y_root = (gdouble) xev->root_y;
+
+        event->touch.device = g_hash_table_lookup (device_manager->id_table,
+                                                   GINT_TO_POINTER (xev->deviceid));
+
+        source_device = g_hash_table_lookup (device_manager->id_table,
+                                             GUINT_TO_POINTER (xev->sourceid));
+        gdk_event_set_source_device (event, source_device);
+
+        event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+
+        event->touch.state |= GDK_BUTTON1_MASK;
+
+        if (xev->flags & XITouchEmulatingPointer)
+          {
+            event->touch.emulating_pointer = TRUE;
+            _gdk_event_set_pointer_emulated (event, TRUE);
+          }
+
+        event->touch.axes = translate_axes (event->touch.device,
+                                            event->touch.x,
+                                            event->touch.y,
+                                            event->touch.window,
+                                            &xev->valuators);
+
+        if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW)
+          {
+            GdkDevice *device = event->touch.device;
+
+            /* Update event coordinates from axes */
+            gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x);
+            gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
+          }
+      }
+      break;
+#endif
+
     case XI_Enter:
     case XI_Leave:
       {
@@ -1350,7 +1469,8 @@ gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
           GDK_BUTTON2_MOTION_MASK |
           GDK_BUTTON3_MOTION_MASK |
           GDK_BUTTON_MOTION_MASK |
-          GDK_FOCUS_CHANGE_MASK);
+          GDK_FOCUS_CHANGE_MASK |
+          GDK_TOUCH_MASK);
 }
 
 static void
@@ -1364,7 +1484,9 @@ gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
   device_manager = GDK_DEVICE_MANAGER (translator);
 
   event_mask.deviceid = XIAllMasterDevices;
-  event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (evmask, &event_mask.mask_len);
+  event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (device_manager),
+                                                              evmask,
+                                                              &event_mask.mask_len);
 
   _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask);
   g_free (event_mask.mask);
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index 551391e..98d7732 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -245,8 +245,9 @@ void _gdk_x11_device_xi_translate_axes     (GdkDevice *device,
 #endif
 
 #ifdef XINPUT_2
-guchar * _gdk_x11_device_xi2_translate_event_mask (GdkEventMask     event_mask,
-                                                   gint            *len);
+guchar * _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager_xi2,
+                                                   GdkEventMask            event_mask,
+                                                   gint                   *len);
 guint    _gdk_x11_device_xi2_translate_state      (XIModifierState *mods_state,
                                                    XIButtonState   *buttons_state,
                                                    XIGroupState    *group_state);



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