[RFC libinput] Import buttonset interface

Peter Hutterer peter.hutterer at who-t.net
Fri Apr 22 03:51:22 UTC 2016


On Fri, Apr 22, 2016 at 12:00:43AM +0530, PrasannaKumar Muralidharan wrote:
> From: PrasannaKumar Muralidharan <prasannatsmkumar at gmail.com>

fwiw, it's very frowned upon to take someone else's patch, rebase it and
then send it on as your own when it has very little changes. Please keep
original authorship while it makes sense and add the author as co-author
where substantial changes have been made.

> Import buttonset interface code from
> https://github.com/whot/libinput/tree/wip/buttonbox-interface.
> 
> There is no user for buttonset interface as of now. I have taken the
> buttonset interface code and removed code related to wacom tablet.
> Please review the changes. Once this is reviewed will add dial
> input support, add test and send another patch.

tbh, I'm not quite sure what to review here though, without a backend
implementation this is quite theoretical. I'm assuming you just want a
quick review to make sure nothing obvious got lost in the rebase?
If so, yes, looks ok, thanks.

There are a couple of questions that arose from the
wacom tablet button switch, specifically:
* what use do the linux/input.h button codes have in the buttonset
  interface? We will run similar issues with the evdev button code ranges as
  we did with the pad, where the button code is meaningless.
* the various axes are nice to have, but without a user I'm hesitant to
  merge them - we'll need to know how they could be used first
* ring and strip are absolute, they are wacom-only axes and until we get a
  device that needs either, we should leave them out.
* the seat button count should be removed, it doesn't make sense for a 
  buttonset device
* get_(x|y)* does not need an axis argument, I struggle to think of a device
  that has two x or y axes on the same event node.

Other than that I still think that the general approach with numbered axes
and axis types makes sense.
 
> This change is compile tested.

That's not a confidence-inspiring statement... :)

Cheers,
   Peter

