[PATCH libinput 1/6] Add the LIBINPUT_DEVICE_CAP_TABLET_PAD capability and matching interface

Peter Hutterer peter.hutterer at who-t.net
Wed Feb 10 06:17:30 UTC 2016


This interface handles the buttons on the physical tablet itself, including
the touch ring and the strip.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 doc/tablet-support.dox |  12 +-
 src/libinput-private.h |  18 +++
 src/libinput.c         | 276 +++++++++++++++++++++++++++++++++++++++++
 src/libinput.h         | 327 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/libinput.sym       |  20 +++
 test/litest.c          |   9 ++
 tools/event-debug.c    |  82 +++++++++++++
 tools/event-gui.c      |   4 +
 8 files changed, 745 insertions(+), 3 deletions(-)

diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
index ff4e460..427bf7b 100644
--- a/doc/tablet-support.dox
+++ b/doc/tablet-support.dox
@@ -8,7 +8,7 @@ Apple iPad.
 
 @image html tablet.svg "Illustration of a graphics tablet"
 
- at section tablet-tools Tablet buttons vs. tablet tools
+ at section tablet-tools Pad buttons vs. tablet tools
 
 Most tablets provide two types of devices. The pysical tablet often provides
 a number of buttons and a touch ring or strip. Interaction on the drawing
@@ -16,6 +16,12 @@ surface of the tablet requires a tool, usually in the shape of a stylus.
 The libinput interface exposed by devices with the @ref
 LIBINPUT_DEVICE_CAP_TABLET_TOOL applies only to events generated by tools.
 
+Buttons, rings or strips on the physical tablet hardware, the "pad" are
+exposed by devices with the @ref LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
+Such events do not require a tool to be in proximity. Note that both
+capabilities may exist on the same device, or it may be split across
+multiple devices.
+
 Touch events on the tablet integrated into a screen itself are exposed
 through the @ref LIBINPUT_DEVICE_CAP_TOUCH capability. Touch events on a
 standalone tablet are exposed through the @ref LIBINPUT_DEVICE_CAP_POINTER
@@ -24,7 +30,7 @@ node for the touch device, resulting in a separate libinput device.
 See libinput_device_get_device_group() for information on how to associate
 the touch part with other devices exposed by the same physical hardware.
 
- at section tablet-tip Tool tip events vs. button events
+ at section tablet-tip Tool tip events vs. tool button events
 
 The primary use of a tablet tool is to draw on the surface of the tablet.
 When the tool tip comes into contact with the surface, libinput sends an
@@ -112,6 +118,8 @@ tablets however extends further than the user may lift the mouse, i.e. the
 tool may not be lifted out of physical proximity. For such tools, libinput 
 provides software-emulated proximity. 
 
+Events from the pad do not require proximity, they may be sent any time.
+
 @section tablet-pressure-offset Pressure offset on worn-out tools
 
 When a tool is used for an extended period it can wear down physically. A
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 8d2492a..539e69a 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -544,6 +544,24 @@ tablet_notify_button(struct libinput_device *device,
 		     int32_t button,
 		     enum libinput_button_state state);
 
