[PATCH libinput 7/9] Introduce seat wide button and key count API

Jonas Ådahl jadahl at gmail.com
Wed Apr 9 12:02:14 PDT 2014


Compositors will need to keep provide virtual devices of supported
generic device types (pointer, keyboard, touch etc). Events from each
device capable of a certain device type abstraction should be combined
as if it was only one device.

For key and button events this means counting presses of every key or
button. With this patch, libinput provides two new API for doing just
this; libinput_event_pointer_get_seat_button_count() and
libinput_event_keyboard_get_seat_key_count().

With these functions, a compositor can sort out what key or button events
that should be ignored for a virtual device. This could for example
look like:

event = libinput_get_event(libinput);
switch (libinput_event_get_type(event)) {
...
case LIBINPUT_EVENT_POINTER_BUTTON:
	device = libinput_event_get_device(event);
	seat = libinput_event_get_seat(device);
	pevent = libinput_event_get_pointer_event(event);

	if (libinput_event_pointer_get_button_state(pevent) &&
	    libinput_event_pointer_get_seat_button_count(pevent) == 1)
		notify_pointer_button_press(seat);
	else if (libinput_event_pointer_get_button_state(pevent) &&
		 libinput_event_pointer_get_seat_button_count(pevent) == 0)
		notify_pointer_button_release(seat);
	break;
...
}

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
 src/evdev.c            |  3 +++
 src/libinput-private.h |  5 ++++
 src/libinput.c         | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/libinput.h         | 32 ++++++++++++++++++++++
 tools/event-debug.c    |  5 ++--
 5 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index b6aaf57..4020496 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -252,6 +252,9 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
 	if (e->value == 2)
 		return;
 
