[clutter/clutter-1.16] evdev: add callback to constrain the pointer position



commit aef3d0022cd5b563f86774ec9ad79b70fbe9308a
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Fri Aug 23 12:15:40 2013 +0200

    evdev: add callback to constrain the pointer position
    
    Add a new callback that is called prior to emitting pointer
    motion events and that can modify the new pointer position.
    The main purpose is allowing multiscreen apps to prevent the
    pointer for entering the dead area that exists when the screens
    are not the same size, but it could also used to implement
    pointer barriers.
    A callback is needed to make sure that the hook is called early
    enough and the Clutter state is always consistent.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706652

 clutter/evdev/clutter-device-manager-evdev.c |   53 +++++++++++++++++++++++++-
 clutter/evdev/clutter-evdev.h                |   27 +++++++++++++
 2 files changed, 78 insertions(+), 2 deletions(-)
---
diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c
index dd503bb..8666763 100644
--- a/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/evdev/clutter-device-manager-evdev.c
@@ -73,6 +73,10 @@ struct _ClutterDeviceManagerEvdevPrivate
   ClutterInputDevice *core_pointer;
   ClutterInputDevice *core_keyboard;
 
+  ClutterPointerConstrainCallback constrain_callback;
+  gpointer                        constrain_data;
+  GDestroyNotify                  constrain_data_notify;
+
   ClutterStageManager *stage_manager;
   guint stage_added_handler;
   guint stage_removed_handler;
@@ -259,8 +263,17 @@ notify_relative_motion (ClutterEventSource *source,
   clutter_input_device_get_coords (manager_evdev->priv->core_pointer, NULL, &point);
   new_x = point.x + dx;
   new_y = point.y + dy;
-  new_x = CLAMP (new_x, 0.f, stage_width - 1);
-  new_y = CLAMP (new_y, 0.f, stage_height - 1);
+
+  if (manager_evdev->priv->constrain_callback)
+    {
+      manager_evdev->priv->constrain_callback (manager_evdev->priv->core_pointer, time_, &new_x, &new_y,
+                                              manager_evdev->priv->constrain_data);
+    }
+  else
+    {
+      new_x = CLAMP (new_x, 0.f, stage_width - 1);
+      new_y = CLAMP (new_y, 0.f, stage_height - 1);
+    }
 
   event->motion.time = time_;
   event->motion.stage = stage;
@@ -1029,6 +1042,9 @@ clutter_device_manager_evdev_finalize (GObject *object)
     }
   g_slist_free (priv->event_sources);
 
+  if (priv->constrain_data_notify)
+    priv->constrain_data_notify (priv->constrain_data);
+
   G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object);
 }
 
@@ -1313,3 +1329,36 @@ clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev,
   for (i = 0; i < priv->keys->len; i++)
     xkb_state_update_key (priv->xkb, g_array_index (priv->keys, guint32, i), XKB_KEY_DOWN);
 }
+
+/**
+ * clutter_evdev_set_pointer_constrain_callback:
+ * @evdev: the #ClutterDeviceManager created by the evdev backend
+ * @callback: the callback
+ * @user_data:
+ * @user_data_notify:
+ *
+ * Sets a callback to be invoked for every pointer motion. The callback
+ * can then modify the new pointer coordinates to constrain movement within
+ * a specific region.
+ */
+void
+clutter_evdev_set_pointer_constrain_callback (ClutterDeviceManager            *evdev,
+                                             ClutterPointerConstrainCallback  callback,
+                                             gpointer                         user_data,
+                                             GDestroyNotify                   user_data_notify)
+{
+  ClutterDeviceManagerEvdev *manager_evdev;
+  ClutterDeviceManagerEvdevPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
+
+  manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
+  priv = manager_evdev->priv;
+
+  if (priv->constrain_data_notify)
+    priv->constrain_data_notify (priv->constrain_data);
+
+  priv->constrain_callback = callback;
+  priv->constrain_data = user_data;
+  priv->constrain_data_notify = user_data_notify;
+}
diff --git a/clutter/evdev/clutter-evdev.h b/clutter/evdev/clutter-evdev.h
index fea26cb..88feaf5 100644
--- a/clutter/evdev/clutter-evdev.h
+++ b/clutter/evdev/clutter-evdev.h
@@ -51,6 +51,33 @@ void  clutter_evdev_set_open_callback (ClutterOpenDeviceCallback callback,
 void  clutter_evdev_release_devices (void);
 void  clutter_evdev_reclaim_devices (void);
 
+/**
+ * ClutterPointerConstrainCallback:
+ * @device: the core pointer device
+ * @time: the event time in milliseconds
+ * @x: (inout): the new X coordinate
+ * @y: (inout): the new Y coordinate
+ * @user_data:
+ *
+ * This callback will be called for all pointer motion events, and should
+ * update (@x, @y) to constrain the pointer position appropriately.
+ * The subsequent motion event will use the updated values as the new coordinates.
+ * Note that the coordinates are not clamped to the stage size, and the callback
+ * must make sure that this happens before it returns.
+ * Also note that the event will be emitted even if the pointer is constrained
+ * to be in the same position.
+ */
+typedef void (*ClutterPointerConstrainCallback) (ClutterInputDevice *device,
+                                                guint32             time,
+                                                float              *x,
+                                                float              *y,
+                                                gpointer            user_data);
+
+void  clutter_evdev_set_pointer_constrain_callback (ClutterDeviceManager            *evdev,
+                                                   ClutterPointerConstrainCallback  callback,
+                                                   gpointer                         user_data,
+                                                   GDestroyNotify                   user_data_notify);
+
 struct xkb_state * clutter_evdev_get_keyboard_state (ClutterDeviceManager *evdev);
 void               clutter_evdev_set_keyboard_map   (ClutterDeviceManager *evdev,
                                                     struct xkb_keymap    *keymap);


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