+void
+tablet_pad_notify_button(struct libinput_device *device,
+			 uint64_t time,
+			 int32_t button,
+			 enum libinput_button_state state);
+void
+tablet_pad_notify_ring(struct libinput_device *device,
+		       uint64_t time,
+		       unsigned int number,
+		       double value,
+		       enum libinput_tablet_pad_ring_axis_source source);
+void
+tablet_pad_notify_strip(struct libinput_device *device,
+			uint64_t time,
+			unsigned int number,
+			double value,
+			enum libinput_tablet_pad_strip_axis_source source);
+
 static inline uint64_t
 libinput_now(struct libinput *libinput)
 {
diff --git a/src/libinput.c b/src/libinput.c
index 3c78905..5f1cc1a 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -138,6 +138,24 @@ struct libinput_event_tablet_tool {
 	enum libinput_tablet_tool_tip_state tip_state;
 };
 
+struct libinput_event_tablet_pad {
+	struct libinput_event base;
+	uint32_t button;
+	enum libinput_button_state state;
+	uint32_t seat_button_count;
+	uint64_t time;
+	struct {
+		enum libinput_tablet_pad_ring_axis_source source;
+		double position;
+		int number;
+	} ring;
+	struct {
+		enum libinput_tablet_pad_strip_axis_source source;
+		double position;
+		int number;
+	} strip;
+};
+
 static void
 libinput_default_log_func(struct libinput *libinput,
 			  enum libinput_log_priority priority,
@@ -318,6 +336,19 @@ libinput_event_get_tablet_tool_event(struct libinput_event *event)
 	return (struct libinput_event_tablet_tool *) event;
 }
 
+LIBINPUT_EXPORT struct libinput_event_tablet_pad *
+libinput_event_get_tablet_pad_event(struct libinput_event *event)
+{
+	require_event_type(libinput_event_get_context(event),
+			   event->type,
+			   NULL,
+			   LIBINPUT_EVENT_TABLET_PAD_RING,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	return (struct libinput_event_tablet_pad *) event;
+}
+
 LIBINPUT_EXPORT struct libinput_event_device_notify *
 libinput_event_get_device_notify_event(struct libinput_event *event)
 {
@@ -1953,6 +1984,9 @@ device_has_cap(struct libinput_device *device,
 	case LIBINPUT_DEVICE_CAP_TABLET_TOOL:
 		capability = "CAP_TABLET_TOOL";
 		break;
+	case LIBINPUT_DEVICE_CAP_TABLET_PAD:
+		capability = "CAP_TABLET_PAD";
+		break;
 	}
 
 	log_bug_libinput(device->seat->libinput,
@@ -2340,6 +2374,88 @@ tablet_notify_button(struct libinput_device *device,
 			  &button_event->base);
 }
 
+void
+tablet_pad_notify_button(struct libinput_device *device,
+			 uint64_t time,
+			 int32_t button,
+			 enum libinput_button_state state)
+{
+	struct libinput_event_tablet_pad *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_tablet_pad) {
+		.time = time,
+		.button = button,
+		.state = state,
+		.seat_button_count = seat_button_count,
+	};
+
+	post_device_event(device,
+			  time,
+			  LIBINPUT_EVENT_TABLET_PAD_BUTTON,
+			  &button_event->base);
+}
+
+void
+tablet_pad_notify_ring(struct libinput_device *device,
+		       uint64_t time,
+		       unsigned int number,
+		       double value,
+		       enum libinput_tablet_pad_ring_axis_source source)
+{
+	struct libinput_event_tablet_pad *ring_event;
+
+	ring_event = zalloc(sizeof *ring_event);
+	if (!ring_event)
+		return;
+
+	*ring_event = (struct libinput_event_tablet_pad) {
+		.time = time,
+		.ring.number = number,
+		.ring.position = value,
+		.ring.source = source,
+	};
+
+	post_device_event(device,
+			  time,
+			  LIBINPUT_EVENT_TABLET_PAD_RING,
+			  &ring_event->base);
+}
+
+void
+tablet_pad_notify_strip(struct libinput_device *device,
+			uint64_t time,
+			unsigned int number,
+			double value,
+			enum libinput_tablet_pad_strip_axis_source source)
+{
+	struct libinput_event_tablet_pad *strip_event;
+
+	strip_event = zalloc(sizeof *strip_event);
+	if (!strip_event)
+		return;
+
+	*strip_event = (struct libinput_event_tablet_pad) {
+		.time = time,
+		.strip.number = number,
+		.strip.position = value,
+		.strip.source = source,
+	};
+
+	post_device_event(device,
+			  time,
+			  LIBINPUT_EVENT_TABLET_PAD_STRIP,
+			  &strip_event->base);
+}
+
 static void
 gesture_notify(struct libinput_device *device,
 	       uint64_t time,
@@ -2445,6 +2561,9 @@ event_type_to_str(enum libinput_event_type type)
 	CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
 	CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_TIP);
 	CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
+	CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+	CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
+	CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
 	CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
 	CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
 	CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
@@ -2676,6 +2795,25 @@ libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code)
 	return evdev_device_has_key((struct evdev_device *)device, code);
 }
 
