From 91ee1ceca452176667708ad898cd59196712a76d Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 25 Apr 2014 19:54:35 +0200 Subject: [PATCH] evdev: Add evdev specific event filter function This function can be used to intercept or translate events that are unmanaged by clutter itself. https://bugzilla.gnome.org/show_bug.cgi?id=728967 --- clutter/evdev/clutter-device-manager-evdev.c | 132 +++++++++++++++++++ clutter/evdev/clutter-evdev.h | 11 ++ 2 files changed, 143 insertions(+) diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c index 30f39f3ab..aa4dc23a3 100644 --- a/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/evdev/clutter-device-manager-evdev.c @@ -62,6 +62,8 @@ #define INITIAL_POINTER_X 16 #define INITIAL_POINTER_Y 16 +typedef struct _ClutterEventFilter ClutterEventFilter; + struct _ClutterSeatEvdev { struct libinput_seat *libinput_seat; @@ -88,6 +90,13 @@ struct _ClutterSeatEvdev ClutterInputDevice *repeat_device; }; +struct _ClutterEventFilter +{ + ClutterEvdevFilterFunc func; + gpointer data; + GDestroyNotify destroy_notify; +}; + typedef struct _ClutterEventSource ClutterEventSource; struct _ClutterDeviceManagerEvdevPrivate @@ -111,6 +120,8 @@ struct _ClutterDeviceManagerEvdevPrivate ClutterStageManager *stage_manager; guint stage_added_handler; guint stage_removed_handler; + + GSList *event_filters; }; G_DEFINE_TYPE_WITH_PRIVATE (ClutterDeviceManagerEvdev, @@ -1098,10 +1109,40 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev, return handled; } +static gboolean +filter_event (ClutterDeviceManagerEvdev *manager_evdev, + struct libinput_event *event) +{ + gboolean retval = CLUTTER_EVENT_PROPAGATE; + ClutterEventFilter *filter; + GSList *tmp_list; + + tmp_list = manager_evdev->priv->event_filters; + + while (tmp_list) + { + filter = tmp_list->data; + retval = filter->func (event, filter->data); + tmp_list = tmp_list->next; + + if (retval != CLUTTER_EVENT_PROPAGATE) + break; + } + + return retval; +} + static void process_event (ClutterDeviceManagerEvdev *manager_evdev, struct libinput_event *event) { + gboolean retval; + + retval = filter_event (manager_evdev, event); + + if (retval != CLUTTER_EVENT_PROPAGATE) + return; + if (process_base_event (manager_evdev, event)) return; if (process_device_event (manager_evdev, event)) @@ -1639,3 +1680,94 @@ clutter_evdev_set_keyboard_repeat (ClutterDeviceManager *evdev, seat->repeat_delay = delay; seat->repeat_interval = interval; } + +/** + * clutter_evdev_add_filter: (skip) + * @func: (closure data): a filter function + * @data: (allow-none): user data to be passed to the filter function, or %NULL + * @destroy_notify: (allow-none): function to call on @data when the filter is removed, or %NULL + * + * Adds an event filter function. + * + * Since: 1.20 + * Stability: unstable + */ +void +clutter_evdev_add_filter (ClutterEvdevFilterFunc func, + gpointer data, + GDestroyNotify destroy_notify) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManager *manager; + ClutterEventFilter *filter; + + g_return_if_fail (func != NULL); + + manager = clutter_device_manager_get_default (); + + if (!CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager)) + { + g_critical ("The Clutter input backend is not a evdev backend"); + return; + } + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + + filter = g_new0 (ClutterEventFilter, 1); + filter->func = func; + filter->data = data; + filter->destroy_notify = destroy_notify; + + manager_evdev->priv->event_filters = + g_slist_append (manager_evdev->priv->event_filters, filter); +} + +/** + * clutter_evdev_remove_filter: (skip) + * @func: a filter function + * @data: (allow-none): user data to be passed to the filter function, or %NULL + * + * Removes the given filter function. + * + * Since: 1.20 + * Stability: unstable + */ +void +clutter_evdev_remove_filter (ClutterEvdevFilterFunc func, + gpointer data) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManager *manager; + ClutterEventFilter *filter; + GSList *tmp_list; + + g_return_if_fail (func != NULL); + + manager = clutter_device_manager_get_default (); + + if (!CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager)) + { + g_critical ("The Clutter input backend is not a evdev backend"); + return; + } + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + tmp_list = manager_evdev->priv->event_filters; + + while (tmp_list) + { + filter = tmp_list->data; + + if (filter->func == func && filter->data == data) + { + if (filter->destroy_notify) + filter->destroy_notify (filter->data); + g_free (filter); + manager_evdev->priv->event_filters = + g_slist_delete_link (manager_evdev->priv->event_filters, tmp_list); + return; + } + + tmp_list = tmp_list->next; + } +} diff --git a/clutter/evdev/clutter-evdev.h b/clutter/evdev/clutter-evdev.h index f97a3f5af..f85127fdd 100644 --- a/clutter/evdev/clutter-evdev.h +++ b/clutter/evdev/clutter-evdev.h @@ -102,6 +102,17 @@ void clutter_evdev_set_keyboard_repeat (ClutterDeviceManager *evdev, guint32 delay, guint32 interval); +typedef gboolean (* ClutterEvdevFilterFunc) (struct libinput_event *event, + gpointer data); + +CLUTTER_AVAILABLE_IN_1_20 +void clutter_evdev_add_filter (ClutterEvdevFilterFunc func, + gpointer data, + GDestroyNotify destroy_notify); +CLUTTER_AVAILABLE_IN_1_20 +void clutter_evdev_remove_filter (ClutterEvdevFilterFunc func, + gpointer data); + G_END_DECLS #endif /* __CLUTTER_EVDEV_H__ */