evdev: add a internal device notification mechanism
authorPeter Hutterer <peter.hutterer@who-t.net>
Wed, 3 Sep 2014 04:34:52 +0000 (14:34 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 18 Sep 2014 03:29:42 +0000 (13:29 +1000)
When a device is added or removed, notify all internal devices about the
device change. This allows all devices to configure themselves depending on
other devices in the system. Prime use-case here is an internal touchpad that
wants to know if an external mouse is connected.

On device added, notification goes both ways: existing devices are notified
about the new device, and the new device is notified about existing devices.
On device removed, notification only goes one way.

In both cases, the internal notification is complete before the event is sent
to the caller.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev-mt-touchpad.c
src/evdev.c
src/evdev.h

index cfc41ecbeb2f9e7d1abb9210ecc61fec35ef158e..62becbaaa479d2e10ba615432e2f74db975af751 100644 (file)
@@ -678,7 +678,9 @@ tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
 
 static struct evdev_dispatch_interface tp_interface = {
        tp_process,
-       tp_destroy
+       tp_destroy,
+       NULL, /* device_added */
+       NULL, /* device_removed */
 };
 
 static void
index 448496912fbfa9b047858896ac12a99b4b4e15ad..638493fbb549368ed96f9de788d6e2b50234828b 100644 (file)
@@ -621,7 +621,9 @@ evdev_calibration_get_default_matrix(struct libinput_device *libinput_device,
 
 struct evdev_dispatch_interface fallback_interface = {
        fallback_process,
-       fallback_destroy
+       fallback_destroy,
+       NULL, /* device_added */
+       NULL, /* device_removed */
 };
 
 static uint32_t
@@ -968,6 +970,26 @@ evdev_configure_device(struct evdev_device *device)
        return 0;
 }
 
+static void
+evdev_notify_added_device(struct evdev_device *device)
+{
+       struct libinput_device *dev;
+
+       list_for_each(dev, &device->base.seat->devices_list, link) {
+               struct evdev_device *d = (struct evdev_device*)dev;
+               if (dev == &device->base)
+                       continue;
+
+               if (d->dispatch->interface->device_added)
+                       d->dispatch->interface->device_added(d, device);
+
+               if (device->dispatch->interface->device_added)
+                       device->dispatch->interface->device_added(device, d);
+       }
+
+       notify_added_device(&device->base);
+}
+
 struct evdev_device *
 evdev_device_create(struct libinput_seat *seat,
                    const char *devnode,
@@ -1042,7 +1064,7 @@ evdev_device_create(struct libinput_seat *seat,
                goto err;
 
        list_insert(seat->devices_list.prev, &device->base.link);
-       notify_added_device(&device->base);
+       evdev_notify_added_device(device);
 
        return device;
 
@@ -1341,6 +1363,17 @@ evdev_device_resume(struct evdev_device *device)
 void
 evdev_device_remove(struct evdev_device *device)
 {
+       struct libinput_device *dev;
+
+       list_for_each(dev, &device->base.seat->devices_list, link) {
+               struct evdev_device *d = (struct evdev_device*)dev;;
+               if (dev == &device->base)
+                       continue;
+
+               if (d->dispatch->interface->device_removed)
+                       d->dispatch->interface->device_removed(d, device);
+       }
+
        evdev_device_suspend(device);
 
        /* A device may be removed while suspended. Free the syspath to
index bdd4a4e5af7792b0913564ad8135121ef89e8f73..74053c5d4219778ef8f729dbddebeb664594e998 100644 (file)
@@ -120,6 +120,14 @@ struct evdev_dispatch_interface {
 
        /* Destroy an event dispatch handler and free all its resources. */
        void (*destroy)(struct evdev_dispatch *dispatch);
+
+       /* A new device was added */
+       void (*device_added)(struct evdev_device *device,
+                            struct evdev_device *added_device);
+
+       /* A device was removed */
+       void (*device_removed)(struct evdev_device *device,
+                              struct evdev_device *removed_device);
 };
 
 struct evdev_dispatch {