Introduce seat wide button and key count API
authorJonas Ådahl <jadahl@gmail.com>
Tue, 1 Apr 2014 19:57:45 +0000 (21:57 +0200)
committerJonas Ådahl <jadahl@gmail.com>
Tue, 22 Apr 2014 22:07:40 +0000 (00:07 +0200)
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@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev.c
src/libinput-private.h
src/libinput.c
src/libinput.h
tools/event-debug.c

index 2e0d1d73b9cd4b6a26b950a67f6ab48654d53d79..08ee0b26c0a88cc336ec57f9c095e05ed3c33822 100644 (file)
@@ -258,6 +258,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);
@@ -284,6 +287,11 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
                break;
 
        default:
+               /* Only let KEY_* codes pass through. */
+               if (!(e->code <= KEY_MICMUTE ||
+                     (e->code >= KEY_OK && e->code <= KEY_LIGHTS_TOGGLE)))
+                       break;
+
                keyboard_notify_key(
                        &device->base,
                        time,
index f778f6eadd9a8d108baf9f5004765f20c1ec03dc..dc1d5905f0dc672dd1d26c644e1203b1037b7268 100644 (file)
@@ -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,8 @@ struct libinput_seat {
        char *logical_name;
 
        uint32_t slot_map;
+
+       uint32_t button_count[KEY_CNT];
 };
 
 struct libinput_device {
index 1e31be30a0b433990d67249d9e1f3e5035e05c0c..6b7e8b88e6fc2e951b42331176d78e997deb8817 100644 (file)
@@ -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;
@@ -281,6 +283,13 @@ libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event)
        return event->state;
 }
 
+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)
 {
@@ -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,48 @@ 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->button_count[key];
+       case LIBINPUT_KEYBOARD_KEY_STATE_RELEASED:
+               /* We might not have received the first PRESSED event. */
+               if (seat->button_count[key] == 0)
+                       return 0;
+
+               return --seat->button_count[key];
+       }
+
+       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];
+       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];
+       }
+
+       return 0;
+}
+
 static void
 init_event_base(struct libinput_event *event,
                struct libinput_device *device,
@@ -735,15 +793,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 +866,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,
index 810a66c22b9fe30f9c87e2d1b1ac6b7f1b3cb13f..fb297e3a7a2d1dfc7bfe6cda3a7cd558eb907fb8 100644 (file)
@@ -370,6 +370,22 @@ libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event);
 struct libinput_event *
 libinput_event_keyboard_get_base_event(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
  *
@@ -529,6 +545,22 @@ libinput_event_pointer_get_button(struct libinput_event_pointer *event);
 enum libinput_pointer_button_state
 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
  *
index c0a08a7a7d5dd372b9ab40a0fb88c55514507a50..6cb57ff2a8868c97ffdb6cedd070577938cbcf6c 100644 (file)
@@ -287,9 +287,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, seat count: %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