diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c index dd503bbe6..866676395 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 fea26cb27..88feaf5de 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);