+LIBINPUT_EXPORT int
+libinput_device_tablet_pad_has_button(struct libinput_device *device,
+				      uint32_t code)
+{
+	return 0;
+}
+
+LIBINPUT_EXPORT int
+libinput_device_tablet_pad_get_num_rings(struct libinput_device *device)
+{
+	return 0;
+}
+
+LIBINPUT_EXPORT int
+libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
+{
+	return 0;
+}
+
 LIBINPUT_EXPORT struct libinput_event *
 libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
 {
@@ -2748,6 +2886,144 @@ libinput_event_tablet_tool_get_base_event(struct libinput_event_tablet_tool *eve
 	return &event->base;
 }
 
+LIBINPUT_EXPORT double
+libinput_event_tablet_pad_get_ring_position(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0.0,
+			   LIBINPUT_EVENT_TABLET_PAD_RING);
+
+	return event->ring.position;
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_event_tablet_pad_get_ring_number(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0.0,
+			   LIBINPUT_EVENT_TABLET_PAD_RING);
+
+	return event->ring.number;
+}
+
+LIBINPUT_EXPORT enum libinput_tablet_pad_ring_axis_source
+libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0.0,
+			   LIBINPUT_EVENT_TABLET_PAD_RING);
+
+	return event->ring.source;
+}
+
+LIBINPUT_EXPORT double
+libinput_event_tablet_pad_get_strip_position(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0.0,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP);
+
+	return event->strip.position;
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0.0,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP);
+
+	return event->strip.number;
+}
+
+LIBINPUT_EXPORT enum libinput_tablet_pad_strip_axis_source
+libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0.0,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP);
+
+	return event->strip.source;
+}
+
+LIBINPUT_EXPORT uint32_t
+libinput_event_tablet_pad_get_button(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	return event->button;
+}
+
+LIBINPUT_EXPORT enum libinput_button_state
+libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	return event->state;
+}
+
+LIBINPUT_EXPORT uint32_t
+libinput_event_tablet_pad_get_seat_button_count(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	return event->seat_button_count;
+}
+
+LIBINPUT_EXPORT uint32_t
+libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_TABLET_PAD_RING,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	return us2ms(event->time);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_TABLET_PAD_RING,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	return event->time;
+}
+
+LIBINPUT_EXPORT struct libinput_event *
+libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   NULL,
+			   LIBINPUT_EVENT_TABLET_PAD_RING,
+			   LIBINPUT_EVENT_TABLET_PAD_STRIP,
+			   LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+	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 b14c281..e243711 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -59,6 +59,7 @@ enum libinput_device_capability {
 	LIBINPUT_DEVICE_CAP_POINTER = 1,
 	LIBINPUT_DEVICE_CAP_TOUCH = 2,
 	LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3,
+	LIBINPUT_DEVICE_CAP_TABLET_PAD = 4,
 	LIBINPUT_DEVICE_CAP_GESTURE = 5,
 };
 
@@ -135,6 +136,36 @@ enum libinput_pointer_axis_source {
 };
 
 /**
+ * @ingroup event_tablet
+ *
+ * The source for a @ref LIBINPUT_EVENT_TABLET_PAD_RING event. See
+ * libinput_event_tablet_pad_get_ring_source() for details.
+ */
+enum libinput_tablet_pad_ring_axis_source {
+	LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN = 1,
+	/**
+	 * The event is caused by the movement of one or more fingers on
+	 * the ring.
+	 */
+	LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
+};
+
+/**
+ * @ingroup event_tablet
+ *
+ * The source for a @ref LIBINPUT_EVENT_TABLET_PAD_STRIP event. See
+ * libinput_event_tablet_pad_get_strip_source() for details.
+ */
+enum libinput_tablet_pad_strip_axis_source {
+	LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN = 1,
+	/**
+	 * The event is caused by the movement of one or more fingers on
+	 * the strip.
+	 */
+	LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
+};
+
+/**
  * @ingroup device
  * @struct libinput_tablet_tool
  *
@@ -336,9 +367,34 @@ enum libinput_event_type {
 	 * same logical hardware event, the order of the @ref
 	 * LIBINPUT_EVENT_TABLET_TOOL_BUTTON and @ref
 	 * LIBINPUT_EVENT_TABLET_TOOL_AXIS event is device-specific.
+	 *
+	 * This event is not to be confused with the button events emitted
+	 * by the tablet pad. See @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON.
+	 *
+	 * @see LIBINPUT_EVENT_TABLET_BUTTON
 	 */
 	LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
 
+	/**
+	 * A button pressed on a device with the @ref
+	 * LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
+	 *
+	 * This event is not to be confused with the button events emitted
+	 * by tools on a tablet. See @ref LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
+	 */
+	LIBINPUT_EVENT_TABLET_PAD_BUTTON = 700,
+	/**
+	 * A status change on a tablet ring with the
+	 * LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
+	 */
+	LIBINPUT_EVENT_TABLET_PAD_RING,
+
+	/**
+	 * A status change on a strip on a device with the @ref
+	 * LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
+	 */
+	LIBINPUT_EVENT_TABLET_PAD_STRIP,
+
 	LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
 	LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
 	LIBINPUT_EVENT_GESTURE_SWIPE_END,
