seat->logical_name = strdup(logical_name);
seat->destroy = destroy;
list_init(&seat->devices_list);
+ list_insert(&libinput->seat_list, &seat->link);
}
LIBINPUT_EXPORT void
*
* Get the seat associated with this input device.
*
+ * A seat can be uniquely identified by the physical and logical seat name.
+ * There will ever be only one seat instance with a given physical and logical
+ * seat name pair at any given time, but if no external reference is kept, it
+ * may be destroyed if no device belonging to it is left.
+ *
* @param device A previously obtained device
* @return The seat this input device belongs to
*/
continue;
evdev_device_remove(device);
- if (list_empty(&seat->devices_list)) {
- /* if the seat may be referenced by the
- client, so make sure it's dropped from
- the seat list now, to be freed whenever
- * the device is removed */
- list_remove(&seat->link);
- list_init(&seat->link);
- }
break;
}
}
libinput_seat_init(&seat->base, &input->base, seat_name,
seat_logical_name, path_seat_destroy);
- list_insert(&input->base.seat_list, &seat->base.link);
return seat;
}
list_for_each_safe(device, next,
&seat->base.devices_list, base.link) {
evdev_device_remove(device);
- if (list_empty(&seat->base.devices_list)) {
- /* if the seat may be referenced by the
- client, 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);
}
libinput_seat_init(&seat->base, &input->base,
device_seat, seat_name,
udev_seat_destroy);
- list_insert(&input->base.seat_list, &seat->base.link);
return seat;
}
}
END_TEST
+START_TEST(path_seat_recycle)
+{
+ struct libinput *li;
+ struct libevdev *evdev;
+ struct libevdev_uinput *uinput;
+ int rc;
+ void *userdata = &rc;
+ struct libinput_event *ev;
+ struct libinput_device *device;
+ struct libinput_seat *saved_seat = NULL;
+ struct libinput_seat *seat;
+ int data = 0;
+ int found = 0;
+ void *user_data;
+
+ evdev = libevdev_new();
+ ck_assert(evdev != NULL);
+
+ libevdev_set_name(evdev, "test device");
+ libevdev_enable_event_code(evdev, EV_KEY, BTN_LEFT, NULL);
+ libevdev_enable_event_code(evdev, EV_KEY, BTN_RIGHT, NULL);
+ libevdev_enable_event_code(evdev, EV_REL, REL_X, NULL);
+ libevdev_enable_event_code(evdev, EV_REL, REL_Y, NULL);
+
+ rc = libevdev_uinput_create_from_device(evdev,
+ LIBEVDEV_UINPUT_OPEN_MANAGED,
+ &uinput);
+ ck_assert_int_eq(rc, 0);
+ libevdev_free(evdev);
+
+ li = libinput_path_create_context(&simple_interface, userdata);
+ ck_assert(li != NULL);
+
+ device = libinput_path_add_device(li,
+ libevdev_uinput_get_devnode(uinput));
+ ck_assert(device != NULL);
+
+ libinput_dispatch(li);
+ while ((ev = libinput_get_event(li))) {
+ switch (libinput_event_get_type(ev)) {
+ case LIBINPUT_EVENT_DEVICE_ADDED:
+ if (saved_seat)
+ break;
+
+ device = libinput_event_get_device(ev);
+ ck_assert(device != NULL);
+ saved_seat = libinput_device_get_seat(device);
+ libinput_seat_set_user_data(saved_seat, &data);
+ libinput_seat_ref(saved_seat);
+ break;
+ default:
+ break;
+ }
+
+ libinput_event_destroy(ev);
+ }
+
+ ck_assert(saved_seat != NULL);
+
+ libinput_suspend(li);
+
+ litest_drain_events(li);
+
+ libinput_resume(li);
+
+ libinput_dispatch(li);
+ while ((ev = libinput_get_event(li))) {
+ switch (libinput_event_get_type(ev)) {
+ case LIBINPUT_EVENT_DEVICE_ADDED:
+ device = libinput_event_get_device(ev);
+ ck_assert(device != NULL);
+
+ seat = libinput_device_get_seat(device);
+ user_data = libinput_seat_get_user_data(seat);
+ if (user_data == &data) {
+ found = 1;
+ ck_assert(seat == saved_seat);
+ }
+ break;
+ default:
+ break;
+ }
+
+ libinput_event_destroy(ev);
+ }
+
+ ck_assert(found == 1);
+
+ libinput_destroy(li);
+
+ libevdev_uinput_destroy(uinput);
+}
+END_TEST
+
int main (int argc, char **argv) {
litest_add("path:create", path_create_NULL, LITEST_ANY, LITEST_ANY);
litest_add("path:device events", path_add_invalid_path, LITEST_ANY, LITEST_ANY);
litest_add("path:device events", path_remove_device, LITEST_ANY, LITEST_ANY);
litest_add("path:device events", path_double_remove_device, LITEST_ANY, LITEST_ANY);
+ litest_add("path:seat", path_seat_recycle,
+ LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
return litest_run(argc, argv);
}
}
END_TEST
+START_TEST(udev_seat_recycle)
+{
+ struct udev *udev;
+ struct libinput *li;
+ struct libinput_event *ev;
+ struct libinput_device *device;
+ struct libinput_seat *saved_seat = NULL;
+ struct libinput_seat *seat;
+ int data = 0;
+ int found = 0;
+ void *user_data;
+
+ udev = udev_new();
+ ck_assert(udev != NULL);
+
+ li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
+ ck_assert(li != NULL);
+
+ libinput_dispatch(li);
+ while ((ev = libinput_get_event(li))) {
+ switch (libinput_event_get_type(ev)) {
+ case LIBINPUT_EVENT_DEVICE_ADDED:
+ if (saved_seat)
+ break;
+
+ device = libinput_event_get_device(ev);
+ ck_assert(device != NULL);
+ saved_seat = libinput_device_get_seat(device);
+ libinput_seat_set_user_data(saved_seat, &data);
+ libinput_seat_ref(saved_seat);
+ break;
+ default:
+ break;
+ }
+
+ libinput_event_destroy(ev);
+ }
+
+ ck_assert(saved_seat != NULL);
+
+ libinput_suspend(li);
+
+ litest_drain_events(li);
+
+ libinput_resume(li);
+
+ libinput_dispatch(li);
+ while ((ev = libinput_get_event(li))) {
+ switch (libinput_event_get_type(ev)) {
+ case LIBINPUT_EVENT_DEVICE_ADDED:
+ device = libinput_event_get_device(ev);
+ ck_assert(device != NULL);
+
+ seat = libinput_device_get_seat(device);
+ user_data = libinput_seat_get_user_data(seat);
+ if (user_data == &data) {
+ found = 1;
+ ck_assert(seat == saved_seat);
+ }
+ break;
+ default:
+ break;
+ }
+
+ libinput_event_destroy(ev);
+ }
+
+ ck_assert(found == 1);
+
+ libinput_destroy(li);
+ udev_unref(udev);
+}
+END_TEST
+
int main (int argc, char **argv) {
litest_add_no_device("udev:create", udev_create_NULL);
litest_add("udev:suspend", udev_double_resume, LITEST_ANY, LITEST_ANY);
litest_add("udev:suspend", udev_suspend_resume, LITEST_ANY, LITEST_ANY);
litest_add("udev:device events", udev_device_sysname, LITEST_ANY, LITEST_ANY);
+ litest_add("udev:seat", udev_seat_recycle, LITEST_ANY, LITEST_ANY);
return litest_run(argc, argv);
}