This reverts commit ab9260c5c70b95779f39069b31646ff5cf8970ad, with a bunch of
changes on top.

First change is different naming, the events are now DEVICE_CAPABILITY_ADDED
and DEVICE_CAPABILITY_REMOVED for consistency with the device events.

The behaviour of capability events is as previously, the event sequence is
always: DEVICE_ADDED
        DEVICE_CAPABILITY_ADDED
        DEVICE_CAPABILITY_ADDED
        ...
        DEVICE_CAPABILITY_REMOVED
        DEVICE_CAPABILITY_REMOVED
        DEVICE_REMOVED

Disabling a device does not send capablity events, but suspending a libinput
context does (since it removes the device).

Signed-off-by: Peter Hutterer <[email protected]>
---
 src/evdev-mt-touchpad.c |   2 +-
 src/evdev.c             |  40 +++++++++++++--
 src/evdev.h             |   3 +-
 src/libinput-private.h  |   8 +++
 src/libinput.c          |  82 +++++++++++++++++++++++++++++
 src/libinput.h          |  44 ++++++++++++++++
 src/libinput.sym        |   3 ++
 test/keyboard.c         |   3 ++
 test/litest.c           |   6 +++
 test/path.c             | 133 +++++++++++++++++++++++++++++++-----------------
 test/pointer.c          |   3 ++
 test/udev.c             |   8 ++-
 tools/event-debug.c     |  48 +++++++++++++----
 tools/event-gui.c       |   3 ++
 14 files changed, 321 insertions(+), 65 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 5221be6..ddb99f4 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -940,7 +940,7 @@ tp_suspend(struct tp_dispatch *tp, struct evdev_device 
*device)
                /* Enlarge topbutton area while suspended */
                tp_init_top_softbuttons(tp, device, 1.5);
        } else {
-               evdev_device_suspend(device);
+               evdev_device_suspend(device, false);
        }
 }
 
diff --git a/src/evdev.c b/src/evdev.c
index 24d30e0..77a4e4a 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -785,7 +785,7 @@ evdev_sendevents_set_mode(struct libinput_device *device,
                evdev_device_resume(evdev);
                break;
        case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
-               evdev_device_suspend(evdev);
+               evdev_device_suspend(evdev, false);
                break;
        default: /* no support for combined modes yet */
                return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
@@ -1559,6 +1559,23 @@ out:
        return rc;
 }
 
+static void
+evdev_register_device_capabilities(struct evdev_device *device)
+{
+       if (device->seat_caps & EVDEV_DEVICE_POINTER) {
+               device_register_capability(&device->base,
+                                          LIBINPUT_DEVICE_CAP_POINTER);
+       }
+       if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) {
+               device_register_capability(&device->base,
+                                          LIBINPUT_DEVICE_CAP_KEYBOARD);
+       }
+       if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
+               device_register_capability(&device->base,
+                                          LIBINPUT_DEVICE_CAP_TOUCH);
+       }
+}
+
 struct evdev_device *
 evdev_device_create(struct libinput_seat *seat,
                    struct udev_device *udev_device)
@@ -1643,6 +1660,7 @@ evdev_device_create(struct libinput_seat *seat,
 
        evdev_tag_device(device);
        evdev_notify_added_device(device);
+       evdev_register_device_capabilities(device);
 
        return device;
 
@@ -1995,10 +2013,26 @@ evdev_notify_resumed_device(struct evdev_device *device)
 }
 
 int
-evdev_device_suspend(struct evdev_device *device)
+evdev_device_suspend(struct evdev_device *device,
+                    bool want_capability_events)
 {
        evdev_notify_suspended_device(device);
 
+       if (want_capability_events) {
+               if (device->seat_caps & EVDEV_DEVICE_POINTER) {
+                       device_unregister_capability(&device->base,
+                                            LIBINPUT_DEVICE_CAP_POINTER);
+               }
+               if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) {
+                       device_unregister_capability(&device->base,
+                                            LIBINPUT_DEVICE_CAP_KEYBOARD);
+               }
+               if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
+                       device_unregister_capability(&device->base,
+                                            LIBINPUT_DEVICE_CAP_TOUCH);
+               }
+       }
+
        if (device->source) {
                libinput_remove_source(device->base.seat->libinput,
                                       device->source);
@@ -2096,7 +2130,7 @@ evdev_device_remove(struct evdev_device *device)
                        d->dispatch->interface->device_removed(d, device);
        }
 
