[clutter] x11: Add support for scroll valuators on XInput2.2



commit 676a31743993915437da419551d7c5193f0b9f43
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Mon Mar 19 12:16:53 2012 +0000

    x11: Add support for scroll valuators on XInput2.2

 clutter/clutter-device-manager-private.h |   23 ++++++
 clutter/clutter-input-device.c           |   96 ++++++++++++++++++++++++++
 clutter/x11/clutter-backend-x11.c        |    5 ++
 clutter/x11/clutter-device-manager-xi2.c |  111 +++++++++++++++++++++++++++++-
 4 files changed, 233 insertions(+), 2 deletions(-)
---
diff --git a/clutter/clutter-device-manager-private.h b/clutter/clutter-device-manager-private.h
index df9b8df..de89ecd 100644
--- a/clutter/clutter-device-manager-private.h
+++ b/clutter/clutter-device-manager-private.h
@@ -50,6 +50,16 @@ typedef struct _ClutterKeyInfo
   ClutterModifierType modifiers;
 } ClutterKeyInfo;
 
+typedef struct _ClutterScrollInfo
+{
+  guint axis_id;
+  ClutterScrollDirection direction;
+  gdouble increment;
+
+  gdouble last_value;
+  guint last_value_valid : 1;
+} ClutterScrollInfo;
+
 struct _ClutterInputDevice
 {
   GObject parent_instance;
@@ -102,6 +112,8 @@ struct _ClutterInputDevice
   guint n_keys;
   GArray *keys;
 
+  GArray *scroll_info;
+
   guint has_cursor : 1;
   guint is_enabled : 1;
 };
@@ -170,6 +182,17 @@ gboolean        _clutter_input_device_translate_axis            (ClutterInputDev
                                                                  gdouble               value,
                                                                  gdouble              *axis_value);
 
+void            _clutter_input_device_add_scroll_info           (ClutterInputDevice   *device,
+                                                                 guint                 index_,
+                                                                 ClutterScrollDirection direction,
+                                                                 gdouble               increment);
+void            _clutter_input_device_reset_scroll_info         (ClutterInputDevice   *device);
+gboolean        _clutter_input_device_get_scroll_delta          (ClutterInputDevice   *device,
+                                                                 guint                 index_,
+                                                                 gdouble               value,
+                                                                 ClutterScrollDirection *direction_p,
+                                                                 gdouble                *delta_p);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ */
diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c
index 41196ee..4e3554b 100644
--- a/clutter/clutter-input-device.c
+++ b/clutter/clutter-input-device.c
@@ -1444,3 +1444,99 @@ clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
                                            hardware_keycode,
                                            evdev_keycode);
 }
