[PATCH libinput 2/2] tablet: Add libinput_tool_has_axis() and tests

Stephen Chandler Paul thatslyude at gmail.com
Wed Aug 6 21:09:23 PDT 2014


Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---
 src/evdev-tablet.c     | 42 +++++++++++++++++++++++++++++++
 src/evdev-tablet.h     |  1 +
 src/libinput-private.h |  1 +
 src/libinput.c         |  7 ++++++
 src/libinput.h         | 26 +++++++++++++++++++
 test/tablet.c          | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 145 insertions(+)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 6ae6844..f56d7f4 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -298,6 +298,40 @@ tablet_get_tool(struct tablet_dispatch *tablet,
 			.refcount = 1,
 		};
 
+		/* Determine the axis capabilities of the tool. Here's a break
+		 * down of the heuristics used here:
+		 * - The Wacom art pen supports all of the extra axes, along
+		 *   with rotation
+		 * - All of normal pens and the airbrush support all of the
+		 *   extra axes if the tablet can report them
+		 * - All of the mouse like devices don't really report any of
+		 *   the extra axes except for rotation.
+		 * (as of writing this comment, rotation isn't supported, so you
+		 * won't see the mouse or art pen here)
+		 */
+		switch (type) {
+		case LIBINPUT_TOOL_PEN:
+		case LIBINPUT_TOOL_ERASER:
+		case LIBINPUT_TOOL_PENCIL:
+		case LIBINPUT_TOOL_BRUSH:
+		case LIBINPUT_TOOL_AIRBRUSH:
+			if (bit_is_set(tablet->axis_caps,
+				       LIBINPUT_TOOL_AXIS_FLAG_PRESSURE))
+				set_bit(tool->axis_caps,
+					LIBINPUT_TOOL_AXIS_FLAG_PRESSURE);
+			if (bit_is_set(tablet->axis_caps,
+				       LIBINPUT_TOOL_AXIS_FLAG_DISTANCE))
+				set_bit(tool->axis_caps,
+					LIBINPUT_TOOL_AXIS_FLAG_DISTANCE);
+			if (bit_is_set(tablet->axis_caps,
+				       LIBINPUT_TOOL_AXIS_FLAG_TILT))
+				set_bit(tool->axis_caps,
+					LIBINPUT_TOOL_AXIS_FLAG_TILT);
+			break;
+		default:
+			break;
+		}
+
 		list_insert(tool_list, &tool->link);
 	}
 
@@ -507,6 +541,14 @@ tablet_init(struct tablet_dispatch *tablet,
 	tablet->current_tool_type = LIBINPUT_TOOL_NONE;
 	list_init(&tablet->tool_list);
 
+	if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_PRESSURE))
+		set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE);
+	if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_DISTANCE))
+		set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE);
+	if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_TILT_X) &&
+	    libevdev_has_event_code(device->evdev, EV_ABS, ABS_TILT_Y))
+		set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_TILT);
+
 	tablet_mark_all_axes_changed(tablet, device);
 
 	return 0;
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index d16aef3..be2d09a 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -49,6 +49,7 @@ struct tablet_dispatch {
 	unsigned char status;
 	unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
 	double axes[LIBINPUT_TABLET_AXIS_CNT];
+	unsigned char axis_caps[NCHARS(LIBINPUT_TOOL_AXIS_FLAG_CNT)];
 
 	/* Only used for tablets that don't report serial numbers */
 	struct list tool_list;
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 8187564..bdef330 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -108,6 +108,7 @@ struct libinput_tool {
 	struct list link;
 	uint32_t serial;
 	enum libinput_tool_type type;
+	unsigned char axis_caps[NCHARS(LIBINPUT_TOOL_AXIS_FLAG_CNT)];
 	int refcount;
 	void *user_data;
 };
diff --git a/src/libinput.c b/src/libinput.c
index 68187d8..560fedd 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -599,6 +599,13 @@ libinput_tool_get_serial(struct libinput_tool *tool)
 	return tool->serial;
 }
 
+LIBINPUT_EXPORT int
+libinput_tool_has_axis(struct libinput_tool *tool,
+		       enum libinput_tool_axis_flag axis)
+{
+	return bit_is_set(tool->axis_caps, axis);
+}
+
 LIBINPUT_EXPORT void
 libinput_tool_set_user_data(struct libinput_tool *tool,
 			    void *user_data)
