mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-11 05:50:28 +01:00
Make it possible to have persistent libinput_seat instances
With this patch, a user can keep a reference to a libinput_seat instance, which will cause the seat to never be unlinked from the libinput context nor destroyed. Previously, a when the last device of a seat was removed, the seat was unlinked and if a new device was discovered with a previously empty seat a new seat instance would always be created, meaning two potential seat instances with identical physical and logical seat name pairs. Signed-off-by: Jonas Ådahl <jadahl@gmail.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
26a1fff787
commit
b34139c9e7
6 changed files with 177 additions and 18 deletions
|
|
@ -508,6 +508,7 @@ libinput_seat_init(struct libinput_seat *seat,
|
|||
seat->logical_name = strdup(logical_name);
|
||||
seat->destroy = destroy;
|
||||
list_init(&seat->devices_list);
|
||||
list_insert(&libinput->seat_list, &seat->link);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
|
|
|
|||
|
|
@ -1069,6 +1069,11 @@ libinput_device_get_output_name(struct libinput_device *device);
|
|||
*
|
||||
* 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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -49,14 +49,6 @@ path_disable_device(struct libinput *libinput,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -97,7 +89,6 @@ path_seat_create(struct path_input *input,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,14 +203,6 @@ udev_input_remove_devices(struct udev_input *input)
|
|||
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);
|
||||
}
|
||||
|
|
@ -311,7 +303,6 @@ udev_seat_create(struct udev_input *input,
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
96
test/path.c
96
test/path.c
|
|
@ -778,6 +778,100 @@ START_TEST(path_add_device_suspend_resume_remove_device)
|
|||
}
|
||||
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);
|
||||
|
|
@ -796,6 +890,8 @@ int main (int argc, char **argv) {
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
75
test/udev.c
75
test/udev.c
|
|
@ -327,6 +327,80 @@ START_TEST(udev_device_sysname)
|
|||
}
|
||||
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);
|
||||
|
|
@ -339,6 +413,7 @@ int main (int argc, char **argv) {
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue