From d546c284c87796ca816b208103b9ef5c33a6099d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Nov 2014 13:43:59 +1000 Subject: [PATCH] Add libinput_device_set_seat_logical_name() to change seats at runtime The seat of a device is currently immutable, but a device may (in a multi-pointer case) move between different logical seats. Moving it between seats is akin to removing it and re-plugging it, so let's do exactly that. The physical seat name stays immutable. Pro: - device handling after changing a seat remains identical as handling any other device. Con: - tracking a device across seat changes is difficult - this is not an atomic operation, if re-adding the device fails it stays removed from the original seat and is now dead Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput-private.h | 2 ++ src/libinput.c | 13 +++++++++++++ src/libinput.h | 26 ++++++++++++++++++++++++++ src/path.c | 20 ++++++++++++++++++++ src/udev-seat.c | 19 +++++++++++++++++++ 5 files changed, 80 insertions(+) diff --git a/src/libinput-private.h b/src/libinput-private.h index 29d3a073..4a9bd540 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -36,6 +36,8 @@ struct libinput_interface_backend { int (*resume)(struct libinput *libinput); void (*suspend)(struct libinput *libinput); void (*destroy)(struct libinput *libinput); + int (*device_change_seat)(struct libinput_device *device, + const char *seat_name); }; struct libinput { diff --git a/src/libinput.c b/src/libinput.c index aa12bfc8..c318eeec 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1213,6 +1213,19 @@ libinput_device_get_seat(struct libinput_device *device) return device->seat; } +LIBINPUT_EXPORT int +libinput_device_set_seat_logical_name(struct libinput_device *device, + const char *name) +{ + struct libinput *libinput = device->seat->libinput; + + if (name == NULL) + return -1; + + return libinput->interface_backend->device_change_seat(device, + name); +} + LIBINPUT_EXPORT void libinput_device_led_update(struct libinput_device *device, enum libinput_led leds) diff --git a/src/libinput.h b/src/libinput.h index 01ded185..26d94ff4 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1370,6 +1370,32 @@ libinput_device_get_output_name(struct libinput_device *device); struct libinput_seat * libinput_device_get_seat(struct libinput_device *device); +/** + * @ingroup device + * + * Change the logical seat associated with this device by removing the + * device and adding it to the new seat. + * + * This command is identical to physically unplugging the device, then + * re-plugging it as member of the new seat, + * @ref LIBINPUT_EVENT_DEVICE_REMOVED and @ref LIBINPUT_EVENT_DEVICE_ADDED + * events are sent accordingly. Those events mark the end of the lifetime + * of this device and the start of a new device. + * + * If the logical seat name already exists in the device's physical seat, + * the device is added to this seat. Otherwise, a new seat is created. + * + * @note This change applies to this device until removal or @ref + * libinput_suspend(), whichever happens earlier. + * + * @param device A previously obtained device + * @param name The new logical seat name + * @return 0 on success, non-zero on error + */ +int +libinput_device_set_seat_logical_name(struct libinput_device *device, + const char *name); + /** * @ingroup device * diff --git a/src/path.c b/src/path.c index 11b736cf..dd70efc6 100644 --- a/src/path.c +++ b/src/path.c @@ -235,10 +235,30 @@ path_create_device(struct libinput *libinput, return device; } +static int +path_device_change_seat(struct libinput_device *device, + const char *seat_name) +{ + struct libinput *libinput = device->seat->libinput; + struct evdev_device *evdev_device = (struct evdev_device *)device; + struct udev_device *udev_device = NULL; + int rc = -1; + + udev_device = evdev_device->udev_device; + udev_device_ref(udev_device); + libinput_path_remove_device(device); + + if (path_create_device(libinput, udev_device, seat_name) != NULL) + rc = 0; + udev_device_unref(udev_device); + return rc; +} + static const struct libinput_interface_backend interface_backend = { .resume = path_input_enable, .suspend = path_input_disable, .destroy = path_input_destroy, + .device_change_seat = path_device_change_seat, }; LIBINPUT_EXPORT struct libinput * diff --git a/src/udev-seat.c b/src/udev-seat.c index c69d175d..f7a3df34 100644 --- a/src/udev-seat.c +++ b/src/udev-seat.c @@ -332,10 +332,29 @@ udev_seat_get_named(struct udev_input *input, const char *seat_name) return NULL; } +static int +udev_device_change_seat(struct libinput_device *device, + const char *seat_name) +{ + struct libinput *libinput = device->seat->libinput; + struct udev_input *input = (struct udev_input *)libinput; + struct evdev_device *evdev_device = (struct evdev_device *)device; + struct udev_device *udev_device = evdev_device->udev_device; + int rc; + + udev_device_ref(udev_device); + device_removed(udev_device, input); + rc = device_added(udev_device, input, seat_name); + udev_device_unref(udev_device); + + return rc; +} + static const struct libinput_interface_backend interface_backend = { .resume = udev_input_enable, .suspend = udev_input_disable, .destroy = udev_input_destroy, + .device_change_seat = udev_device_change_seat, }; LIBINPUT_EXPORT struct libinput *