diff --git a/src/libinput.h b/src/libinput.h
index 1d4952b..63c5ad3 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -214,6 +214,19 @@ enum libinput_tool_type {
 };
 
 /**
+ * @ingroup device
+ *
+ * A series of flags for representing which kinds of axes a tablet tool can
+ * support.
+ */
+enum libinput_tool_axis_flag {
+	LIBINPUT_TOOL_AXIS_FLAG_PRESSURE = 0,
+	LIBINPUT_TOOL_AXIS_FLAG_DISTANCE = 1,
+	LIBINPUT_TOOL_AXIS_FLAG_TILT = 2,
+	LIBINPUT_TOOL_AXIS_FLAG_CNT = 3,
+};
+
+/**
  * @ingroup base
  *
  * Event type for events returned by libinput_get_event().
@@ -1010,6 +1023,19 @@ libinput_tool_ref(struct libinput_tool *tool);
 /**
  * @ingroup event_tablet
  *
+ * Return whether or not a tablet tool supports the specified axis
+ *
+ * @param tool The tool to check the axis capabilities of
+ * @param axis The axis to check for support
+ * @return Whether or not the axis is supported
+ */
+int
+libinput_tool_has_axis(struct libinput_tool *tool,
+		       enum libinput_tool_axis_flag axis);
+
+/**
+ * @ingroup event_tablet
+ *
  * Decrement the ref count of tool by one. When the ref count of tool reaches 0,
  * the memory allocated for tool will be freed.
  *
diff --git a/test/tablet.c b/test/tablet.c
index 60a4240..d4624a5 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -758,10 +758,78 @@ START_TEST(tools_without_serials)
 }
 END_TEST
 
+START_TEST(tool_capabilities)
+{
+	struct libinput *li = litest_create_context();
+	struct litest_device *intuos;
+	struct litest_device *bamboo;
+	struct libinput_event *event;
+
+	/* The axis capabilities of a tool can differ depending on the type of
+	 * tablet the tool is being used with */
+	bamboo = litest_create_device_with_overrides(LITEST_WACOM_BAMBOO,
+						     NULL,
+						     NULL,
+						     NULL,
+						     NULL);
+	intuos = litest_create_device_with_overrides(LITEST_WACOM_INTUOS,
+						     NULL,
+						     NULL,
+						     NULL,
+						     NULL);
+
+	litest_event(bamboo, EV_KEY, BTN_TOOL_PEN, 1);
+	litest_event(bamboo, EV_SYN, SYN_REPORT, 0);
+
+	libinput_dispatch(li);
+	while ((event = libinput_get_event(li))) {
+		if (libinput_event_get_type(event) ==
+		    LIBINPUT_EVENT_TABLET_PROXIMITY_IN) {
+			struct libinput_event_tablet *t =
+				libinput_event_get_tablet_event(event);
+			struct libinput_tool *tool =
+				libinput_event_tablet_get_tool(t);
+
+			ck_assert(libinput_tool_has_axis(
+				tool, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));
+			ck_assert(!libinput_tool_has_axis(
+				tool, LIBINPUT_TOOL_AXIS_FLAG_TILT));
+			ck_assert(libinput_tool_has_axis(
+				tool, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE));
+		}
+
+		libinput_event_destroy(event);
+	}
+
+	litest_event(intuos, EV_KEY, BTN_TOOL_PEN, 1);
+	litest_event(intuos, EV_SYN, SYN_REPORT, 0);
+
+	while ((event = libinput_get_event(li))) {
+		if (libinput_event_get_type(event) ==
+		    LIBINPUT_EVENT_TABLET_PROXIMITY_IN) {
+			struct libinput_event_tablet *t =
+				libinput_event_get_tablet_event(event);
+			struct libinput_tool *tool =
+				libinput_event_tablet_get_tool(t);
+
+			ck_assert(libinput_tool_has_axis(
+				tool, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));
+			ck_assert(libinput_tool_has_axis(
+				tool, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE));
+			ck_assert(libinput_tool_has_axis(
+				tool, LIBINPUT_TOOL_AXIS_FLAG_TILT));
+		}
+
+		libinput_event_destroy(event);
+	}
+}
+END_TEST
+
 int
 main(int argc, char **argv)
 {
 	litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
+	litest_add_no_device("tablet:tool", tool_capabilities);
 	litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
 	litest_add("tablet:tool_serial", serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
 	litest_add("tablet:tool_serial", invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
-- 
1.8.5.5



More information about the wayland-devel mailing list