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

Peter Hutterer peter.hutterer at who-t.net
Wed Apr 9 23:48:52 PDT 2014


On Thu, Apr 10, 2014 at 08:35:00AM +0200, Jonas Ådahl wrote:
> On Thu, Apr 10, 2014 at 04:07:34PM +1000, Peter Hutterer wrote:
> > On Wed, Apr 09, 2014 at 09:02:14PM +0200, Jonas Ådahl wrote:
> > > 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];
> > 
> > the ranges are mutually exclusive, we don't really need two arrays here.
> 
> This is in the seat, and libinput separates pointers from keyboards, so
> shouldn't they be counted separately because of that? Will a pointer
> never press a "key" and a keyboard never a "button"? If they would then
> the keyboards button count should not effect the pointers button count
> and vice versa.

are you suggesting we add keyboard_button or pointer_key events? because
that's a bridge we should burn when we have cross it, not before :)

Cheers,
   Peter

> 
> > 
> > >  };
> > >  
> > >  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 and break seems excessive ;)
> 
> Uhm, fixed locally.
> 
> > 
> > > +	}
> > > +
> > > +	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));
> > 
> > might as well make it easy to understand and have ", seat cound %u".
> 
> Sure, amended locally.
> 
> > 
> > Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net> though, the test too.
> 
> Thanks
> 
> > 
> > 
> > Cheers,
> >    Peter
> > 
> > >  }
> > >  
> > >  static void
> > > -- 
> > > 1.8.3.2
> > > 
> > > _______________________________________________
> > > wayland-devel mailing list
> > > wayland-devel at lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> > > 


More information about the wayland-devel mailing list