x11: Avoid invalid ClutterInputDevice pointers in the device list

Due to the way add_device() invariably adds to the master/slave device
lists, while keeping ClutterInputDevices 1:1 with device IDs, it may
leave invalid pointers in the list if add_device() is called multiple
times for the same device ID. There are two situations where this may
happen:

1) If devices are disabled and later enabled: devices are added invariably
   to the master/slave lists on constructed(), but then on XIDeviceEnabled
   they'd get added yet again.
2) Racy cases where the ClutterDeviceManager is created around the same time
   XIHierarchyEvents are sent. When getting the XIDeviceInfo on constructed(),
   these devices may already appear as enabled, even though XIDeviceEnabled
   is seen through XIHierarchyEvents processed in the event loop sortly after.

   This last case can be seen when starting gnome-shell on a different tty,
   and entering in the one it's been spawned on, clutter initialization
   happens around the same time devices are added back because of the tty
   switch, and multiple extra ClutterInputDevices are created.

https://bugzilla.gnome.org/show_bug.cgi?id=724971
This commit is contained in:
Carlos Garnacho 2014-02-22 20:35:23 +01:00
parent 086190273b
commit 45935fbe29

View File

@ -402,7 +402,9 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
for (i = 0; i < ev->num_info; i++) for (i = 0; i < ev->num_info; i++)
{ {
if (ev->info[i].flags & XIDeviceEnabled) if (ev->info[i].flags & XIDeviceEnabled &&
!g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (ev->info[i].deviceid)))
{ {
XIDeviceInfo *info; XIDeviceInfo *info;
int n_devices; int n_devices;
@ -1383,6 +1385,9 @@ clutter_device_manager_xi2_constructed (GObject *gobject)
{ {
XIDeviceInfo *xi_device = &info[i]; XIDeviceInfo *xi_device = &info[i];
if (!xi_device->enabled)
continue;
add_device (manager_xi2, backend_x11, xi_device, TRUE); add_device (manager_xi2, backend_x11, xi_device, TRUE);
if (xi_device->use == XIMasterPointer || if (xi_device->use == XIMasterPointer ||