diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2014-11-19 13:43:59 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-11-25 16:34:22 +1000 |
commit | d546c284c87796ca816b208103b9ef5c33a6099d (patch) | |
tree | 800f07d08320cdaf17689d25425eca65f78d2166 | |
parent | ff2b0cb84b6968e9772c92180b947ba80187f9fe (diff) | |
download | libinput-d546c284c87796ca816b208103b9ef5c33a6099d.tar.gz |
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 <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | src/libinput-private.h | 2 | ||||
-rw-r--r-- | src/libinput.c | 13 | ||||
-rw-r--r-- | src/libinput.h | 26 | ||||
-rw-r--r-- | src/path.c | 20 | ||||
-rw-r--r-- | src/udev-seat.c | 19 |
5 files changed, 80 insertions, 0 deletions
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 @@ -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. @@ -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 * |