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

Stephen Chandler Paul thatslyude at gmail.com
Thu Aug 7 15:54:55 PDT 2014


Because the axes that tool reports can change depending on the tool in use, we
want to be able to provide functionality to determine which axes each tool can
support.

Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---

Changes:
	- Added a description to the patch
	- Fixed all of the memory leaks, passes make check with flying
	  colors now

 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          | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 149 insertions(+)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 43da67a..5f8a466 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);
 	}
 
@@ -512,6 +546,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 2de0989..657251e 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -766,10 +766,82 @@ 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);
+	}
+
+	litest_delete_device(bamboo);
+	litest_delete_device(intuos);
+	libinput_unref(li);
+}
+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