+	if (e->code > KEY_MAX)
+		return;
+
 	if (e->code == BTN_TOUCH) {
 		if (!device->is_mt)
 			evdev_process_touch_button(device, time, e->value);
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 21627b0..39d6445 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -23,6 +23,8 @@
 #ifndef LIBINPUT_PRIVATE_H
 #define LIBINPUT_PRIVATE_H
 
+#include <linux/input.h>
+
 #include "libinput.h"
 #include "libinput-util.h"
 
@@ -63,6 +65,9 @@ struct libinput_seat {
 	char *logical_name;
 
 	uint32_t slot_map;
+
+	uint32_t button_count[KEY_CNT];
+	uint32_t key_count[KEY_CNT];
 };
 
 struct libinput_device {
diff --git a/src/libinput.c b/src/libinput.c
index 182c401..799b309 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -54,6 +54,7 @@ struct libinput_event_keyboard {
 	struct libinput_event base;
 	uint32_t time;
 	uint32_t key;
+	uint32_t seat_key_count;
 	enum libinput_keyboard_key_state state;
 };
 
@@ -63,6 +64,7 @@ struct libinput_event_pointer {
 	li_fixed_t x;
 	li_fixed_t y;
 	uint32_t button;
+	uint32_t seat_button_count;
 	enum libinput_pointer_button_state state;
 	enum libinput_pointer_axis axis;
 	li_fixed_t value;
@@ -282,6 +284,13 @@ libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event)
 }
 
 LIBINPUT_EXPORT uint32_t
+libinput_event_keyboard_get_seat_key_count(
+	struct libinput_event_keyboard *event)
+{
+	return event->seat_key_count;
+}
+
+LIBINPUT_EXPORT uint32_t
 libinput_event_pointer_get_time(struct libinput_event_pointer *event)
 {
 	return event->time;
@@ -345,6 +354,13 @@ libinput_event_pointer_get_button_state(struct libinput_event_pointer *event)
 	return event->state;
 }
 
+LIBINPUT_EXPORT uint32_t
+libinput_event_pointer_get_seat_button_count(
+	struct libinput_event_pointer *event)
+{
+	return event->seat_button_count;
+}
+
 LIBINPUT_EXPORT enum libinput_pointer_axis
 libinput_event_pointer_get_axis(struct libinput_event_pointer *event)
 {
@@ -672,6 +688,52 @@ libinput_dispatch(struct libinput *libinput)
 	return 0;
 }
 
+static uint32_t
+update_seat_key_count(struct libinput_seat *seat,
+		      int32_t key,
+		      enum libinput_keyboard_key_state state)
+{
+	assert(key >= 0 && key <= KEY_MAX);
+
+	switch (state) {
+	case LIBINPUT_KEYBOARD_KEY_STATE_PRESSED:
+		return ++seat->key_count[key];
+		break;
+	case LIBINPUT_KEYBOARD_KEY_STATE_RELEASED:
+		/* We might not have received the first PRESSED event. */
+		if (seat->key_count[key] == 0)
+			return 0;
+
+		return --seat->key_count[key];
+		break;
+	}
+
+	return 0;
+}
+
+static uint32_t
+update_seat_button_count(struct libinput_seat *seat,
+			 int32_t button,
+			 enum libinput_pointer_button_state state)
+{
+	assert(button >= 0 && button <= KEY_MAX);
+
+	switch (state) {
+	case LIBINPUT_POINTER_BUTTON_STATE_PRESSED:
+		return ++seat->button_count[button];
+		break;
+	case LIBINPUT_POINTER_BUTTON_STATE_RELEASED:
+		/* We might not have received the first PRESSED event. */
+		if (seat->button_count[button] == 0)
+			return 0;
+
+		return --seat->button_count[button];
+		break;
+	}
+
+	return 0;
+}
+
 static void
 init_event_base(struct libinput_event *event,
 		struct libinput_device *device,
@@ -735,15 +797,19 @@ keyboard_notify_key(struct libinput_device *device,
 		    enum libinput_keyboard_key_state state)
 {
 	struct libinput_event_keyboard *key_event;
+	uint32_t seat_key_count;
 
 	key_event = zalloc(sizeof *key_event);
 	if (!key_event)
 		return;
 
+	seat_key_count = update_seat_key_count(device->seat, key, state);
+
 	*key_event = (struct libinput_event_keyboard) {
 		.time = time,
 		.key = key,
 		.state = state,
+		.seat_key_count = seat_key_count,
 	};
 
 	post_device_event(device,
@@ -804,15 +870,21 @@ pointer_notify_button(struct libinput_device *device,
 		      enum libinput_pointer_button_state state)
 {
 	struct libinput_event_pointer *button_event;
+	int32_t seat_button_count;
 
 	button_event = zalloc(sizeof *button_event);
 	if (!button_event)
 		return;
 
+	seat_button_count = update_seat_button_count(device->seat,
+						     button,
+						     state);
+
 	*button_event = (struct libinput_event_pointer) {
 		.time = time,
 		.button = button,
 		.state = state,
+		.seat_button_count = seat_button_count,
 	};
 
 	post_device_event(device,
diff --git a/src/libinput.h b/src/libinput.h
index 5599a6a..e21cd28 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -345,6 +345,22 @@ enum libinput_keyboard_key_state
 libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event);
 
 /**
+ * @ingroup event_keyboard
+ *
+ * For the key of a LIBINPUT_EVENT_KEYBOARD_KEY event, return the total number
+ * of keys pressed on all devices on the associated seat after the event was
+ * triggered.
+ *
+ " @note It is an application bug to call this function for events other than
+ * LIBINPUT_EVENT_KEYBOARD_KEY. For other events, this function returns 0.
+ *
+ * @return the seat wide pressed key count for the key of this event
+ */
+uint32_t
+libinput_event_keyboard_get_seat_key_count(
+	struct libinput_event_keyboard *event);
+
+/**
  * @defgroup event_pointer Pointer events
  *
  * Pointer events reflect motion, button and scroll events, as well as
@@ -506,6 +522,22 @@ libinput_event_pointer_get_button_state(struct libinput_event_pointer *event);
 /**
  * @ingroup event_pointer
  *
+ * For the button of a LIBINPUT_EVENT_POINTER_BUTTON event, return the total
+ * number of buttons pressed on all devices on the associated seat after the
+ * the event was triggered.
+ *
+ " @note It is an application bug to call this function for events other than
+ * LIBINPUT_EVENT_POINTER_BUTTON. For other events, this function returns 0.
+ *
+ * @return the seat wide pressed button count for the key of this event
+ */
+uint32_t
+libinput_event_pointer_get_seat_button_count(
+	struct libinput_event_pointer *event);
+
+/**
+ * @ingroup event_pointer
+ *
  * Return the axis that triggered this event.
  * For pointer events that are not of type LIBINPUT_EVENT_POINTER_AXIS,
  * this function returns 0.
diff --git a/tools/event-debug.c b/tools/event-debug.c
index 12a2df8..e466e09 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -281,9 +281,10 @@ print_button_event(struct libinput_event *ev)
 	print_event_time(libinput_event_pointer_get_time(p));
 
 	state = libinput_event_pointer_get_button_state(p);
-	printf("%3d %s\n",
+	printf("%3d %s (%u)\n",
 	       libinput_event_pointer_get_button(p),
-	       state == LIBINPUT_POINTER_BUTTON_STATE_PRESSED ? "pressed" : "released");
+	       state == LIBINPUT_POINTER_BUTTON_STATE_PRESSED ? "pressed" : "released",
+	       libinput_event_pointer_get_seat_button_count(p));
 }
 
 static void
-- 
1.8.3.2



More information about the wayland-devel mailing list