Add libinput_device_set_seat_logical_name() to change seats at runtime
authorPeter Hutterer <peter.hutterer@who-t.net>
Wed, 19 Nov 2014 03:43:59 +0000 (13:43 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Tue, 25 Nov 2014 06:34:22 +0000 (16:34 +1000)
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>
src/libinput-private.h
src/libinput.c
src/libinput.h
src/path.c
src/udev-seat.c

index 29d3a0736c32278419d3564b41df28a43b0a969e..4a9bd540be25ce8947a26bc02ea7a7e85cdc3851 100644 (file)
@@ -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 {
index aa12bfc86e8401d22850d3d519976cd7ae705d04..c318eeeccbbd2a519f725171e4cc14521529109a 100644 (file)
@@ -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)
index 01ded1854a29618c192d111a63b6691086c0dc08..26d94ff4a37fe88f2febf409692a7c7b97492dfb 100644 (file)
@@ -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
  *
index 11b736cf0cd35ff9e3064287dbc34325ec0417d8..dd70efc645c60e74d00578502cd0355ede58a243 100644 (file)
@@ -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 *
index c69d175d1486500cd4540fd9e6016e21e0ab2665..f7a3df3478f4ab39a692c8aba68ddf408b6d7848 100644 (file)
@@ -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 *