[PATCH libinput 21/26] tablet: support artpen rotation
Peter Hutterer
peter.hutterer at who-t.net
Mon Feb 23 22:21:24 PST 2015
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/evdev-tablet.c | 35 +++++++++++++++-----
src/evdev-tablet.h | 6 ++++
src/libinput.h | 3 +-
test/tablet.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 130 insertions(+), 9 deletions(-)
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 143d618..d05b6c2 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -103,6 +103,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:
@@ -240,6 +241,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, double offset)
+{
+ /* range is [0, 360[, i.e. range + 1 */
+ double range = absinfo->maximum - absinfo->minimum + 1;
+ double value = (absinfo->value - absinfo->minimum) / range;
+
+ return fmod(value * 360.0 + offset, 360.0);
+}
+
static void
tablet_check_notify_axes(struct tablet_dispatch *tablet,
struct evdev_device *device,
@@ -263,14 +274,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;
}
@@ -294,6 +304,10 @@ 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:
+ /* artpen has 0 with buttons pointing east */
+ tablet->axes[a] = convert_to_degrees(absinfo, 90);
+ break;
default:
log_bug_libinput(device->base.seat->libinput,
"Invalid axis update: %d\n", a);
@@ -506,6 +520,10 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet,
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_SLIDER);
/* fall-through */
case WSTYLUS_MARKER:
+ if (type == WSTYLUS_MARKER)
+ copy_axis_cap(tablet, tool,
+ LIBINPUT_TABLET_AXIS_ROTATION_Z);
+ /* fallthrough */
case WSTYLUS_GENERAL:
case WSTYLUS_INKING:
case WSTYLUS_CLASSIC:
@@ -555,6 +573,7 @@ tool_set_bits(const struct tablet_dispatch *tablet,
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_TILT_X);
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_TILT_Y);
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_SLIDER);
+ copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_ROTATION_Z);
break;
case LIBINPUT_TOOL_MOUSE:
case LIBINPUT_TOOL_LENS:
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index d86bf9e..7c472cf 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -75,6 +75,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;
@@ -122,6 +125,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 fb6b803..87d220b 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -1056,7 +1056,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 fef4fc5..afc654e 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -1359,6 +1359,99 @@ START_TEST(airbrush_wheel)
}
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_ABS,
+ ABS_Z))
+ return;
+
+ litest_drain_events(li);
+
+ litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
+ litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
+ 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_PEN);
+ ck_assert(libinput_tool_has_axis(tool,
+ LIBINPUT_TABLET_AXIS_ROTATION_Z));
+
+ 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_ABS,
+ ABS_Z))
+ 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_ABS, ABS_MISC, 0x804); /* Art Pen */
+ 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);
+
+ /* artpen has a 90 deg offset cw */
+ ck_assert_int_eq(round(val), (angle + 90) % 360);
+ libinput_event_destroy(event);
+ litest_assert_empty_queue(li);
+ }
+}
+END_TEST
+
int
main(int argc, char **argv)
{
@@ -1384,6 +1477,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