udev: notify about a removed seat when the last device is removed
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 23 Dec 2013 04:16:03 +0000 (14:16 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Fri, 10 Jan 2014 01:08:24 +0000 (11:08 +1000)
When the last device is removed from a seat, destroy the seat.
This guarantees seat removal events on libinput_suspend() as well.

Note that the seat must be manually unlinked, we can't rely on the unlinking
in libinput_seat_destroy. After the event, the seat's refcount is always > 1,
so the seat will live on until the event is destroyed. We need to make sure
it's not in the list anymore though.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/udev-seat.c

index 08e7ada711243ff4044dc370f1f00743adefa312..97f8259cbe7d710997c337e46b76892ef7601cb0 100644 (file)
@@ -198,6 +198,8 @@ evdev_udev_handler(void *data)
                                                 device->devname, device->devnode);
                                        close_restricted(libinput, device->fd);
                                        evdev_device_remove(device);
+                                       if (list_empty(&seat->base.devices_list))
+                                               notify_removed_seat(&seat->base);
                                        libinput_seat_unref(&seat->base);
                                        break;
                                }
@@ -219,6 +221,15 @@ udev_input_remove_devices(struct udev_input *input)
                                   &seat->base.devices_list, base.link) {
                        close_restricted(&input->base, device->fd);
                        evdev_device_remove(device);
+                       if (list_empty(&seat->base.devices_list)) {
+                               notify_removed_seat(&seat->base);
+                               /* seat is referenced by the event, so make
+                                  sure it's dropped from the seat list now,
+                                  to be freed whenever the device is
+                                  removed */
+                               list_remove(&seat->base.link);
+                               list_init(&seat->base.link);
+                       }
                        libinput_seat_unref(&seat->base);
                }
        }