From a10200509e7aa25d43373c586e2539739806e914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 30 Sep 2015 14:26:09 +0800 Subject: [PATCH] evdev: Recycle device ids after devices are removed In order to not grow the device id number forever, recycle the ids whenever a device is released. https://bugzilla.gnome.org/show_bug.cgi?id=755849 --- clutter/evdev/clutter-device-manager-evdev.c | 62 ++++++++++++++++++++ clutter/evdev/clutter-device-manager-evdev.h | 5 ++ clutter/evdev/clutter-input-device-evdev.c | 36 ++++++------ 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c index 29bef7e72..28ae69949 100644 --- a/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/evdev/clutter-device-manager-evdev.c @@ -65,6 +65,16 @@ #define INITIAL_POINTER_X 16 #define INITIAL_POINTER_Y 16 +/* + * Clutter makes the assumption that two core devices have ID's 2 and 3 (core + * pointer and core keyboard). + * + * Since the two first devices that will ever be created will be the virtual + * pointer and virtual keyboard of the first seat, we fulfill the made + * assumptions by having the first device having ID 2 and following 3. + */ +#define INITIAL_DEVICE_ID 2 + typedef struct _ClutterTouchState ClutterTouchState; typedef struct _ClutterEventFilter ClutterEventFilter; @@ -142,6 +152,9 @@ struct _ClutterDeviceManagerEvdevPrivate guint stage_removed_handler; GSList *event_filters; + + gint device_id_next; + GList *free_device_ids; }; static void clutter_device_manager_evdev_event_extender_init (ClutterEventExtenderInterface *iface); @@ -1944,6 +1957,8 @@ clutter_device_manager_evdev_finalize (GObject *object) if (priv->libinput != NULL) libinput_unref (priv->libinput); + g_list_free (priv->free_device_ids); + G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object); } @@ -2043,6 +2058,8 @@ clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self) "stage-removed", G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb), self); + + priv->device_id_next = INITIAL_DEVICE_ID; } void @@ -2061,6 +2078,51 @@ _clutter_events_evdev_uninit (ClutterBackend *backend) CLUTTER_NOTE (EVENT, "Uninitializing evdev backend"); } +gint +_clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + GList *first; + gint next_id; + + if (priv->free_device_ids == NULL) + { + gint i; + + /* We ran out of free ID's, so append 10 new ones. */ + for (i = 0; i < 10; i++) + priv->free_device_ids = + g_list_append (priv->free_device_ids, + GINT_TO_POINTER (priv->device_id_next++)); + } + + first = g_list_first (priv->free_device_ids); + next_id = GPOINTER_TO_INT (first->data); + priv->free_device_ids = g_list_remove_link (priv->free_device_ids, first); + + return next_id; +} + +static int +compare_ids (gconstpointer a, + gconstpointer b) +{ + return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b); +} + +void +_clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *device) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + gint device_id; + + device_id = clutter_input_device_get_device_id (device); + priv->free_device_ids = g_list_insert_sorted (priv->free_device_ids, + GINT_TO_POINTER (device_id), + compare_ids); +} + /** * clutter_evdev_release_devices: * diff --git a/clutter/evdev/clutter-device-manager-evdev.h b/clutter/evdev/clutter-device-manager-evdev.h index a5e9f52f8..2f6e1a96e 100644 --- a/clutter/evdev/clutter-device-manager-evdev.h +++ b/clutter/evdev/clutter-device-manager-evdev.h @@ -56,6 +56,11 @@ GType clutter_device_manager_evdev_get_type (void) G_GNUC_CONST; void _clutter_events_evdev_init (ClutterBackend *backend); void _clutter_events_evdev_uninit (ClutterBackend *backend); +gint _clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev *manager_evdev); + +void _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *device); + G_END_DECLS #endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */ diff --git a/clutter/evdev/clutter-input-device-evdev.c b/clutter/evdev/clutter-input-device-evdev.c index bcf7bafc6..db190b192 100644 --- a/clutter/evdev/clutter-input-device-evdev.c +++ b/clutter/evdev/clutter-input-device-evdev.c @@ -32,6 +32,7 @@ #include "clutter-evdev.h" #include "clutter-input-device-evdev.h" +#include "clutter-device-manager-evdev.h" typedef struct _ClutterInputDeviceClass ClutterInputDeviceEvdevClass; @@ -41,25 +42,18 @@ G_DEFINE_TYPE (ClutterInputDeviceEvdev, clutter_input_device_evdev, CLUTTER_TYPE_INPUT_DEVICE) -/* - * Clutter makes the assumption that two core devices have ID's 2 and 3 (core - * pointer and core keyboard). - * - * Since the two first devices that will ever be created will be the virtual - * pointer and virtual keyboard of the first seat, we fulfill the made - * assumptions by having the first device having ID 2 and following 3. - */ -#define INITIAL_DEVICE_ID 2 - -static gint global_device_id_next = INITIAL_DEVICE_ID; - static void clutter_input_device_evdev_finalize (GObject *object) { - ClutterInputDeviceEvdev *device = CLUTTER_INPUT_DEVICE_EVDEV (object); + ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (object); + ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (object); + ClutterDeviceManagerEvdev *manager_evdev = + CLUTTER_DEVICE_MANAGER_EVDEV (device->device_manager); - if (device->libinput_device) - libinput_device_unref (device->libinput_device); + if (device_evdev->libinput_device) + libinput_device_unref (device_evdev->libinput_device); + + _clutter_device_manager_evdev_release_device_id (manager_evdev, device); G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object); } @@ -107,13 +101,17 @@ _clutter_input_device_evdev_new (ClutterDeviceManager *manager, { ClutterInputDeviceEvdev *device; ClutterInputDeviceType type; + ClutterDeviceManagerEvdev *manager_evdev; gchar *vendor, *product; + gint device_id; type = _clutter_input_device_evdev_determine_type (libinput_device); vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device)); product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device)); + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, - "id", global_device_id_next++, + "id", device_id, "name", libinput_device_get_sysname (libinput_device), "device-manager", manager, "device-type", type, @@ -148,7 +146,9 @@ _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager, ClutterInputDeviceType type) { ClutterInputDeviceEvdev *device; + ClutterDeviceManagerEvdev *manager_evdev; const char *name; + gint device_id; switch (type) { @@ -163,8 +163,10 @@ _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager, break; }; + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, - "id", global_device_id_next++, + "id", device_id, "name", name, "device-manager", manager, "device-type", type,