@@ -446,6 +502,17 @@ struct libinput_event_touch;
 struct libinput_event_tablet_tool;
 
 /**
+ * @ingroup event_tablet
+ * @struct libinput_event_tablet_pad
+ *
+ * Tablet pad event representing an button press, or ring/strip update on
+ * the tablet pad itself. Valid
+ * event types for this event are @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON, @ref
+ * LIBINPUT_EVENT_TABLET_PAD_RING and @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.
+ */
+struct libinput_event_tablet_pad;
+
+/**
  * @defgroup event Accessing and destruction of events
  */
 
@@ -567,6 +634,19 @@ libinput_event_get_tablet_tool_event(struct libinput_event *event);
 /**
  * @ingroup event
  *
+ * Return the tablet pad event that is this input event. If the event type does not
+ * match the tablet pad event types, this function returns NULL.
+ *
+ * The inverse of this function is libinput_event_tablet_pad_get_base_event().
+ *
+ * @return A tablet pad event, or NULL for other events
+ */
+struct libinput_event_tablet_pad *
+libinput_event_get_tablet_pad_event(struct libinput_event *event);
+
+/**
+ * @ingroup event
+ *
  * Return the device event that is this input event. If the event type does
  * not match the device event types, this function returns NULL.
  *
@@ -1355,7 +1435,17 @@ libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event);
 /**
  * @defgroup event_tablet Tablet events
  *
- * Events that come from tools on tablet devices.
+ * Events that come from tools on or the pad of tablet devices.
+ *
+ * Events from tablet devices are split into two event streams, tool events
+ * and pad events.Tool events originate (usually) from a stylus-like device,
+ * pad events reflect any events originating fom the physical tablet itself.
+ *
+ * Note that many tablets support touch events. These are exposed through
+ * the @ref LIBINPUT_DEVICE_CAP_POINTER interface (for external touchpad-like
+ * devices such as the Wacom Intuos series) or @ref
+ * LIBINPUT_DEVICE_CAP_TOUCH interface (for built-in touchscreen-like
+ * devices such as the Wacom Cintiq series).
  */
 
 /**
@@ -2092,6 +2182,195 @@ libinput_tablet_tool_set_user_data(struct libinput_tablet_tool *tool,
 				   void *user_data);
 
 /**
+ * @ingroup event_tablet
+ *
+ * @return The generic libinput_event of this event
+ */
+struct libinput_event *
+libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Returns the current position of the ring, in degrees counterclockwise
+ * from the northern-most point of the ring in the tablet's current logical
+ * orientation.
+ *
+ * If the source is @ref LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER and the
+ * finger is lifted from the ring, libinput sends a terminating event with a
+ * ring value of -1. A caller may use this information to e.g. determine if
+ * kinetic scrolling should be triggered.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_RING.  For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return The current value of the the axis
+ * @retval -1 The finger was lifted
+ */
+double
+libinput_event_tablet_pad_get_ring_position(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Returns the number of the ring that has changed state, with 0 being the
+ * first ring. On tablets with only one ring, this function always returns
+ * 0.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_RING.  For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return The index of the ring that changed state
+ */
+unsigned int
+libinput_event_tablet_pad_get_ring_number(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Returns the source of the interaction with the ring. If the source is
+ * @ref LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, libinput sends a ring
+ * position value of -1 to terminate the current interaction.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_RING.  For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return The source of the ring interaction
+ */
+enum libinput_tablet_pad_ring_axis_source
+libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Returns the current position of the strip, normalized to the range
+ * [0, 1], with 0 being the top/left-most point in the tablet's current
+ * logical orientation.
+ *
+ * If the source is @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER and the
+ * finger is lifted from the strip, libinput sends a terminating event with a
+ * strip value of -1. A caller may use this information to e.g. determine if
+ * kinetic scrolling should be triggered.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.  For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return The current value of the the axis
+ * @retval -1 The finger was lifted
+ */
+double
+libinput_event_tablet_pad_get_strip_position(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Returns the number of the strip that has changed state, with 0 being the
+ * first strip. On tablets with only one strip, this function always returns
+ * 0.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.  For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return The index of the strip that changed state
+ */
+unsigned int
+libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Returns the source of the interaction with the strip. If the source is
+ * @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, libinput sends a strip
+ * position value of -1 to terminate the current interaction.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.  For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return The source of the strip interaction
+ */
+enum libinput_tablet_pad_strip_axis_source
+libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Return the button that triggered this event.
+ * For events that are not of type @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON,
+ * this function returns 0.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON. For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return the button triggering this event
+ */
+uint32_t
+libinput_event_tablet_pad_get_button(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Return the button state of the event.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON. For other events, this function
+ * returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return the button state triggering this event
+ */
+enum libinput_button_state
+libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * For the button of a @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON event, return the total
+ * number of buttons pressed on all devices on the associated seat after the
+ * the event was triggered. This includes non-pad devices such as a pointer
+ * device.
+ *
+ " @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON. For other events, this function returns 0.
+ *
+ * @param event The libinput tablet pad event
+ * @return the seat wide pressed button count for the key of this event
+ */
+uint32_t
+libinput_event_tablet_pad_get_seat_button_count(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * @param event The libinput tablet pad event
+ * @return The event time for this event
+ */
+uint32_t
+libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * @param event The libinput tablet pad event
+ * @return The event time for this event in microseconds
+ */
+uint64_t
+libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event);
+
+/**
  * @defgroup base Initialization and manipulation of libinput contexts
  */
 
@@ -2920,6 +3199,52 @@ libinput_device_keyboard_has_key(struct libinput_device *device,
 /**
  * @ingroup device
  *
+ * Check if a @ref LIBINPUT_DEVICE_CAP_TABLET_PAD 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, e.g. <i>BTN_0</i>
+ *
+ * @return 1 if the device supports this button code, 0 if it does not, -1
+ * on error.
+ */
+int
+libinput_device_tablet_pad_has_button(struct libinput_device *device,
+				      uint32_t code);
+
+/**
+ * @ingroup device
+ *
+ * Return the number of rings a device with the @ref
+ * LIBINPUT_DEVICE_CAP_TABLET_PAD capability provides.
+ *
+ * @param device A current input device
+ *
+ * @return The number of rings or 0 if the device has no rings.
+ *
+ * @see libinput_event_tablet_pad_get_ring_number
+ */
+int
+libinput_device_tablet_pad_get_num_rings(struct libinput_device *device);
+
+/**
+ * @ingroup device
+ *
+ * Return the number of strips a device with the @ref
+ * LIBINPUT_DEVICE_CAP_TABLET_PAD capability provides.
+ *
+ * @param device A current input device
+ *
+ * @return The number of strips or 0 if the device has no strips.
+ *
+ * @see libinput_event_tablet_pad_get_strip_number
+ */
+int
+libinput_device_tablet_pad_get_num_strips(struct libinput_device *device);
+
+/**
+ * @ingroup device
+ *
  * Increase the refcount of the device group. A device group will be freed
  * whenever the refcount reaches 0. This may happen during
  * libinput_dispatch() if all devices of this group were removed from the
diff --git a/src/libinput.sym b/src/libinput.sym
index a211388..3a93e97 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -234,3 +234,23 @@ LIBINPUT_1.2 {
 	libinput_tablet_tool_set_user_data;
 	libinput_tablet_tool_unref;
 } LIBINPUT_1.1;
+
+TABLET_PAD {
+	libinput_device_tablet_pad_has_button;
+	libinput_device_tablet_pad_get_num_rings;
+	libinput_device_tablet_pad_get_num_strips;
+	libinput_event_get_tablet_pad_event;
+	libinput_event_tablet_pad_get_base_event;
+	libinput_event_tablet_pad_get_ring_position;
+	libinput_event_tablet_pad_get_ring_number;
+	libinput_event_tablet_pad_get_ring_source;
+	libinput_event_tablet_pad_get_strip_position;
+	libinput_event_tablet_pad_get_strip_number;
+	libinput_event_tablet_pad_get_strip_source;
+	libinput_event_tablet_pad_get_button;
+	libinput_event_tablet_pad_get_button_state;
+	libinput_event_tablet_pad_get_seat_button_count;
+	libinput_event_tablet_pad_get_time;
+	libinput_event_tablet_pad_get_time_usec;
+
+} LIBINPUT_1.2;
diff --git a/test/litest.c b/test/litest.c
index d5dbd8b..dcb34a9 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -1945,6 +1945,15 @@ litest_event_type_str(struct libinput_event *event)
 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
 		str = "TABLET TOOL BUTTON";
 		break;
+	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+		str = "TABLET PAD BUTTON";
+		break;
+	case LIBINPUT_EVENT_TABLET_PAD_RING:
+		str = "TABLET PAD RING";
+		break;
+	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+		str = "TABLET PAD STRIP";
+		break;
 	}
 	return str;
 }
diff --git a/tools/event-debug.c b/tools/event-debug.c
index 2c904fe..3e6bbe7 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -121,6 +121,15 @@ print_event_header(struct libinput_event *ev)
 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
 		type = "TABLET_TOOL_BUTTON";
 		break;
+	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+		type = "TABLET_PAD_BUTTON";
+		break;
+	case LIBINPUT_EVENT_TABLET_PAD_RING:
+		type = "TABLET_PAD_RING";
+		break;
+	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+		type = "TABLET_PAD_STRIP";
+		break;
 	}
 
 	printf("%-7s	%-16s ", libinput_device_get_sysname(dev), type);
@@ -172,6 +181,9 @@ print_device_notify(struct libinput_event *ev)
 	if (libinput_device_has_capability(dev,
 					   LIBINPUT_DEVICE_CAP_TABLET_TOOL))
 		printf("T");
+	if (libinput_device_has_capability(dev,
+					   LIBINPUT_DEVICE_CAP_TABLET_PAD))
+		printf("P");
 
 	if (libinput_device_get_size(dev, &w, &h) == 0)
 		printf("\tsize %.2f/%.2fmm", w, h);
@@ -568,6 +580,67 @@ print_gesture_event_with_coords(struct libinput_event *ev)
 	}
 }
 
+static void
+print_tablet_pad_button_event(struct libinput_event *ev)
+{
+	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
+	enum libinput_button_state state;
+
+	print_event_time(libinput_event_tablet_pad_get_time(p));
+
+	state = libinput_event_tablet_pad_get_button_state(p);
+	printf("%3d %s, seat count: %u\n",
+	       libinput_event_tablet_pad_get_button(p),
+	       state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
+	       libinput_event_tablet_pad_get_seat_button_count(p));
+}
+
+static void
+print_tablet_pad_ring_event(struct libinput_event *ev)
+{
+	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
+	const char *source = "<invalid>";
+
+	print_event_time(libinput_event_tablet_pad_get_time(p));
+
+	switch (libinput_event_tablet_pad_get_ring_source(p)) {
+	case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
+		source = "finger";
+		break;
+	case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
+		source = "unknown";
+		break;
+	}
+
+	printf("ring %d position %.2f (source %s)\n",
+	       libinput_event_tablet_pad_get_ring_number(p),
+	       libinput_event_tablet_pad_get_ring_position(p),
+	       source);
+}
+
+static void
+print_tablet_pad_strip_event(struct libinput_event *ev)
+{
+	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
+	const char *source = "<invalid>";
+
+	print_event_time(libinput_event_tablet_pad_get_time(p));
+
+	switch (libinput_event_tablet_pad_get_strip_source(p)) {
+	case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
+		source = "finger";
+		break;
+	case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
+		source = "unknown";
+		break;
+	}
+
+	printf("strip %d position %.2f (source %s)\n",
+	       libinput_event_tablet_pad_get_strip_number(p),
+	       libinput_event_tablet_pad_get_strip_position(p),
+	       source);
+}
+
 static int
 handle_and_print_events(struct libinput *li)
 {
@@ -647,6 +720,15 @@ handle_and_print_events(struct libinput *li)
 		case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
 			print_tablet_button_event(ev);
 			break;
+		case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+			print_tablet_pad_button_event(ev);
+			break;
+		case LIBINPUT_EVENT_TABLET_PAD_RING:
+			print_tablet_pad_ring_event(ev);
+			break;
+		case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+			print_tablet_pad_strip_event(ev);
+			break;
 		}
 
 		libinput_event_destroy(ev);
diff --git a/tools/event-gui.c b/tools/event-gui.c
index 9d541a3..791a1ea 100644
--- a/tools/event-gui.c
+++ b/tools/event-gui.c
@@ -798,6 +798,10 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
 		case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
 			handle_event_tablet(ev, w);
 			break;
+		case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+		case LIBINPUT_EVENT_TABLET_PAD_RING:
+		case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+			break;
 		}
 
 		libinput_event_destroy(ev);
-- 
2.5.0



More information about the wayland-devel mailing list