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 <peter.hutte...@who-t.net> --- 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 8c75d1f..07db7fd 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 3f5370f..7b94320 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 092b0e7..9c9a313 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1373,6 +1373,32 @@ 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 + * * Update the LEDs on the device, if any. If the device does not have * LEDs, or does not have one or more of the LEDs given in the mask, this * function does nothing. diff --git a/src/path.c b/src/path.c index fef1d46..57f4cc6 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 c69d175..f7a3df3 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 * -- 2.1.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel