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
This commit is contained in:
Jonas Ådahl 2015-09-30 14:26:09 +08:00
parent 3a8ba7b173
commit a10200509e
3 changed files with 86 additions and 17 deletions

View File

@ -65,6 +65,16 @@
#define INITIAL_POINTER_X 16 #define INITIAL_POINTER_X 16
#define INITIAL_POINTER_Y 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 _ClutterTouchState ClutterTouchState;
typedef struct _ClutterEventFilter ClutterEventFilter; typedef struct _ClutterEventFilter ClutterEventFilter;
@ -142,6 +152,9 @@ struct _ClutterDeviceManagerEvdevPrivate
guint stage_removed_handler; guint stage_removed_handler;
GSList *event_filters; GSList *event_filters;
gint device_id_next;
GList *free_device_ids;
}; };
static void clutter_device_manager_evdev_event_extender_init (ClutterEventExtenderInterface *iface); 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) if (priv->libinput != NULL)
libinput_unref (priv->libinput); libinput_unref (priv->libinput);
g_list_free (priv->free_device_ids);
G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object); G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object);
} }
@ -2043,6 +2058,8 @@ clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self)
"stage-removed", "stage-removed",
G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb), G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb),
self); self);
priv->device_id_next = INITIAL_DEVICE_ID;
} }
void void
@ -2061,6 +2078,51 @@ _clutter_events_evdev_uninit (ClutterBackend *backend)
CLUTTER_NOTE (EVENT, "Uninitializing evdev 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: * clutter_evdev_release_devices:
* *

View File

@ -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_init (ClutterBackend *backend);
void _clutter_events_evdev_uninit (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 G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */ #endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */

View File

@ -32,6 +32,7 @@
#include "clutter-evdev.h" #include "clutter-evdev.h"
#include "clutter-input-device-evdev.h" #include "clutter-input-device-evdev.h"
#include "clutter-device-manager-evdev.h"
typedef struct _ClutterInputDeviceClass ClutterInputDeviceEvdevClass; typedef struct _ClutterInputDeviceClass ClutterInputDeviceEvdevClass;
@ -41,25 +42,18 @@ G_DEFINE_TYPE (ClutterInputDeviceEvdev,
clutter_input_device_evdev, clutter_input_device_evdev,
CLUTTER_TYPE_INPUT_DEVICE) 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 static void
clutter_input_device_evdev_finalize (GObject *object) 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) if (device_evdev->libinput_device)
libinput_device_unref (device->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); G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object);
} }
@ -107,13 +101,17 @@ _clutter_input_device_evdev_new (ClutterDeviceManager *manager,
{ {
ClutterInputDeviceEvdev *device; ClutterInputDeviceEvdev *device;
ClutterInputDeviceType type; ClutterInputDeviceType type;
ClutterDeviceManagerEvdev *manager_evdev;
gchar *vendor, *product; gchar *vendor, *product;
gint device_id;
type = _clutter_input_device_evdev_determine_type (libinput_device); type = _clutter_input_device_evdev_determine_type (libinput_device);
vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (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)); 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, device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
"id", global_device_id_next++, "id", device_id,
"name", libinput_device_get_sysname (libinput_device), "name", libinput_device_get_sysname (libinput_device),
"device-manager", manager, "device-manager", manager,
"device-type", type, "device-type", type,
@ -148,7 +146,9 @@ _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager,
ClutterInputDeviceType type) ClutterInputDeviceType type)
{ {
ClutterInputDeviceEvdev *device; ClutterInputDeviceEvdev *device;
ClutterDeviceManagerEvdev *manager_evdev;
const char *name; const char *name;
gint device_id;
switch (type) switch (type)
{ {
@ -163,8 +163,10 @@ _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager,
break; 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, device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
"id", global_device_id_next++, "id", device_id,
"name", name, "name", name,
"device-manager", manager, "device-manager", manager,
"device-type", type, "device-type", type,