[PATCH libinput 11/15] tablet: support artpen rotation

Peter Hutterer peter.hutterer at who-t.net
Tue Feb 17 21:45:12 PST 2015


Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-tablet.c |  33 +++++++++++++----
 src/evdev-tablet.h |   6 +++
 src/libinput.h     |   3 +-
 test/tablet.c      | 105 +++++++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 131 insertions(+), 16 deletions(-)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 27589b1..81cb99e 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -72,6 +72,7 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
 	switch (e->code) {
 	case ABS_X:
 	case ABS_Y:
+	case ABS_Z:
 	case ABS_PRESSURE:
 	case ABS_TILT_X:
 	case ABS_TILT_Y:
@@ -205,6 +206,16 @@ convert_tilt_to_rotation(struct tablet_dispatch *tablet)
 	set_bit(tablet->changed_axes, LIBINPUT_TABLET_AXIS_ROTATION_Z);
 }
 
+static double
+convert_to_degrees(const struct input_absinfo *absinfo)
+{
+	/* range is [0, 360[, i.e. range + 1 */
+	double range = absinfo->maximum - absinfo->minimum + 1;
+	double value = (absinfo->value - absinfo->minimum) / range;
+
+	return value * 360.0;
+}
+
 static void
 tablet_check_notify_axes(struct tablet_dispatch *tablet,
 			 struct evdev_device *device,
@@ -228,14 +239,13 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
 
 		/* ROTATION_Z is higher than TILT_X/Y so we know that the
 		   tilt axes are already normalized and set */
-		if (a == LIBINPUT_TABLET_AXIS_ROTATION_Z) {
-			if (tablet->current_tool_type == LIBINPUT_TOOL_MOUSE ||
-			    tablet->current_tool_type == LIBINPUT_TOOL_LENS) {
-				convert_tilt_to_rotation(tablet);
-				axes[LIBINPUT_TABLET_AXIS_TILT_X] = 0;
-				axes[LIBINPUT_TABLET_AXIS_TILT_Y] = 0;
-				axes[a] = tablet->axes[a];
-			}
+		if (a == LIBINPUT_TABLET_AXIS_ROTATION_Z &&
+		   (tablet->current_tool_type == LIBINPUT_TOOL_MOUSE ||
+		    tablet->current_tool_type == LIBINPUT_TOOL_LENS)) {
+			convert_tilt_to_rotation(tablet);
+			axes[LIBINPUT_TABLET_AXIS_TILT_X] = 0;
+			axes[LIBINPUT_TABLET_AXIS_TILT_Y] = 0;
+			axes[a] = tablet->axes[a];
 			continue;
 		}
 
@@ -259,6 +269,9 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
 		case LIBINPUT_TABLET_AXIS_TILT_Y:
 			tablet->axes[a] = normalize_tilt(absinfo);
 			break;
+		case LIBINPUT_TABLET_AXIS_ROTATION_Z:
+			tablet->axes[a] = convert_to_degrees(absinfo);
+			break;
 		default:
 			log_bug_libinput(device->base.seat->libinput,
 					 "Invalid axis update: %d\n", a);
@@ -457,6 +470,10 @@ tablet_get_tool(struct tablet_dispatch *tablet,
 				set_bit(tool->axis_caps,
 					LIBINPUT_TABLET_AXIS_TILT_Y);
 			if (bit_is_set(tablet->axis_caps,
+				       LIBINPUT_TABLET_AXIS_ROTATION_Z))
+				set_bit(tool->axis_caps,
+					LIBINPUT_TABLET_AXIS_ROTATION_Z);
+			if (bit_is_set(tablet->axis_caps,
 				       LIBINPUT_TABLET_AXIS_SLIDER))
 				set_bit(tool->axis_caps,
 					LIBINPUT_TABLET_AXIS_SLIDER);
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index ee2ef08..8804ae6 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -74,6 +74,9 @@ evcode_to_axis(const uint32_t evcode)
 	case ABS_Y:
 		axis = LIBINPUT_TABLET_AXIS_Y;
 		break;
+	case ABS_Z:
+		axis = LIBINPUT_TABLET_AXIS_ROTATION_Z;
+		break;
 	case ABS_DISTANCE:
 		axis = LIBINPUT_TABLET_AXIS_DISTANCE;
 		break;
@@ -121,6 +124,9 @@ axis_to_evcode(const enum libinput_tablet_axis axis)
 	case LIBINPUT_TABLET_AXIS_TILT_Y:
 		evcode = ABS_TILT_Y;
 		break;
+	case LIBINPUT_TABLET_AXIS_ROTATION_Z:
+		evcode = ABS_Z;
+		break;
 	case LIBINPUT_TABLET_AXIS_SLIDER:
 		evcode = ABS_WHEEL;
 		break;
diff --git a/src/libinput.h b/src/libinput.h
index 7b90e91..461925a 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -1044,7 +1044,8 @@ libinput_event_tablet_axis_has_changed(struct libinput_event_tablet *event,
  *   degrees, clockwise from the tool's logical neutral position. For the
  *   @ref LIBINPUT_TOOL_MOUSE and @ref LIBINPUT_TOOL_LENS tools the logical
  *   neutral position is pointing to the current logical north of the
- *   tablet.
+ *   tablet. For the @ref LIBINPUT_TOOL_BRUSH tool, the logical neutral
+ *   position is with the buttons pointing up.
  * - @ref LIBINPUT_TABLET_AXIS_SLIDER - A slider on the tool, normalized
  *   from 0 to 1. e.g. the wheel-like tool on the Wacom Airbrush.
  *
diff --git a/test/tablet.c b/test/tablet.c
index 3ab9fa3..99a4b91 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -1188,7 +1188,7 @@ START_TEST(airbrush_wheel)
 	struct libinput_event_tablet *tev;
 	const struct input_absinfo *abs;
 	double val;
-	double scale;
+	double range;
 	int angle;
 
 	if (!libevdev_has_event_code(dev->evdev,
@@ -1211,11 +1211,9 @@ START_TEST(airbrush_wheel)
 
 	litest_drain_events(li);
 
-	scale = (abs->maximum - abs->minimum)/360.0;
-	for (angle = 0; angle < 360; angle += 8) {
-		int a = angle * scale + abs->minimum;
-
-		litest_event(dev, EV_ABS, ABS_WHEEL, a);
+	range = (abs->maximum - abs->minimum);
+	for (angle = abs->minimum; angle <= abs->maximum; angle += 8) {
+		litest_event(dev, EV_ABS, ABS_WHEEL, angle);
 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
 
 		litest_wait_for_event_of_type(li,
@@ -1228,7 +1226,98 @@ START_TEST(airbrush_wheel)
 		val = libinput_event_tablet_get_axis_value(tev,
 					 LIBINPUT_TABLET_AXIS_SLIDER);
 
-		ck_assert_int_eq(val, angle);
+		litest_assert_double_ge(val, 0.0);
+		litest_assert_double_le(val, 1.0);
+
+		ck_assert_int_eq(val, 1.0 * (angle/range));
+		libinput_event_destroy(event);
+		litest_assert_empty_queue(li);
+	}
+}
+END_TEST
+
+START_TEST(artpen_tool)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet *tev;
+	struct libinput_tool *tool;
+
+	if (!libevdev_has_event_code(dev->evdev,
+				    EV_KEY,
+				    BTN_TOOL_BRUSH))
+		return;
+
+	litest_drain_events(li);
+
+	litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
+	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
+	litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+	litest_wait_for_event_of_type(li,
+				      LIBINPUT_EVENT_TABLET_PROXIMITY,
+				      -1);
+	event = libinput_get_event(li);
+	tev = libinput_event_get_tablet_event(event);
+	tool = libinput_event_tablet_get_tool(tev);
+	ck_assert_notnull(tool);
+	ck_assert_int_eq(libinput_tool_get_type(tool),
+			 LIBINPUT_TOOL_BRUSH);
+
+	libinput_event_destroy(event);
+}
+END_TEST
+
+START_TEST(artpen_rotation)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet *tev;
+	const struct input_absinfo *abs;
+	double val;
+	double scale;
+	int angle;
+
+	if (!libevdev_has_event_code(dev->evdev,
+				    EV_KEY,
+				    BTN_TOOL_BRUSH))
+		return;
+
+	litest_drain_events(li);
+
+	abs = libevdev_get_abs_info(dev->evdev, ABS_Z);
+	ck_assert_notnull(abs);
+
+	litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
+	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
+	litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+	/* start with non-zero */
+	litest_event(dev, EV_ABS, ABS_Z, 10);
+	litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+	litest_drain_events(li);
+
+	scale = (abs->maximum - abs->minimum + 1)/360.0;
+	for (angle = 0; angle < 360; angle += 8) {
+		int a = angle * scale + abs->minimum;
+
+		litest_event(dev, EV_ABS, ABS_Z, a);
+		litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+		litest_wait_for_event_of_type(li,
+					      LIBINPUT_EVENT_TABLET_AXIS,
+					      -1);
+		event = libinput_get_event(li);
+		tev = libinput_event_get_tablet_event(event);
+		ck_assert(libinput_event_tablet_axis_has_changed(tev,
+					 LIBINPUT_TABLET_AXIS_ROTATION_Z));
+		val = libinput_event_tablet_get_axis_value(tev,
+					 LIBINPUT_TABLET_AXIS_ROTATION_Z);
+
+		ck_assert_int_eq(round(val), angle);
 		libinput_event_destroy(event);
 		litest_assert_empty_queue(li);
 	}
@@ -1258,6 +1347,8 @@ main(int argc, char **argv)
 	litest_add("tablet:mouse", mouse_rotation, LITEST_TABLET, LITEST_ANY);
 	litest_add("tablet:airbrush", airbrush_tool, LITEST_TABLET, LITEST_ANY);
 	litest_add("tablet:airbrush", airbrush_wheel, LITEST_TABLET, LITEST_ANY);
+	litest_add("tablet:artpen", artpen_tool, LITEST_TABLET, LITEST_ANY);
+	litest_add("tablet:artpen", artpen_rotation, LITEST_TABLET, LITEST_ANY);
 
 	return litest_run(argc, argv);
 }
-- 
2.1.0



More information about the wayland-devel mailing list