From 488639eb63f0c26d65db0700e94b1067da873617 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 22 Feb 2014 20:35:23 +0100 Subject: [PATCH] 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 --- clutter/x11/clutter-device-manager-xi2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c index f9614f5dd..d508026dd 100644 --- a/clutter/x11/clutter-device-manager-xi2.c +++ b/clutter/x11/clutter-device-manager-xi2.c @@ -401,7 +401,9 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11, 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; int n_devices; @@ -1435,6 +1437,9 @@ clutter_device_manager_xi2_constructed (GObject *gobject) { XIDeviceInfo *xi_device = &info[i]; + if (!xi_device->enabled) + continue; + add_device (manager_xi2, backend_x11, xi_device, TRUE); if (xi_device->use == XIMasterPointer ||