> ---
>  src/evdev.c            |  74 ++++++-
>  src/evdev.h            |  33 +++
>  src/libinput-private.h |  31 +++
>  src/libinput.c         | 482 ++++++++++++++++++++++++++++++++++++++++++
>  src/libinput.h         | 563 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 1181 insertions(+), 2 deletions(-)
> 
> diff --git a/src/evdev.c b/src/evdev.c
> index afc4710..cab28ff 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -67,6 +67,7 @@ enum evdev_device_udev_tags {
>          EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7),
>          EVDEV_UDEV_TAG_TABLET_PAD = (1 << 8),
>          EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9),
> +        EVDEV_UDEV_TAG_BUTTONSET = (1 << 10),
>  };
>  
>  struct evdev_udev_tag_match {
> @@ -86,6 +87,7 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = {
>  	{"ID_INPUT_JOYSTICK",		EVDEV_UDEV_TAG_JOYSTICK},
>  	{"ID_INPUT_ACCELEROMETER",	EVDEV_UDEV_TAG_ACCELEROMETER},
>  	{"ID_INPUT_POINTINGSTICK",	EVDEV_UDEV_TAG_POINTINGSTICK},
> +	{"ID_INPUT_TABLET_BUTTONSET",	EVDEV_UDEV_TAG_BUTTONSET},
>  
>  	/* sentinel value */
>  	{ 0 },
> @@ -318,6 +320,26 @@ evdev_device_transform_y(struct evdev_device *device,
>  	return scale_axis(device->abs.absinfo_y, y, height);
>  }
>  
> +double
> +evdev_device_transform_x_mm(struct evdev_device *device,
> +			    double mm,
> +			    uint32_t width)
> +{
> +	mm *= device->abs.absinfo_x->resolution;
> +
> +	return evdev_device_transform_x(device, mm, width);
> +}
> +
> +double
> +evdev_device_transform_y_mm(struct evdev_device *device,
> +			    double mm,
> +			    uint32_t height)
> +{
> +	mm *= device->abs.absinfo_y->resolution;
> +
> +	return evdev_device_transform_y(device, mm, height);
> +}
> +
>  static inline void
>  normalize_delta(struct evdev_device *device,
>  		const struct device_coords *delta,
> @@ -1028,6 +1050,9 @@ struct evdev_dispatch_interface fallback_interface = {
>  	NULL, /* device_suspended */
>  	NULL, /* device_resumed */
>  	NULL, /* post_added */
> +	NULL, /* buttonset_to_phys */
> +	NULL, /* buttonset_get_num_axes */
> +	NULL, /* buttonset_get_axis_type */
>  };
>  
>  static uint32_t
> @@ -2086,7 +2111,8 @@ evdev_configure_device(struct evdev_device *device)
>  		 udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK ? " Pointingstick" : "",
>  		 udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "",
>  		 udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "",
> -		 udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : "");
> +		 udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : "",
> +		 udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : "");
>  
>  	if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) {
>  		log_info(libinput,
> @@ -2158,6 +2184,17 @@ evdev_configure_device(struct evdev_device *device)
>  		return device->dispatch == NULL ? -1 : 0;
>  	}
>  
> +#if 0
> +	if (udev_tags & EVDEV_UDEV_TAG_BUTTONSET) {
> +		device->dispatch = evdev_buttonset_create(device);
> +		device->seat_caps |= EVDEV_DEVICE_BUTTONSET;
> +		log_info(libinput,
> +			 "input device '%s', %s is a buttonset\n",
> +			 device->devname, devnode);
> +		return device->dispatch == NULL ? -1 : 0;
> +	}
> +#endif
> +
>  	if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
>  		device->dispatch = evdev_mt_touchpad_create(device);
>  		log_info(libinput,
> @@ -2580,6 +2617,8 @@ evdev_device_has_capability(struct evdev_device *device,
>  		return !!(device->seat_caps & EVDEV_DEVICE_TABLET);
>  	case LIBINPUT_DEVICE_CAP_TABLET_PAD:
>  		return !!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD);
> +	case LIBINPUT_DEVICE_CAP_BUTTONSET:
> +		return !!(device->seat_caps & EVDEV_DEVICE_BUTTONSET);
>  	default:
>  		return 0;
>  	}
> @@ -2623,6 +2662,39 @@ evdev_device_has_key(struct evdev_device *device, uint32_t code)
>  	return libevdev_has_event_code(device->evdev, EV_KEY, code);
>  }
>  
> +int
> +evdev_device_buttonset_has_button(struct evdev_device *device,
> +				  uint32_t code)
> +{
> +	if (!(device->seat_caps & EVDEV_DEVICE_BUTTONSET))
> +		return -1;
> +
> +	return libevdev_has_event_code(device->evdev, EV_KEY, code);
> +}
> +
> +unsigned int
> +evdev_device_buttonset_get_num_axes(struct evdev_device *device)
> +{
> +	struct evdev_dispatch *dispatch = device->dispatch;
> +
> +	if (!(device->seat_caps & EVDEV_DEVICE_BUTTONSET))
> +		return 0;
> +
> +	return dispatch->interface->buttonset_get_num_axes(device);
> +}
> +
> +enum libinput_buttonset_axis_type
> +evdev_device_buttonset_get_axis_type(struct evdev_device *device,
> +				     unsigned int axis)
> +{
> +	struct evdev_dispatch *dispatch = device->dispatch;
> +
> +	if (!(device->seat_caps & EVDEV_DEVICE_BUTTONSET))
> +		return 0;
> +
> +	return dispatch->interface->buttonset_get_axis_type(device, axis);
> +}
> +
>  static inline bool
>  evdev_is_scrolling(const struct evdev_device *device,
>  		   enum libinput_pointer_axis axis)
> diff --git a/src/evdev.h b/src/evdev.h
> index db6d83f..14f4eab 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -63,6 +63,7 @@ enum evdev_device_seat_capability {
>  	EVDEV_DEVICE_TABLET = (1 << 3),
>  	EVDEV_DEVICE_TABLET_PAD = (1 << 4),
>  	EVDEV_DEVICE_GESTURE = (1 << 5),
> +	EVDEV_DEVICE_BUTTONSET = (1 << 6),
>  };
>  
>  enum evdev_device_tags {
> @@ -282,6 +283,14 @@ struct evdev_dispatch_interface {
>  	 * was sent */
>  	void (*post_added)(struct evdev_device *device,
>  			   struct evdev_dispatch *dispatch);
> +
> +	/* Return the number of axes on the buttonset device */
> +	unsigned int (*buttonset_get_num_axes)(struct evdev_device *device);
> +
> +	/* Return the axis type of the given axes on the buttonset device */
> +	enum libinput_buttonset_axis_type (*buttonset_get_axis_type)(
> +					     struct evdev_device *device,
> +					     unsigned int axis);
>  };
>  
>  struct evdev_dispatch {
> @@ -326,6 +335,9 @@ evdev_tablet_create(struct evdev_device *device);
>  struct evdev_dispatch *
>  evdev_tablet_pad_create(struct evdev_device *device);
>  
> +struct evdev_dispatch *
> +evdev_buttonset_create(struct evdev_device *device);
> +
>  void
>  evdev_tag_touchpad(struct evdev_device *device,
>  		   struct udev_device *udev_device);
> @@ -385,6 +397,16 @@ evdev_device_tablet_pad_get_num_rings(struct evdev_device *device);
>  int
>  evdev_device_tablet_pad_get_num_strips(struct evdev_device *device);
>  
> +int
> +evdev_device_buttonset_has_button(struct evdev_device *device,
> +				  uint32_t code);
> +
> +enum libinput_buttonset_axis_type
> +evdev_device_buttonset_get_axis_type(struct evdev_device *device,
> +				     unsigned int axis);
> +unsigned int
> +evdev_device_buttonset_get_num_axes(struct evdev_device *device);
> +
>  double
>  evdev_device_transform_x(struct evdev_device *device,
>  			 double x,
> @@ -394,6 +416,17 @@ double
>  evdev_device_transform_y(struct evdev_device *device,
>  			 double y,
>  			 uint32_t height);
> +
> +double
> +evdev_device_transform_x_mm(struct evdev_device *device,
> +			    double mm,
> +			    uint32_t width);
> +
> +double
> +evdev_device_transform_y_mm(struct evdev_device *device,
> +			    double mm,
> +			    uint32_t height);
> +
>  int
>  evdev_device_suspend(struct evdev_device *device);
>  
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 539e69a..7fe065e 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -33,6 +33,8 @@
>  #include "libinput.h"
>  #include "libinput-util.h"
>  
> +#define LIBINPUT_BUTTONSET_MAX_NUM_AXES 32
> +
>  struct libinput_source;
>  
>  /* A coordinate pair in device coordinates */
> @@ -311,6 +313,20 @@ struct libinput_tablet_tool {
>  	bool has_pressure_offset;
>  };
>  
> +struct libinput_buttonset_axis {
> +	enum libinput_buttonset_axis_type type;
> +	enum libinput_buttonset_axis_source source;
> +	union {
> +		double mm;
> +		double normalized;
> +		double delta;
> +		double degrees;
> +		double position;
> +
> +		double any;
> +	} value;
> +};
> +
>  struct libinput_event {
>  	enum libinput_event_type type;
>  	struct libinput_device *device;
> @@ -562,6 +578,21 @@ tablet_pad_notify_strip(struct libinput_device *device,
>  			double value,
>  			enum libinput_tablet_pad_strip_axis_source source);
>  
> +void
> +buttonset_notify_axis(struct libinput_device *device,
> +		      uint32_t time,
> +		      unsigned char *changed_axes,
> +		      struct libinput_buttonset_axis *axes,
> +		      size_t naxes);
> +
> +void
> +buttonset_notify_button(struct libinput_device *device,
> +			uint32_t time,
> +			struct libinput_buttonset_axis *axes,
> +			size_t naxes,
> +			int32_t button,
> +			enum libinput_button_state state);
> +
>  static inline uint64_t
>  libinput_now(struct libinput *libinput)
>  {
> diff --git a/src/libinput.c b/src/libinput.c
> index bcd0dcd..0cff1ad 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -42,6 +42,10 @@
>  	if (!check_event_type(li_, __func__, type_, __VA_ARGS__, -1)) \
>  		return retval_; \
>  
> +#define require_buttonset_axis(dev_, axis_, type_, retval_) \
> +	if (!check_buttonset_axis_type(dev_, __func__, axis_, type_)) \
> +		return retval_;
> +
>  static inline bool
>  check_event_type(struct libinput *libinput,
>  		 const char *function_name,
> @@ -73,6 +77,32 @@ check_event_type(struct libinput *libinput,
>  	return rc;
>  }
>  
> +static inline bool
> +check_buttonset_axis_type(struct libinput_device *device,
> +			  const char *function_name,
> +			  unsigned int axis,
> +			  enum libinput_buttonset_axis_type type_wanted)
> +{
> +	enum libinput_buttonset_axis_type type;
> +
> +	if (axis >= libinput_device_buttonset_get_num_axes(device)) {
> +		log_bug_client(device->seat->libinput,
> +			       "Invalid axis number %d in %s()\n",
> +			       axis, function_name);
> +		return false;
> +	}
> +
> +	type = libinput_device_buttonset_get_axis_type(device, axis);
> +	if (type != type_wanted) {
> +		log_bug_client(device->seat->libinput,
> +			       "Invalid axis type %d (need %d for %s())\n",
> +			       type, type_wanted, function_name);
> +		return false;
> +	} else {
> +		return true;
> +	}
> +}
> +
>  struct libinput_source {
>  	libinput_source_dispatch_t dispatch;
>  	void *user_data;
> @@ -155,6 +185,16 @@ struct libinput_event_tablet_pad {
>  	} strip;
>  };
>  
> +struct libinput_event_buttonset {
> +	struct libinput_event base;
> +	uint32_t button;
> +	enum libinput_button_state state;
> +	uint32_t seat_button_count;
> +	uint32_t time;
> +	struct libinput_buttonset_axis axes[LIBINPUT_BUTTONSET_MAX_NUM_AXES];
> +	unsigned char changed_axes[NCHARS(LIBINPUT_BUTTONSET_MAX_NUM_AXES)];
> +};
> +
>  static void
>  libinput_default_log_func(struct libinput *libinput,
>  			  enum libinput_log_priority priority,
> @@ -360,6 +400,19 @@ libinput_event_get_device_notify_event(struct libinput_event *event)
>  	return (struct libinput_event_device_notify *) event;
>  }
>  
> +
> +LIBINPUT_EXPORT struct libinput_event_buttonset *
> +libinput_event_get_buttonset_event(struct libinput_event *event)
> +{
> +	require_event_type(libinput_event_get_context(event),
> +			   event->type,
> +			   NULL,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON);
> +
> +	return (struct libinput_event_buttonset *) event;
> +}
> +
>  LIBINPUT_EXPORT uint32_t
>  libinput_event_keyboard_get_time(struct libinput_event_keyboard *event)
>  {
> @@ -1503,6 +1556,326 @@ libinput_tablet_tool_unref(struct libinput_tablet_tool *tool)
>  	return NULL;
>  }
>  
> +LIBINPUT_EXPORT uint32_t
> +libinput_event_buttonset_get_time(struct libinput_event_buttonset *event)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON);
> +
> +	return us2ms(event->time);
> +}
> +
> +LIBINPUT_EXPORT uint64_t
> +libinput_event_buttonset_get_time_usec(struct libinput_event_buttonset *event)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON);
> +
> +	return event->time;
> +}
> +
> +LIBINPUT_EXPORT uint32_t
> +libinput_event_buttonset_get_button(struct libinput_event_buttonset *event)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON);
> +
> +	return event->button;
> +}
> +
> +LIBINPUT_EXPORT enum libinput_button_state
> +libinput_event_buttonset_get_button_state(struct libinput_event_buttonset *event)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON);
> +
> +	return event->state;
> +}
> +
> +LIBINPUT_EXPORT uint32_t
> +libinput_event_buttonset_get_seat_button_count(struct libinput_event_buttonset *event)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON);
> +
> +	return event->seat_button_count;
> +}
> +
> +LIBINPUT_EXPORT int
> +libinput_event_buttonset_axis_has_changed(struct libinput_event_buttonset *event,
> +					  unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +
> +	return (NCHARS(axis) <= sizeof(event->changed_axes)) ?
> +		bit_is_set(event->changed_axes, axis) : 0;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_x(struct libinput_event_buttonset *event,
> +			       unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +			       axis,
> +			       LIBINPUT_BUTTONSET_AXIS_X,
> +			       0.0);
> +
> +	return event->axes[axis].value.mm;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_x_transformed(struct libinput_event_buttonset *event,
> +					   unsigned int axis,
> +					   uint32_t width)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_X,
> +				    0.0);
> +
> +	return evdev_device_transform_x_mm(device,
> +					   event->axes[axis].value.mm,
> +					   width);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_y(struct libinput_event_buttonset *event,
> +			       unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_Y,
> +				    0.0);
> +	return event->axes[axis].value.mm;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_y_transformed(struct libinput_event_buttonset *event,
> +					   unsigned int axis,
> +					   uint32_t height)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_Y,
> +				    0.0);
> +
> +	return evdev_device_transform_y_mm(device,
> +					   event->axes[axis].value.mm,
> +					   height);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_z(struct libinput_event_buttonset *event,
> +			       unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_Z,
> +				    0.0);
> +
> +	return event->axes[axis].value.mm;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_dx(struct libinput_event_buttonset *event,
> +				unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_REL_X,
> +				    0.0);
> +
> +	return event->axes[axis].value.delta;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_dy(struct libinput_event_buttonset *event,
> +				unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_REL_Y,
> +				    0.0);
> +
> +	return event->axes[axis].value.delta;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_dz(struct libinput_event_buttonset *event,
> +				unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_REL_Z,
> +				    0.0);
> +
> +	return event->axes[axis].value.delta;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_rotation_x(struct libinput_event_buttonset *event,
> +					unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_ROTATION_X,
> +				    0.0);
> +
> +	return event->axes[axis].value.degrees;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_rotation_y(struct libinput_event_buttonset *event,
> +					unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_ROTATION_Y,
> +				    0.0);
> +
> +	return event->axes[axis].value.degrees;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_rotation_z(struct libinput_event_buttonset *event,
> +					unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_ROTATION_Z,
> +				    0.0);
> +
> +	return event->axes[axis].value.degrees;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_ring_position(struct libinput_event_buttonset *event,
> +					   unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_RING,
> +				    0.0);
> +
> +	return event->axes[axis].value.position;
> +}
> +
> +LIBINPUT_EXPORT enum libinput_buttonset_axis_source
> +libinput_event_buttonset_get_ring_source(struct libinput_event_buttonset *event,
> +					 unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +				    axis,
> +				    LIBINPUT_BUTTONSET_AXIS_RING,
> +				    0.0);
> +
> +	return event->axes[axis].source;
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_buttonset_get_strip_position(struct libinput_event_buttonset *event,
> +					    unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +			       axis,
> +			       LIBINPUT_BUTTONSET_AXIS_STRIP,
> +			       0.0);
> +
> +	return event->axes[axis].value.position;
> +}
> +
> +LIBINPUT_EXPORT enum libinput_buttonset_axis_source
> +libinput_event_buttonset_get_strip_source(struct libinput_event_buttonset *event,
> +					 unsigned int axis)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0.0,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	require_buttonset_axis(event->base.device,
> +			       axis,
> +			       LIBINPUT_BUTTONSET_AXIS_STRIP,
> +			       0.0);
> +	return event->axes[axis].source;
> +}
> +
>  struct libinput_source *
>  libinput_add_fd(struct libinput *libinput,
>  		int fd,
> @@ -1989,6 +2362,9 @@ device_has_cap(struct libinput_device *device,
>  	case LIBINPUT_DEVICE_CAP_TABLET_PAD:
>  		capability = "CAP_TABLET_PAD";
>  		break;
> +	case LIBINPUT_DEVICE_CAP_BUTTONSET:
> +		capability = "CAP_BUTTONSET";
> +		break;
>  	}
>  
>  	log_bug_libinput(device->seat->libinput,
> @@ -2452,6 +2828,75 @@ tablet_pad_notify_strip(struct libinput_device *device,
>  			  &strip_event->base);
>  }
>  
> +void
> +buttonset_notify_axis(struct libinput_device *device,
> +		      uint32_t time,
> +		      unsigned char *changed_axes,
> +		      struct libinput_buttonset_axis *axes,
> +		      size_t naxes)
> +{
> +	struct libinput_event_buttonset *axis_event;
> +
> +	if (naxes > ARRAY_LENGTH(axis_event->axes)) {
> +		log_bug_libinput(device->seat->libinput,
> +				 "%s: Invalid axis number %zd\n",
> +				 __func__,
> +				 naxes);
> +		naxes = ARRAY_LENGTH(axis_event->axes);
> +	}
> +
> +	axis_event = zalloc(sizeof *axis_event);
> +	if (!axis_event)
> +		return;
> +
> +	*axis_event = (struct libinput_event_buttonset) {
> +		.time = time,
> +	};
> +
> +	memcpy(axis_event->changed_axes,
> +	       changed_axes,
> +	       sizeof(axis_event->changed_axes));
> +	memcpy(axis_event->axes, axes, sizeof(axis_event->axes));
> +
> +	post_device_event(device,
> +			  time,
> +			  LIBINPUT_EVENT_BUTTONSET_AXIS,
> +			  &axis_event->base);
> +}
> +
> +void
> +buttonset_notify_button(struct libinput_device *device,
> +			uint32_t time,
> +			struct libinput_buttonset_axis *axes,
> +			size_t naxes,
> +			int32_t button,
> +			enum libinput_button_state state)
> +{
> +	struct libinput_event_buttonset *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_buttonset) {
> +		.time = time,
> +		.button = button,
> +		.state = state,
> +		.seat_button_count = seat_button_count,
> +	};
> +	memcpy(button_event->axes, axes, sizeof(button_event->axes));
> +
> +	post_device_event(device,
> +			  time,
> +			  LIBINPUT_EVENT_BUTTONSET_BUTTON,
> +			  &button_event->base);
> +}
> +
>  static void
>  gesture_notify(struct libinput_device *device,
>  	       uint64_t time,
> @@ -2566,6 +3011,8 @@ event_type_to_str(enum libinput_event_type type)
>  	CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN);
>  	CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE);
>  	CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
> +	CASE_RETURN_STRING(LIBINPUT_EVENT_BUTTONSET_AXIS);
> +	CASE_RETURN_STRING(LIBINPUT_EVENT_BUTTONSET_BUTTON);
>  	case LIBINPUT_EVENT_NONE:
>  		abort();
>  	}
> @@ -2809,6 +3256,29 @@ libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
>  	return evdev_device_tablet_pad_get_num_strips((struct evdev_device *)device);
>  }
>  
> +LIBINPUT_EXPORT int
> +libinput_device_buttonset_has_button(struct libinput_device *device, uint32_t code)
> +{
> +	return evdev_device_buttonset_has_button((struct evdev_device *)device,
> +						 code);
> +}
> +
> +LIBINPUT_EXPORT enum libinput_buttonset_axis_type
> +libinput_device_buttonset_get_axis_type(struct libinput_device *device,
> +					unsigned int axis)
> +{
> +	return evdev_device_buttonset_get_axis_type(
> +					    (struct evdev_device *)device,
> +					    axis);
> +}
> +
> +LIBINPUT_EXPORT unsigned int
> +libinput_device_buttonset_get_num_axes(struct libinput_device *device)
> +{
> +	return evdev_device_buttonset_get_num_axes(
> +					   (struct evdev_device *)device);
> +}
> +
>  LIBINPUT_EXPORT struct libinput_event *
>  libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
>  {
> @@ -3008,6 +3478,18 @@ libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event
>  	return &event->base;
>  }
>  
> +LIBINPUT_EXPORT struct libinput_event *
> +libinput_event_buttonset_get_base_event(struct libinput_event_buttonset *event)
> +{
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   NULL,
> +			   LIBINPUT_EVENT_BUTTONSET_BUTTON,
> +			   LIBINPUT_EVENT_BUTTONSET_AXIS);
> +
> +	return &event->base;
> +}
> +
>  LIBINPUT_EXPORT struct libinput_device_group *
>  libinput_device_group_ref(struct libinput_device_group *group)
>  {
> diff --git a/src/libinput.h b/src/libinput.h
> index 97fd570..ac38072 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -61,6 +61,7 @@ enum libinput_device_capability {
>  	LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3,
>  	LIBINPUT_DEVICE_CAP_TABLET_PAD = 4,
>  	LIBINPUT_DEVICE_CAP_GESTURE = 5,
> +	LIBINPUT_DEVICE_CAP_BUTTONSET=6,
>  };
>  
>  /**
> @@ -169,6 +170,56 @@ enum libinput_tablet_pad_strip_axis_source {
>   * @ingroup device
>   * @struct libinput_tablet_tool
>   *
> + * Available axis types for a buttonset device. It must have the @ref
> + * LIBINPUT_DEVICE_CAP_BUTTONSET capability. A device may have more than one
> + * axis of the same type, e.g. a Wacom Cintiq 24HD has two ring axes.
> + */
> +enum libinput_buttonset_axis_type {
> +	LIBINPUT_BUTTONSET_AXIS_X = 1, /**< Absolute X axis */
> +	LIBINPUT_BUTTONSET_AXIS_Y, /**< Absolute Y axis */
> +	LIBINPUT_BUTTONSET_AXIS_Z, /**< Absolute Z axis */
> +	LIBINPUT_BUTTONSET_AXIS_REL_X, /**< Relative X axis */
> +	LIBINPUT_BUTTONSET_AXIS_REL_Y, /**< Relative Y axis */
> +	LIBINPUT_BUTTONSET_AXIS_REL_Z, /**< Relative Z axis */
> +	LIBINPUT_BUTTONSET_AXIS_ROTATION_X,
> +	LIBINPUT_BUTTONSET_AXIS_ROTATION_Y,
> +	LIBINPUT_BUTTONSET_AXIS_ROTATION_Z,
> +	/**
> +	 * A capacitative touch ring axis with absolute axis values, e.g.
> +	 * the ring on the Wacom Intuos4.
> +	 *
> +	 * This axis does not describe a rotary encoder like a dial.
> +	 */
> +	LIBINPUT_BUTTONSET_AXIS_RING,
> +	/**
> +	 * A capacitative touch strip axis with absolute axis values, e.g.
> +	 * the strip on the Wacom Intuos3.
> +	 *
> +	 * This axis does not describe a slider-like device.
> +	 */
> +	LIBINPUT_BUTTONSET_AXIS_STRIP,
> +};
> +
> +/**
> + * @ingroup device
> + *
> + * The source for a libinput_buttonset_axis event. See
> + * libinput_event_buttonset_get_axis_source() for details.
> + */
> +enum libinput_buttonset_axis_source {
> +	LIBINPUT_BUTTONSET_AXIS_SOURCE_UNKNOWN = 1,
> +	/**
> +	 * The event is caused by the movement of one or more fingers on a
> +	 * device.
> +	 */
> +	LIBINPUT_BUTTONSET_AXIS_SOURCE_FINGER,
> +};
> +
> +
> +/**
> + * @ingroup device
> + * @struct libinput_tablet_tool
> + *
>   * An object representing a tool being used by a device with the @ref
>   * LIBINPUT_DEVICE_CAP_TABLET_TOOL capability.
>   *
> @@ -395,7 +446,11 @@ enum libinput_event_type {
>  	 */
>  	LIBINPUT_EVENT_TABLET_PAD_STRIP,
>  
> -	LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
> +
> +	LIBINPUT_EVENT_BUTTONSET_AXIS = 800,
> +	LIBINPUT_EVENT_BUTTONSET_BUTTON,
> +
> +	LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 900,
>  	LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
>  	LIBINPUT_EVENT_GESTURE_SWIPE_END,
>  	LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
> @@ -512,6 +567,18 @@ struct libinput_event_tablet_tool;
>   */
>  struct libinput_event_tablet_pad;
>  
> +
> +/**
> + * @ingroup event_buttonset
> + * @struct libinput_event_buttonset
> + *
> + * Event representing a button press/release or axis update on device with
> + * the @ref LIBINPUT_DEVICE_CAP_BUTTONSET capability. Valid event types for
> + * this event are @ref LIBINPUT_EVENT_BUTTONSET_AXIS and @ref
> + * LIBINPUT_EVENT_BUTTONSET_BUTTON.
> + */
> +struct libinput_event_buttonset;
> +
>  /**
>   * @defgroup event Accessing and destruction of events
>   */
> @@ -663,6 +730,19 @@ libinput_event_get_device_notify_event(struct libinput_event *event);
>  /**
>   * @ingroup event
>   *
> + * Return the buttonset event that is this input event. If the event type
> + * does not match the buttonset event types, this function returns NULL.
> + *
> + * The inverse of this function is libinput_event_buttonset_get_base_event().
> + *
> + * @return A buttonset event, or NULL for other events
> + */
> +struct libinput_event_buttonset *
> +libinput_event_get_buttonset_event(struct libinput_event *event);
> +
> +/**
> + * @ingroup event
> + *
>   * @return The generic libinput_event of this event
>   */
>  struct libinput_event *
> @@ -2372,6 +2452,424 @@ uint64_t
>  libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event);
>  
>  /**
> + * @defgroup event_buttonset Events from button devices
> + *
> + * Events that come from button devices. Such devices provide one or more
> + * custom buttons (other than left, middle, right) and usually do not
> + * control the pointer. Axes other than x/y axes may be present on the
> + * device.
> + *
> + * Note that buttonset devices may have x/y axes. It is up to the caller to
> + * decide whether those devices should control the pointer.
> + * While libinput provides some information about the device and a unified
> + * API to handle axes and events, the caller is expected to gather
> + * additional information from external sources. For example, for
> + * information on the button layout and other behaviors on Wacom tablet
> + * pads, the caller should use libwacom.
> + */
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * @return The generic libinput_event of this event
> + */
> +struct libinput_event *
> +libinput_event_buttonset_get_base_event(struct libinput_event_buttonset *event);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * @return The event time for this event
> + */
> +uint32_t
> +libinput_event_buttonset_get_time(struct libinput_event_buttonset *event);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * @return The event time for this event
> + */
> +uint64_t
> +libinput_event_buttonset_get_time_usec(struct libinput_event_buttonset *event);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Checks if an axis was updated in this event or return 0 otherwise.
> + * For buttonset events that are not of type @ref LIBINPUT_EVENT_BUTTONSET_AXIS,
> + * this function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_BUTTONSET_AXIS.
> + *
> + * @param event The libinput buttonset event
> + * @param axis The axis to check for updates
> + * @return 1 if the axis was updated or 0 otherwise
> + */
> +int
> +libinput_event_buttonset_axis_has_changed(struct libinput_event_buttonset *event,
> +					  unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the x coordinate in mm. The definition of x follows the HID Usage
> + * Tables, the x coordinate is defined as "linear translation
> + * in the X direction. Report values should increase as the control’s
> + * position is moved from left to right."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * The axis must be of type @ref LIBINPUT_BUTTONSET_AXIS_X.
> + *
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_X
> + * @return The x coordinate in mm, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_X.
> + */
> +double
> +libinput_event_buttonset_get_x(struct libinput_event_buttonset *event,
> +			       unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Return the x coordinate of the buttonset event, transformed to
> + * screen coordinates. The axis must be of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_X.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_X
> + * @param width The screen width
> + * @return The x coordinate transformed to screen coordinates, or 0 if the
> + * axis is not of type @ref LIBINPUT_BUTTONSET_AXIS_X.
> + */
> +double
> +libinput_event_buttonset_get_x_transformed(struct libinput_event_buttonset *event,
> +					   unsigned int axis,
> +					   uint32_t width);
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the y coordinate in mm. The definition of y follows the HID Usage
> + * Tables, the y coordinate is defined as "linear translation
> + * in the Y direction. Report values should increase as the control’s
> + * position is moved from far to near."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * The axis must be of type @ref LIBINPUT_BUTTONSET_AXIS_Y.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_Y
> + * @return The y coordinate in mm, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_Y.
> + */
> +double
> +libinput_event_buttonset_get_y(struct libinput_event_buttonset *event,
> +			       unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Return the y coordinate of the buttonset event, transformed to
> + * screen coordinates. The axis must be of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_Y.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_Y
> + * @param height The screen height
> + * @return The x coordinate transformed to screen coordinates, or 0 if the
> + * axis is not of type @ref LIBINPUT_BUTTONSET_AXIS_Y.
> + */
> +double
> +libinput_event_buttonset_get_y_transformed(struct libinput_event_buttonset *event,
> +					   unsigned int axis,
> +					   uint32_t height);
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the z coordinate in mm. The definition of z follows the HID Usage
> + * Tables, the z coordinate is defined as "linear translation
> + * in the Z direction. Report values should increase as the control’s
> + * position is moved from high to low."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * The axis must be of type @ref LIBINPUT_BUTTONSET_AXIS_Z.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_Z
> + * @return The z coordinate in mm, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_Z.
> + */
> +double
> +libinput_event_buttonset_get_z(struct libinput_event_buttonset *event,
> +			       unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the delta coordinates for a relative x axis of type
> + * @ref LIBINPUT_BUTTONSET_AXIS_REL_X.
> + *
> + * The definition of x follows the HID Usage Tables, the x coordinate is
> + * defined as "linear translation in the X direction. Report values should
> + * increase as the control’s position is moved from left to right."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * The interpretation of a delta is device-specific. Buttonset devices are
> + * not usually supposed to control the cursor position, a caller should not
> + * assume that delta coordinates are directly applicable to pointer
> + * movement.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_REL_X
> + * @return The delta x coordinate, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_REL_X.
> + */
> +double
> +libinput_event_buttonset_get_dx(struct libinput_event_buttonset *event,
> +				unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the delta coordinates for a relative x axis of type
> + * @ref LIBINPUT_BUTTONSET_AXIS_REL_Y.
> + *
> + * The definition of y follows the HID Usage Tables, the y coordinate is
> + * defined as "linear translation in the Y direction. Report values should
> + * increase as the control’s position is moved from near to far."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * The interpretation of a delta is device-specific. Buttonset devices are
> + * not usually supposed to control the cursor position, a caller should not
> + * assume that delta coordinates are directly applicable to pointer
> + * movement.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_REL_Y
> + * @return The delta y coordinate, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_REL_Y.
> + */
> +double
> +libinput_event_buttonset_get_dy(struct libinput_event_buttonset *event,
> +				unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the delta coordinates for a relative x axis of type
> + * @ref LIBINPUT_BUTTONSET_AXIS_REL_Z.
> + *
> + * The definition of z follows the HID Usage Tables, the z coordinate is
> + * defined as "linear translation in the Z direction. Report values should
> + * increase as the control’s position is moved from high to low."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_REL_Z
> + * @return The delta z coordinate, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_REL_Z.
> + */
> +double
> +libinput_event_buttonset_get_dz(struct libinput_event_buttonset *event,
> +				unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the rotational position in degrees off the logical neutral position
> + * in the current logical orientation for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_X.
> + *
> + * The definition of x rotation follows the HID Usage Tables, x rotation
> + * is defined as "rotation about the X axis. Angular position report values
> + * follow the righthand rule."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_X
> + * @return The rotational x value in degrees, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_X.
> + */
> +double
> +libinput_event_buttonset_get_rotation_x(struct libinput_event_buttonset *event,
> +					unsigned int axis);
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the rotational position in degrees off the logical neutral position
> + * in the current logical orientation for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_Y.
> + *
> + * The definition of y rotation follows the HID Usage Tables, the y rotation
> + * is defined as "rotation about the Y axis. Angular position report values
> + * follow the righthand rule."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_Y
> + * @return The rotational y value in degrees, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_Y.
> + */
> +double
> +libinput_event_buttonset_get_rotation_y(struct libinput_event_buttonset *event,
> +					unsigned int axis);
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the rotational position in degrees off the logical neutral position
> + * in the current logical orientation for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_Z.
> + *
> + * The definition of z rotation follows the HID Usage Tables, z rotation
> + * is defined as "rotation about the Z axis. Angular position report values
> + * follow the righthand rule."
> + * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_Z
> + * @return The rotational z value in degrees, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_ROTATION_Z.
> + */
> +double
> +libinput_event_buttonset_get_rotation_z(struct libinput_event_buttonset *event,
> +					unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the absolute position for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_RING in degrees clockwise in the
> + * device's current logical rotation.
> + *
> + * If the libinput_event_buttonset_get_ring_source() returns @ref
> + * LIBINPUT_BUTTONSET_AXIS_SOURCE_FINGER for this event and this axis,
> + * libinput will send an event with a value of -1 when the finger is
> + * lifted.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_RING
> + * @return The ring's position in degrees, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_RING.
> + */
> +double
> +libinput_event_buttonset_get_ring_position(struct libinput_event_buttonset *event,
> +					   unsigned int axis);
> +/**
> + * @ingroup event_buttonset
> + *
> + * Return the source for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_RING.
> + *
> + * If the source is @ref LIBINPUT_BUTTONSET_AXIS_SOURCE_FINGER, libinput
> + * guarantees that a sequence is terminated with an out-of-range value (see
> + * libinput_event_buttonset_get_ring_value() for details).
> + * A caller may use this information to decide on whether kinetic motion
> + * should be triggered on this event sequence.
> + *
> + * If the source is @ref LIBINPUT_BUTTONSET_AXIS_SOURCE_UNKNOWN, libinput
> + * does not send a terminating value to indicate release.
> + *
> + */
> +enum libinput_buttonset_axis_source
> +libinput_event_buttonset_get_ring_source(struct libinput_event_buttonset *event,
> +					 unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Get the absolute position for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_STRIP normalized to the axis range [0, 1], where
> + * 0 is the strip's top or left-most point in the device's current logical
> + * rotation.
> + *
> + * If the libinput_event_buttonset_get_strip_source() returns @ref
> + * LIBINPUT_BUTTONSET_AXIS_SOURCE_FINGER for this event and this axis,
> + * libinput will send an event with a value of -1 when the finger is
> + * lifted.
> + *
> + * @param event The event
> + * @param axis An index for an axis of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_STRIP
> + * @return The normalized position on the strip, or 0 if the axis is not of type @ref
> + * LIBINPUT_BUTTONSET_AXIS_STRIP.
> + */
> +double
> +libinput_event_buttonset_get_strip_position(struct libinput_event_buttonset *event,
> +					    unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Return the source for an axis of type @ref LIBINPUT_BUTTONSET_AXIS_STRIP.
> + *
> + * If the source is @ref LIBINPUT_BUTTONSET_AXIS_SOURCE_FINGER, libinput
> + * guarantees that a sequence is terminated with an out-of-range value (see
> + * libinput_event_buttonset_get_strip_value() for details).
> + * A caller may use this information to decide on whether kinetic motion
> + * should be triggered on this event sequence.
> + *
> + * If the source is @ref LIBINPUT_BUTTONSET_AXIS_SOURCE_UNKNOWN, libinput
> + * does not send a terminating value to indicate release.
> + */
> +enum libinput_buttonset_axis_source
> +libinput_event_buttonset_get_strip_source(struct libinput_event_buttonset *event,
> +					 unsigned int axis);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Return the button that triggered this event.
> + * For buttonset events that are not of type @ref LIBINPUT_EVENT_BUTTONSET_BUTTON, this
> + * function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_BUTTONSET_BUTTON.
> + *
> + * @param event The libinput buttonset event
> + * @return the button triggering this event
> + */
> +uint32_t
> +libinput_event_buttonset_get_button(struct libinput_event_buttonset *event);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * Return the button state of the event.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_BUTTONSET_BUTTON.
> + *
> + * @param event The libinput buttonset event
> + * @return the button state triggering this event
> + */
> +enum libinput_button_state
> +libinput_event_buttonset_get_button_state(struct libinput_event_buttonset *event);
> +
> +/**
> + * @ingroup event_buttonset
> + *
> + * For the button of a @ref LIBINPUT_EVENT_BUTTONSET_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
> + * @ref LIBINPUT_EVENT_BUTTONSET_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_buttonset_get_seat_button_count(struct libinput_event_buttonset *event);
> +
> +
> +/**
>   * @defgroup base Initialization and manipulation of libinput contexts
>   */
>  
> @@ -3239,10 +3737,73 @@ libinput_device_tablet_pad_get_num_rings(struct libinput_device *device);
>   *
>   * @see libinput_event_tablet_pad_get_strip_number
>   */
> +
>  int
>  libinput_device_tablet_pad_get_num_strips(struct libinput_device *device);
>  
>  /**
> + * Check if a @ref LIBINPUT_DEVICE_CAP_BUTTONSET device has a button with
> + * the given code (see linux/input.h).
> + *
> + * @param device A current input device
> + * @param code button code to check for
> + *
> + * @return 1 if the device supports this button code, 0 if it does not, -1
> + * on error.
> + *
> + * @see @ref buttonset_buttons
> + */
> +int
> +libinput_device_buttonset_has_button(struct libinput_device *device,
> +				     uint32_t code);
> +
> +/**
> + * @ingroup device
> + *
> + * Return the number of axes on this @ref LIBINPUT_DEVICE_CAP_BUTTONSET
> + * device.
> + *
> + * If the device does not have the @ref LIBINPUT_DEVICE_CAP_BUTTONSET
> + * capability, this function returns zero.
> + *
> + * @note: axis numbers are not stable, see @ref buttonset_axes for details.
> + *
> + * @note It is an application bug to call this function on a device
> + * without the @ref LIBINPUT_DEVICE_CAP_BUTTONSET capability.
> + *
> + * @param device A current input device
> + *
> + * @return The number of axes on this device or zero.
> + */
> +unsigned int
> +libinput_device_buttonset_get_num_axes(struct libinput_device *device);
> +
> +/**
> + * @ingroup device
> + *
> + * Return the axis type for the given axis on this @ref
> + * LIBINPUT_DEVICE_CAP_BUTTONSET device.
> + *
> + * If the device does not have the @ref LIBINPUT_DEVICE_CAP_BUTTONSET
> + * capability or the axis does not exist on this device, this function
> + * returns zero.
> + *
> + * @note It is an application bug to call this function on a device
> + * without the @ref LIBINPUT_DEVICE_CAP_BUTTONSET capability or for an axis
> + * that does not exist.
> + *
> + * @param device A current input device
> + * @param axis The axis to retrieve the type of
> + *
> + * @return The axis type for the given axis or 0 if the axis does not exist
> + *
> + * @see libinput_device_buttonset_get_num_axes
> + */
> +enum libinput_buttonset_axis_type
> +libinput_device_buttonset_get_axis_type(struct libinput_device *device,
> +					unsigned int axis);
> +
> +/**
>   * @ingroup device
>   *
>   * Increase the refcount of the device group. A device group will be freed
> -- 
> 2.5.0
> 


More information about the wayland-devel mailing list