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 *