mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 14:00:29 +01:00
udev: Refcount the seat for each device
Use the seat's internal refcounting to up the reference each time we have a device using it. This fixes the issue with seats being created but never actually removed by anything. udev_seat_get_named() will now return a seat with refcount 1 for a newly created seat, or just up the refcount for the seat if it already exists. This requires that the ADDED_SEAT and REMOVED_SEAT events up the refcount of the seat as well: a device may be removed before the event is processed, without the refcount the seat would be destroyed (if it's the last device on the seat). Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
1ee5b28c6e
commit
6fcaf7699c
2 changed files with 27 additions and 17 deletions
|
|
@ -478,6 +478,10 @@ libinput_event_destroy(struct libinput_event *event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (libinput_event_get_type(event) == LIBINPUT_EVENT_ADDED_SEAT ||
|
||||
libinput_event_get_type(event) == LIBINPUT_EVENT_REMOVED_SEAT)
|
||||
libinput_seat_unref(((struct libinput_event_added_seat*)event)->seat);
|
||||
|
||||
free(event);
|
||||
}
|
||||
|
||||
|
|
@ -647,6 +651,8 @@ notify_added_seat(struct libinput_seat *seat)
|
|||
if (!added_seat_event)
|
||||
return;
|
||||
|
||||
libinput_seat_ref(seat);
|
||||
|
||||
*added_seat_event = (struct libinput_event_added_seat) {
|
||||
.seat = seat,
|
||||
};
|
||||
|
|
@ -665,6 +671,8 @@ notify_removed_seat(struct libinput_seat *seat)
|
|||
if (!removed_seat_event)
|
||||
return;
|
||||
|
||||
libinput_seat_ref(seat);
|
||||
|
||||
*removed_seat_event = (struct libinput_event_removed_seat) {
|
||||
.seat = seat,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -68,8 +68,13 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
|
||||
seat = udev_seat_get_named(input, seat_name);
|
||||
|
||||
if (seat == NULL)
|
||||
return -1;
|
||||
if (seat)
|
||||
libinput_seat_ref(&seat->base);
|
||||
else {
|
||||
seat = udev_seat_create(input, seat_name);
|
||||
if (!seat)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Use non-blocking mode so that we can loop on read on
|
||||
* evdev_device_data() until all events on the fd are
|
||||
|
|
@ -77,18 +82,18 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
log_info("opening input device '%s' failed (%s).\n", devnode, strerror(-fd));
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
device = evdev_device_create(&seat->base, devnode, sysname, fd);
|
||||
if (device == EVDEV_UNHANDLED_DEVICE) {
|
||||
close_restricted(libinput, fd);
|
||||
log_info("not using input device '%s'.\n", devnode);
|
||||
return 0;
|
||||
goto error;
|
||||
} else if (device == NULL) {
|
||||
close_restricted(libinput, fd);
|
||||
log_info("failed to create input device '%s'.\n", devnode);
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
calibration_values =
|
||||
|
|
@ -118,6 +123,10 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
device->output_name = strdup(output_name);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if (seat)
|
||||
libinput_seat_unref(&seat->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -189,6 +198,7 @@ evdev_udev_handler(void *data)
|
|||
device->devname, device->devnode);
|
||||
close_restricted(libinput, device->fd);
|
||||
evdev_device_remove(device);
|
||||
libinput_seat_unref(&seat->base);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -202,13 +212,14 @@ static void
|
|||
udev_input_remove_devices(struct udev_input *input)
|
||||
{
|
||||
struct evdev_device *device, *next;
|
||||
struct udev_seat *seat;
|
||||
struct udev_seat *seat, *tmp;
|
||||
|
||||
list_for_each(seat, &input->base.seat_list, base.link) {
|
||||
list_for_each_safe(seat, tmp, &input->base.seat_list, base.link) {
|
||||
list_for_each_safe(device, next,
|
||||
&seat->base.devices_list, base.link) {
|
||||
close_restricted(&input->base, device->fd);
|
||||
evdev_device_remove(device);
|
||||
libinput_seat_unref(&seat->base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -278,16 +289,12 @@ udev_input_enable(struct libinput *libinput)
|
|||
static void
|
||||
udev_input_destroy(struct libinput *input)
|
||||
{
|
||||
struct libinput_seat *seat, *next;
|
||||
struct udev_input *udev_input = (struct udev_input*)input;
|
||||
|
||||
if (input == NULL)
|
||||
return;
|
||||
|
||||
udev_input_disable(input);
|
||||
list_for_each_safe(seat, next, &input->seat_list, link) {
|
||||
libinput_seat_unref(seat);
|
||||
}
|
||||
udev_unref(udev_input->udev);
|
||||
free(udev_input->seat_id);
|
||||
}
|
||||
|
|
@ -325,12 +332,7 @@ udev_seat_get_named(struct udev_input *input, const char *seat_name)
|
|||
return seat;
|
||||
}
|
||||
|
||||
seat = udev_seat_create(input, seat_name);
|
||||
|
||||
if (!seat)
|
||||
return NULL;
|
||||
|
||||
return seat;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct libinput_interface_backend interface_backend = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue