[PATCH v2 libinput] Restore capability events

Peter Hutterer peter.hutterer at who-t.net
Tue Jan 27 15:45:31 PST 2015


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 <peter.hutterer at who-t.net>
---
Changes to v1:
- rename device_register_capability to device_notify_capability_added, same
  for removed
- add/split out evdev_device_notify_capability_removed from
  evdev_device_suspend (instead of the previous boolean flag)
- rename evdev_register_device_capabilities to
  evdev_device_notify_capability_added

 src/evdev.c            |  36 +++++++++++++
 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 ++
 12 files changed, 317 insertions(+), 60 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 24d30e0..f4b7f85 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1559,6 +1559,23 @@ out:
 	return rc;
 }
 
+static void
+evdev_device_notify_capability_added(struct evdev_device *device)
+{
+	if (device->seat_caps & EVDEV_DEVICE_POINTER) {
+		device_notify_capability_added(&device->base,
+					       LIBINPUT_DEVICE_CAP_POINTER);
+	}
+	if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) {
+		device_notify_capability_added(&device->base,
+					       LIBINPUT_DEVICE_CAP_KEYBOARD);
+	}
+	if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
+		device_notify_capability_added(&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_device_notify_capability_added(device);
 
 	return device;
 
@@ -2082,6 +2100,23 @@ evdev_device_resume(struct evdev_device *device)
 	return 0;
 }
 
+static void
+evdev_device_notify_capability_removed(struct evdev_device *device)
+{
+	if (device->seat_caps & EVDEV_DEVICE_POINTER) {
+		device_notify_capability_removed(&device->base,
+						 LIBINPUT_DEVICE_CAP_POINTER);
+	}
+	if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) {
+		device_notify_capability_removed(&device->base,
+						 LIBINPUT_DEVICE_CAP_KEYBOARD);
+	}
+	if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
+		device_notify_capability_removed(&device->base,
+						 LIBINPUT_DEVICE_CAP_TOUCH);
+	}
+}
+
 void
 evdev_device_remove(struct evdev_device *device)
 {
@@ -2096,6 +2131,7 @@ evdev_device_remove(struct evdev_device *device)
 			d->dispatch->interface->device_removed(d, device);
 	}
 
+	evdev_device_notify_capability_removed(device);
 	evdev_device_suspend(device);
 
 	if (device->dispatch->interface->remove)
diff --git a/src/libinput-private.h b/src/libinput-private.h
index b938ed0..b9a877b 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_notify_capability_added(struct libinput_device *device,
+			       enum libinput_device_capability capability);
+
+void
+device_notify_capability_removed(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..39c4ef6 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_notify_capability_added(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_notify_capability_removed(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 70dd854..10a5fa3 100644
--- a/tools/event-gui.c
+++ b/tools/event-gui.c
@@ -443,6 +443,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



More information about the wayland-devel mailing list