[clutter] evdev: Recycle device ids after devices are removed



commit a10200509e7aa25d43373c586e2539739806e914
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Sep 30 14:26:09 2015 +0800

    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 29bef7e..28ae699 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 a5e9f52..2f6e1a9 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 bcf7baf..db190b1 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_evdev->libinput_device)
+    libinput_device_unref (device_evdev->libinput_device);
 
-  if (device->libinput_device)
-    libinput_device_unref (device->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,


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