Introduce seat wide button and key count API

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>
This commit is contained in:
Jonas Ådahl 2014-04-01 21:57:45 +02:00
parent dbbc091123
commit 604f22eb79
5 changed files with 115 additions and 2 deletions

View 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,

View 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 {

View 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,

View 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
*

View 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