+
+void
+_clutter_input_device_add_scroll_info (ClutterInputDevice     *device,
+                                       guint                   index_,
+                                       ClutterScrollDirection  direction,
+                                       gdouble                 increment)
+{
+  ClutterScrollInfo info;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+  g_return_if_fail (index_ < clutter_input_device_get_n_axes (device));
+
+  info.axis_id = index_;
+  info.direction = direction;
+  info.increment = increment;
+  info.last_value_valid = FALSE;
+
+  if (device->scroll_info == NULL)
+    {
+      device->scroll_info = g_array_new (FALSE,
+                                         FALSE,
+                                         sizeof (ClutterScrollInfo));
+    }
+
+  g_array_append_val (device->scroll_info, info);
+}
+
+gboolean
+_clutter_input_device_get_scroll_delta (ClutterInputDevice     *device,
+                                        guint                   index_,
+                                        gdouble                 value,
+                                        ClutterScrollDirection *direction_p,
+                                        gdouble                *delta_p)
+{
+  guint i;
+
+  g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
+  g_return_val_if_fail (index_ < clutter_input_device_get_n_axes (device), FALSE);
+
+  if (device->scroll_info == NULL)
+    return FALSE;
+
+  for (i = 0; i < device->scroll_info->len; i++)
+    {
+      ClutterScrollInfo *info = &g_array_index (device->scroll_info,
+                                                ClutterScrollInfo,
+                                                i);
+
+      if (info->axis_id == index_)
+        {
+          if (direction_p != NULL)
+            *direction_p = info->direction;
+
+          if (delta_p != NULL)
+            *delta_p = 0.0;
+
+          if (info->last_value_valid)
+            {
+              if (delta_p != NULL)
+                {
+                  *delta_p = (value - info->last_value)
+                           / info->increment;
+                }
+
+              info->last_value = value;
+            }
+          else
+            {
+              info->last_value = value;
+              info->last_value_valid = TRUE;
+            }
+
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+void
+_clutter_input_device_reset_scroll_info (ClutterInputDevice *device)
+{
+  guint i;
+
+  if (device->scroll_info == NULL)
+    return;
+
+  for (i = 0; i < device->scroll_info->len; i++)
+    {
+      ClutterScrollInfo *info = &g_array_index (device->scroll_info,
+                                                ClutterScrollInfo,
+                                                i);
+
+      info->last_value_valid = FALSE;
+    }
+}
diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c
index f781767..7cd6a78 100644
--- a/clutter/x11/clutter-backend-x11.c
+++ b/clutter/x11/clutter-backend-x11.c
@@ -239,7 +239,12 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
             {
 #ifdef HAVE_XINPUT_2
               int major = 2;
+
+#ifdef HAVE_XINPUT_2_2
+              int minor = 2;
+#else
               int minor = 0;
+#endif /* HAVE_XINPUT_2_2 */
 
               if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest)
                 {
diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c
index 28e0ba2..bdbe536 100644
--- a/clutter/x11/clutter-device-manager-xi2.c
+++ b/clutter/x11/clutter-device-manager-xi2.c
@@ -154,6 +154,32 @@ translate_device_classes (Display             *xdisplay,
                                     (XIValuatorClassInfo *) class_info);
           break;
 
+#ifdef XINPUT_2_2
+        case XIScrollClass:
+          {
+            XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
+            ClutterScrollDirection direction;
+
+            if (scroll_info->scroll_type == XIScrollTypeVertical)
+              direction = CLUTTER_SCROLL_DOWN;
+            else
+              direction = CLUTTER_SCROLL_RIGHT;
+
+            CLUTTER_NOTE (BACKEND, "Scroll valuator %d: %s, increment: %f",
+                          scroll_info->number,
+                          scroll_info->scroll_type == XIScrollTypeVertical
+                            ? "vertical"
+                            : "horizontal",
+                          scroll_info->increment);
+
+            _clutter_input_device_add_scroll_info (device,
+                                                   scroll_info->number,
+                                                   direction,
+                                                   scroll_info->increment);
+          }
+          break;
+#endif /* XINPUT_2_2 */
+
         default:
           break;
         }
@@ -541,6 +567,51 @@ translate_axes (ClutterInputDevice *device,
   return retval;
 }
 
+static gdouble
+scroll_valuators_changed (ClutterInputDevice *device,
+                          XIValuatorState    *valuators,
+                          gdouble            *dx_p,
+                          gdouble            *dy_p)
+{
+  gboolean retval = FALSE;
+  guint n_axes, n_val, i;
+  double *values;
+
+  n_axes = clutter_input_device_get_n_axes (device);
+  values = valuators->values;
+
+  *dx_p = *dy_p = 0.0;
+
+  n_val = 0;
+
+  for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
+    {
+      ClutterScrollDirection direction;
+      gdouble delta;
+
+      if (!XIMaskIsSet (valuators->mask, i))
+        continue;
+
+      if (_clutter_input_device_get_scroll_delta (device, i,
+                                                  values[n_val],
+                                                  &direction,
+                                                  &delta))
+        {
+          retval = TRUE;
+
+          if (direction == CLUTTER_SCROLL_UP ||
+              direction == CLUTTER_SCROLL_DOWN)
+            *dx_p = delta;
+          else
+            *dy_p = delta;
+        }
+
+      n_val += 1;
+    }
+
+  return retval;
+}
+
 static ClutterTranslateReturn
 clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
                                             gpointer                native,
@@ -793,6 +864,44 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
     case XI_Motion:
       {
         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
+        gdouble delta_x, delta_y;
+
+        source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+                                             GINT_TO_POINTER (xev->sourceid));
+
+        if (scroll_valuators_changed (source_device,
+                                      &xev->valuators,
+                                      &delta_x, &delta_y))
+          {
+            event->scroll.type = event->type = CLUTTER_SCROLL;
+            event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
+
+            event->scroll.stage = stage;
+            event->scroll.time = xev->time;
+            event->scroll.x = xev->event_x;
+            event->scroll.y = xev->event_y;
+            event->scroll.modifier_state =
+              _clutter_input_device_xi2_translate_state (&xev->mods,
+                                                         &xev->buttons);
+
+            clutter_event_set_scroll_delta (event, delta_x, delta_y);
+            clutter_event_set_source_device (event, source_device);
+
+            device = g_hash_table_lookup (manager_xi2->devices_by_id,
+                                          GINT_TO_POINTER (xev->deviceid));
+            clutter_event_set_device (event, device);
+
+            CLUTTER_NOTE (EVENT,
+                          "smooth scroll: win:0x%x device:%s (x:%.2f, y:%.2f, delta:%f, %f)",
+                          (unsigned int) stage_x11->xwin,
+                          event->scroll.device->device_name,
+                          event->scroll.x,
+                          event->scroll.y,
+                          delta_x, delta_y);
+
+            retval = CLUTTER_TRANSLATE_QUEUE;
+            break;
+          }
 
         event->motion.type = event->type = CLUTTER_MOTION;
 
@@ -805,8 +914,6 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
           _clutter_input_device_xi2_translate_state (&xev->mods,
                                                      &xev->buttons);
 
-        source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
-                                             GINT_TO_POINTER (xev->sourceid));
         clutter_event_set_source_device (event, source_device);
 
         device = g_hash_table_lookup (manager_xi2->devices_by_id,



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