-       evdev_device_suspend(device);
+       evdev_device_suspend(device, true);
 
        if (device->dispatch->interface->remove)
                device->dispatch->interface->remove(device->dispatch);
diff --git a/src/evdev.h b/src/evdev.h
index 0f2c5ac..22a83b2 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -272,7 +272,8 @@ evdev_device_transform_y(struct evdev_device *device,
                         double y,
                         uint32_t height);
 int
-evdev_device_suspend(struct evdev_device *device);
+evdev_device_suspend(struct evdev_device *device,
+                    bool want_capability_events);
 
 int
 evdev_device_resume(struct evdev_device *device);
diff --git a/src/libinput-private.h b/src/libinput-private.h
index b938ed0..a1c0691 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -259,6 +259,14 @@ void
 notify_removed_device(struct libinput_device *device);
 
 void
+device_register_capability(struct libinput_device *device,
+                          enum libinput_device_capability capability);
+
+void
+device_unregister_capability(struct libinput_device *device,
+                            enum libinput_device_capability capability);
+
+void
 keyboard_notify_key(struct libinput_device *device,
                    uint64_t time,
                    uint32_t key,
diff --git a/src/libinput.c b/src/libinput.c
index 951698a..62ef5e6 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -46,6 +46,11 @@ struct libinput_event_device_notify {
        struct libinput_event base;
 };
 
+struct libinput_event_device_capability {
+       struct libinput_event base;
+       enum libinput_device_capability capability;
+};
+
 struct libinput_event_keyboard {
        struct libinput_event base;
        uint32_t time;
@@ -170,6 +175,8 @@ libinput_event_get_pointer_event(struct libinput_event 
*event)
                abort(); /* not used as actual event type */
        case LIBINPUT_EVENT_DEVICE_ADDED:
        case LIBINPUT_EVENT_DEVICE_REMOVED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
        case LIBINPUT_EVENT_KEYBOARD_KEY:
                break;
        case LIBINPUT_EVENT_POINTER_MOTION:
@@ -196,6 +203,8 @@ libinput_event_get_keyboard_event(struct libinput_event 
*event)
                abort(); /* not used as actual event type */
        case LIBINPUT_EVENT_DEVICE_ADDED:
        case LIBINPUT_EVENT_DEVICE_REMOVED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
                break;
        case LIBINPUT_EVENT_KEYBOARD_KEY:
                return (struct libinput_event_keyboard *) event;
@@ -222,6 +231,8 @@ libinput_event_get_touch_event(struct libinput_event *event)
                abort(); /* not used as actual event type */
        case LIBINPUT_EVENT_DEVICE_ADDED:
        case LIBINPUT_EVENT_DEVICE_REMOVED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
        case LIBINPUT_EVENT_KEYBOARD_KEY:
        case LIBINPUT_EVENT_POINTER_MOTION:
        case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
@@ -248,6 +259,8 @@ libinput_event_get_device_notify_event(struct 
libinput_event *event)
        case LIBINPUT_EVENT_DEVICE_ADDED:
        case LIBINPUT_EVENT_DEVICE_REMOVED:
                return (struct libinput_event_device_notify *) event;
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
        case LIBINPUT_EVENT_KEYBOARD_KEY:
        case LIBINPUT_EVENT_POINTER_MOTION:
        case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
@@ -264,6 +277,41 @@ libinput_event_get_device_notify_event(struct 
libinput_event *event)
        return NULL;
 }
 
+LIBINPUT_EXPORT struct libinput_event_device_capability *
+libinput_event_get_device_capability_event(struct libinput_event *event)
+{
+       switch (event->type) {
+       case LIBINPUT_EVENT_NONE:
+               abort(); /* not used as actual event type */
+       case LIBINPUT_EVENT_DEVICE_ADDED:
+       case LIBINPUT_EVENT_DEVICE_REMOVED:
+               break;
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
+               return (struct libinput_event_device_capability *) event;
+       case LIBINPUT_EVENT_KEYBOARD_KEY:
+       case LIBINPUT_EVENT_POINTER_MOTION:
+       case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+       case LIBINPUT_EVENT_POINTER_BUTTON:
+       case LIBINPUT_EVENT_POINTER_AXIS:
+       case LIBINPUT_EVENT_TOUCH_DOWN:
+       case LIBINPUT_EVENT_TOUCH_UP:
+       case LIBINPUT_EVENT_TOUCH_MOTION:
+       case LIBINPUT_EVENT_TOUCH_CANCEL:
+       case LIBINPUT_EVENT_TOUCH_FRAME:
+               break;
+       }
+
+       return NULL;
+}
+
+LIBINPUT_EXPORT enum libinput_device_capability
+libinput_event_device_capability_get_capability(
+       struct libinput_event_device_capability *event)
+{
+       return event->capability;
+}
+
 LIBINPUT_EXPORT uint32_t
 libinput_event_keyboard_get_time(struct libinput_event_keyboard *event)
 {
@@ -932,6 +980,40 @@ notify_removed_device(struct libinput_device *device)
 }
 
 void
+device_register_capability(struct libinput_device *device,
+                          enum libinput_device_capability capability)
+{
+       struct libinput_event_device_capability *capability_event;
+
+       capability_event = malloc(sizeof *capability_event);
+
+       *capability_event = (struct libinput_event_device_capability) {
+               .capability = capability,
+       };
+
+       post_base_event(device,
+                       LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED,
+                       &capability_event->base);
+}
+
+void
+device_unregister_capability(struct libinput_device *device,
+                            enum libinput_device_capability capability)
+{
+       struct libinput_event_device_capability *capability_event;
+
+       capability_event = malloc(sizeof *capability_event);
+
+       *capability_event = (struct libinput_event_device_capability) {
+               .capability = capability,
+       };
+
+       post_base_event(device,
+                       LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED,
+                       &capability_event->base);
+}
+
+void
 keyboard_notify_key(struct libinput_device *device,
                    uint64_t time,
                    uint32_t key,
diff --git a/src/libinput.h b/src/libinput.h
index 7b7a2db..50bedc8 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -158,6 +158,9 @@ enum libinput_event_type {
         */
        LIBINPUT_EVENT_DEVICE_REMOVED,
 
+       LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED = 200,
+       LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED,
+
        LIBINPUT_EVENT_KEYBOARD_KEY = 300,
 
        LIBINPUT_EVENT_POINTER_MOTION = 400,
@@ -224,6 +227,15 @@ struct libinput_event;
 struct libinput_event_device_notify;
 
 /**
+ * @ingroup event
+ * @struct libinput_event_device_capability
+ *
+ * An event notifying the caller of a device capability being added or
+ * removed
+ */
+struct libinput_event_device_capability;
+
+/**
  * @ingroup event_keyboard
  * @struct libinput_event_keyboard
  *
@@ -370,6 +382,38 @@ struct libinput_event *
 libinput_event_device_notify_get_base_event(struct 
libinput_event_device_notify *event);
 
 /**
+ * @ingroup event
+ *
+ * Return the capability event that is this input event. If the event type
+ * does not match the capability event types, this function returns NULL.
+ *
+ * The inverse of this function is
+ * libinput_event_device_capability_get_base_event().
+ *
+ * @return A capability event, or NULL for other events
+ */
+struct libinput_event_device_capability *
+libinput_event_get_device_capability_event(struct libinput_event *event);
+
+/**
+ * @ingroup event
+ *
+ * @return The capability registered or unregistered from this device
+ */
+enum libinput_device_capability
+libinput_event_device_capability_get_capability(
+       struct libinput_event_device_capability *event);
+
+/**
+ * @ingroup event
+ *
+ * @return The generic libinput_event of this event
+ */
+struct libinput_event *
+libinput_event_device_capability_get_base_event(
+                       struct libinput_event_device_capability *event);
+
+/**
  * @defgroup event_keyboard Keyboard events
  *
  * Key events are generated when a key changes its logical state, usually by
diff --git a/src/libinput.sym b/src/libinput.sym
index 77fccb8..671930e 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -121,8 +121,11 @@ local:
 
 LIBINPUT_0.9.0 {
 global:
+       libinput_event_device_capability_get_capability;
+       libinput_event_device_capability_get_base_event;
        libinput_device_config_click_get_default_method;
        libinput_device_config_click_get_method;
        libinput_device_config_click_get_methods;
        libinput_device_config_click_set_method;
+       libinput_event_get_device_capability_event;
 } LIBINPUT_0.8.0;
diff --git a/test/keyboard.c b/test/keyboard.c
index 4563ce6..022edd4 100644
--- a/test/keyboard.c
+++ b/test/keyboard.c
@@ -261,6 +261,9 @@ START_TEST(keyboard_key_auto_release)
                if (type == LIBINPUT_EVENT_DEVICE_REMOVED) {
                        libinput_event_destroy(event);
                        break;
+               } else if (type == LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED) {
+                       libinput_event_destroy(event);
+                       continue;
                }
 
                ck_assert_int_eq(type, LIBINPUT_EVENT_KEYBOARD_KEY);
diff --git a/test/litest.c b/test/litest.c
index 643c168..92ed4ce 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -958,6 +958,12 @@ litest_event_type_str(struct libinput_event *event)
        case LIBINPUT_EVENT_DEVICE_REMOVED:
                str = "REMOVED";
                break;
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+               str = "CAPABILITY ADDED";
+               break;
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
+               str = "CAPABILITY REMOVED";
+               break;
        case LIBINPUT_EVENT_KEYBOARD_KEY:
                str = "KEY";
                break;
diff --git a/test/path.c b/test/path.c
index 243edd7..1dbae46 100644
--- a/test/path.c
+++ b/test/path.c
@@ -211,6 +211,10 @@ START_TEST(path_seat_change)
 
        libinput_dispatch(li);
 
+       litest_drain_typed_events(li,
+                                 LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED,
+                                 -1);
+
        event = libinput_get_event(li);
        ck_assert(event != NULL);
 
@@ -354,14 +358,14 @@ START_TEST(path_device_sysname)
        libinput_dispatch(dev->libinput);
 
        while ((ev = libinput_get_event(dev->libinput))) {
-               if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED)
-                       continue;
-
-               device = libinput_event_get_device(ev);
-               sysname = libinput_device_get_sysname(device);
-               ck_assert(sysname != NULL && strlen(sysname) > 1);
-               ck_assert(strchr(sysname, '/') == NULL);
-               ck_assert_int_eq(strncmp(sysname, "event", 5), 0);
+               if (libinput_event_get_type(ev) ==
+                           LIBINPUT_EVENT_DEVICE_ADDED) {
+                       device = libinput_event_get_device(ev);
+                       sysname = libinput_device_get_sysname(device);
+                       ck_assert(sysname != NULL && strlen(sysname) > 1);
+                       ck_assert(strchr(sysname, '/') == NULL);
+                       ck_assert_int_eq(strncmp(sysname, "event", 5), 0);
+               }
 
                libinput_event_destroy(ev);
        }
@@ -537,7 +541,7 @@ START_TEST(path_add_device_suspend_resume)
        struct libinput_event *event;
        struct libevdev_uinput *uinput1, *uinput2;
        int rc;
-       int nevents;
+       int ndevices;
        void *userdata = &rc;
 
        uinput1 = litest_create_uinput_device("test device", NULL,
@@ -564,44 +568,53 @@ START_TEST(path_add_device_suspend_resume)
 
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+               if (type != LIBINPUT_EVENT_DEVICE_ADDED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED)
+                       ck_assert_msg(type, "Expected device/capability added");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_ADDED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        libinput_suspend(li);
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_REMOVED);
+               if (type != LIBINPUT_EVENT_DEVICE_REMOVED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED)
+                       ck_assert_msg(type, "Expected device/capability 
removed");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_REMOVED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        libinput_resume(li);
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+               if (type != LIBINPUT_EVENT_DEVICE_ADDED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED)
+                       ck_assert_msg(type, "Expected device/capability added");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_ADDED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        libevdev_uinput_destroy(uinput1);
        libevdev_uinput_destroy(uinput2);
@@ -619,7 +632,7 @@ START_TEST(path_add_device_suspend_resume_fail)
        struct libinput_event *event;
        struct libevdev_uinput *uinput1, *uinput2;
        int rc;
-       int nevents;
+       int ndevices;
        void *userdata = &rc;
 
        uinput1 = litest_create_uinput_device("test device", NULL,
@@ -647,30 +660,36 @@ START_TEST(path_add_device_suspend_resume_fail)
 
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+               if (type != LIBINPUT_EVENT_DEVICE_ADDED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED)
+                       ck_assert_msg(type, "Expected device/capability added");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_ADDED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        libinput_suspend(li);
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_REMOVED);
+               if (type != LIBINPUT_EVENT_DEVICE_REMOVED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED)
+                       ck_assert_msg(type, "Expected device/capability 
removed");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_REMOVED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        /* now drop one of the devices */
        libevdev_uinput_destroy(uinput1);
@@ -679,20 +698,27 @@ START_TEST(path_add_device_suspend_resume_fail)
 
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
                /* We expect one device being added, second one fails,
                 * causing a removed event for the first one */
-               if (type != LIBINPUT_EVENT_DEVICE_ADDED &&
-                   type != LIBINPUT_EVENT_DEVICE_REMOVED)
+               switch(type) {
+               case LIBINPUT_EVENT_DEVICE_ADDED:
+               case LIBINPUT_EVENT_DEVICE_REMOVED:
+                       ndevices++;
+                       break;
+               case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+               case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
+                       break;
+               default:
                        ck_abort();
+               }
                libinput_event_destroy(event);
-               nevents++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        libevdev_uinput_destroy(uinput2);
        libinput_unref(li);
@@ -709,7 +735,7 @@ START_TEST(path_add_device_suspend_resume_remove_device)
        struct libinput_event *event;
        struct libevdev_uinput *uinput1, *uinput2;
        int rc;
-       int nevents;
+       int ndevices;
        void *userdata = &rc;
 
        uinput1 = litest_create_uinput_device("test device", NULL,
@@ -737,30 +763,36 @@ START_TEST(path_add_device_suspend_resume_remove_device)
        libinput_device_ref(device);
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+               if (type != LIBINPUT_EVENT_DEVICE_ADDED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED)
+                       ck_assert_msg(type, "Expected device/capability added");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_ADDED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        libinput_suspend(li);
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_REMOVED);
+               if (type != LIBINPUT_EVENT_DEVICE_REMOVED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED)
+                       ck_assert_msg(type, "Expected device/capability 
removed");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_REMOVED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 2);
+       ck_assert_int_eq(ndevices, 2);
 
        /* now drop and remove one of the devices */
        libevdev_uinput_destroy(uinput2);
@@ -772,16 +804,19 @@ START_TEST(path_add_device_suspend_resume_remove_device)
 
        libinput_dispatch(li);
 
-       nevents = 0;
+       ndevices = 0;
        while ((event = libinput_get_event(li))) {
                enum libinput_event_type type;
                type = libinput_event_get_type(event);
-               ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+               if (type != LIBINPUT_EVENT_DEVICE_ADDED &&
+                   type != LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED)
+                       ck_assert_msg(type, "Expected device/capability added");
                libinput_event_destroy(event);
-               nevents++;
+               if (type == LIBINPUT_EVENT_DEVICE_ADDED)
+                       ndevices++;
        }
 
-       ck_assert_int_eq(nevents, 1);
+       ck_assert_int_eq(ndevices, 1);
 
        libevdev_uinput_destroy(uinput1);
        libinput_unref(li);
@@ -889,10 +924,12 @@ main(int argc, char **argv)
        litest_add_no_device("path:suspend", path_add_device_suspend_resume);
        litest_add_no_device("path:suspend", 
path_add_device_suspend_resume_fail);
        litest_add_no_device("path:suspend", 
path_add_device_suspend_resume_remove_device);
+
        litest_add_for_device("path:seat", path_added_seat, 
LITEST_SYNAPTICS_CLICKPAD);
        litest_add_for_device("path:seat", path_seat_change, 
LITEST_SYNAPTICS_CLICKPAD);
        litest_add("path:device events", path_added_device, LITEST_ANY, 
LITEST_ANY);
        litest_add("path:device events", path_device_sysname, LITEST_ANY, 
LITEST_ANY);
+
        litest_add_for_device("path:device events", path_add_device, 
LITEST_SYNAPTICS_CLICKPAD);
        litest_add_no_device("path:device events", path_add_invalid_path);
        litest_add_for_device("path:device events", path_remove_device, 
LITEST_SYNAPTICS_CLICKPAD);
diff --git a/test/pointer.c b/test/pointer.c
index 45e0d57..c3dedb2 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -313,6 +313,9 @@ START_TEST(pointer_button_auto_release)
                if (type == LIBINPUT_EVENT_DEVICE_REMOVED) {
                        libinput_event_destroy(event);
                        break;
+               } else if (type == LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED) {
+                       libinput_event_destroy(event);
+                       continue;
                }
 
                ck_assert_int_eq(type, LIBINPUT_EVENT_POINTER_BUTTON);
diff --git a/test/udev.c b/test/udev.c
index c351bed..44a12c2 100644
--- a/test/udev.c
+++ b/test/udev.c
@@ -241,6 +241,10 @@ START_TEST(udev_change_seat)
 
        libinput_dispatch(li);
 
+       litest_drain_typed_events(li,
+                                 LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED,
+                                 -1);
+
        event = libinput_get_event(li);
        ck_assert_int_eq(libinput_event_get_type(event),
                         LIBINPUT_EVENT_DEVICE_REMOVED);
@@ -411,8 +415,10 @@ START_TEST(udev_device_sysname)
        libinput_dispatch(li);
 
        while ((ev = libinput_get_event(li))) {
-               if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED)
+               if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED) 
{
+                       libinput_event_destroy(ev);
                        continue;
+               }
 
                device = libinput_event_get_device(ev);
                sysname = libinput_device_get_sysname(device);
diff --git a/tools/event-debug.c b/tools/event-debug.c
index 297e47d..48f7a62 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -76,6 +76,12 @@ print_event_header(struct libinput_event *ev)
        case LIBINPUT_EVENT_DEVICE_REMOVED:
                type = "DEVICE_REMOVED";
                break;
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+               type = "CAPABILITY_ADDED";
+               break;
+       case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
+               type = "CAPABILITY_REMOVED";
+               break;
        case LIBINPUT_EVENT_KEYBOARD_KEY:
                type = "KEYBOARD_KEY";
                break;
@@ -130,17 +136,6 @@ print_device_notify(struct libinput_event *ev)
               libinput_seat_get_physical_name(seat),
               libinput_seat_get_logical_name(seat));
 
-       printf(" cap:");
-       if (libinput_device_has_capability(dev,
-                                          LIBINPUT_DEVICE_CAP_KEYBOARD))
-               printf("k");
-       if (libinput_device_has_capability(dev,
-                                          LIBINPUT_DEVICE_CAP_POINTER))
-               printf("p");
-       if (libinput_device_has_capability(dev,
-                                          LIBINPUT_DEVICE_CAP_TOUCH))
-               printf("t");
-
        if (libinput_device_get_size(dev, &w, &h) == 0)
                printf("\tsize %.2f/%.2fmm", w, h);
 
@@ -169,6 +164,33 @@ print_device_notify(struct libinput_event *ev)
 }
 
 static void
+print_device_capability(struct libinput_event *ev)
+{
+       struct libinput_event_device_capability *c =
+               libinput_event_get_device_capability_event(ev);
+       const char *cap, *mode;
+
+       switch (libinput_event_device_capability_get_capability(c)) {
+       case LIBINPUT_DEVICE_CAP_KEYBOARD:
+               cap = "keyboard";
+               break;
+       case LIBINPUT_DEVICE_CAP_POINTER:
+               cap = "pointer";
+               break;
+       case LIBINPUT_DEVICE_CAP_TOUCH:
+               cap = "touch";
+               break;
+       }
+
+       if (libinput_event_get_type(ev) == 
LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED)
+               mode = "added";
+       else
+               mode = "removed";
+
+       printf(" capability %s: %s\n", mode, cap);
+}
+
+static void
 print_key_event(struct libinput_event *ev)
 {
        struct libinput_event_keyboard *k = 
libinput_event_get_keyboard_event(ev);
@@ -285,6 +307,10 @@ handle_and_print_events(struct libinput *li)
                        tools_device_apply_config(libinput_event_get_device(ev),
                                                  &options);
                        break;
+               case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+               case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
+                       print_device_capability(ev);
+                       break;
                case LIBINPUT_EVENT_KEYBOARD_KEY:
                        print_key_event(ev);
                        break;
diff --git a/tools/event-gui.c b/tools/event-gui.c
index 4f9d7e6..924f332 100644
--- a/tools/event-gui.c
+++ b/tools/event-gui.c
@@ -441,6 +441,9 @@ handle_event_libinput(GIOChannel *source, GIOCondition 
condition, gpointer data)
                case LIBINPUT_EVENT_DEVICE_REMOVED:
                        handle_event_device_notify(ev);
                        break;
+               case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+               case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
+                       break;
                case LIBINPUT_EVENT_POINTER_MOTION:
                        handle_event_motion(ev, w);
                        break;
-- 
2.1.0

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to