[PATCH libinput 24/26] tablet: support the rel wheel on the mouse device
Peter Hutterer
peter.hutterer at who-t.net
Mon Feb 23 22:21:27 PST 2015
Providing a relative axis in the axis_get_value() is inconsistent with the
other axes, this will be fixed in a follow-up commit.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/evdev-tablet.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/evdev-tablet.h | 18 ++++++++++++++++
src/libinput-private.h | 2 +-
src/libinput.c | 1 +
src/libinput.h | 4 ++++
test/tablet.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
tools/event-debug.c | 11 +++++++++-
7 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index d05b6c2..0fd5033 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -82,6 +82,10 @@ tablet_device_has_axis(struct tablet_dispatch *tablet,
libevdev_has_event_code(evdev,
EV_ABS,
ABS_TILT_Y));
+ } else if (axis == LIBINPUT_TABLET_AXIS_REL_WHEEL) {
+ has_axis = libevdev_has_event_code(evdev,
+ EV_REL,
+ REL_WHEEL);
} else {
code = axis_to_evcode(axis);
has_axis = libevdev_has_event_code(evdev,
@@ -251,6 +255,15 @@ convert_to_degrees(const struct input_absinfo *absinfo, double offset)
return fmod(value * 360.0 + offset, 360.0);
}
+static inline double
+normalize_wheel(struct tablet_dispatch *tablet,
+ int value)
+{
+ struct evdev_device *device = tablet->device;
+
+ return value * device->scroll.wheel_click_angle;
+}
+
static void
tablet_check_notify_axes(struct tablet_dispatch *tablet,
struct evdev_device *device,
@@ -282,6 +295,11 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
axes[LIBINPUT_TABLET_AXIS_TILT_Y] = 0;
axes[a] = tablet->axes[a];
continue;
+ } else if (a == LIBINPUT_TABLET_AXIS_REL_WHEEL) {
+ tablet->axes[a] = normalize_wheel(tablet,
+ tablet->deltas[a]);
+ axes[a] = tablet->axes[a];
+ break;
}
absinfo = libevdev_get_abs_info(device->evdev,
@@ -442,6 +460,35 @@ tablet_process_key(struct tablet_dispatch *tablet,
}
static void
+tablet_process_relative(struct tablet_dispatch *tablet,
+ struct evdev_device *device,
+ struct input_event *e,
+ uint32_t time)
+{
+ enum libinput_tablet_axis axis;
+ switch (e->code) {
+ case REL_WHEEL:
+ axis = rel_evcode_to_axis(e->code);
+ if (axis == LIBINPUT_TABLET_AXIS_NONE) {
+ log_bug_libinput(device->base.seat->libinput,
+ "Invalid ABS event code %#x\n",
+ e->code);
+ break;
+ }
+ set_bit(tablet->changed_axes, axis);
+ tablet->deltas[axis] = e->value;
+ tablet_set_status(tablet, TABLET_AXES_UPDATED);
+ break;
+ default:
+ log_info(tablet->device->base.seat->libinput,
+ "Unhandled relative axis %s (%#x)\n",
+ libevdev_event_code_get_name(EV_REL, e->code),
+ e->code);
+ return;
+ }
+}
+
+static void
tablet_process_misc(struct tablet_dispatch *tablet,
struct evdev_device *device,
struct input_event *e,
@@ -535,6 +582,11 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet,
break;
case WSTYLUS_PUCK:
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_ROTATION_Z);
+ /* lens cursors don't have a wheel */
+ if (!libwacom_stylus_has_lens(s))
+ copy_axis_cap(tablet,
+ tool,
+ LIBINPUT_TABLET_AXIS_REL_WHEEL);
break;
default:
break;
@@ -578,6 +630,7 @@ tool_set_bits(const struct tablet_dispatch *tablet,
case LIBINPUT_TOOL_MOUSE:
case LIBINPUT_TOOL_LENS:
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_ROTATION_Z);
+ copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_REL_WHEEL);
break;
default:
break;
@@ -824,6 +877,9 @@ tablet_process(struct evdev_dispatch *dispatch,
case EV_ABS:
tablet_process_absolute(tablet, device, e, time);
break;
+ case EV_REL:
+ tablet_process_relative(tablet, device, e, time);
+ break;
case EV_KEY:
tablet_process_key(tablet, device, e, time);
break;
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index 7c472cf..ea103b0 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -50,6 +50,7 @@ struct tablet_dispatch {
unsigned char status;
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_MAX + 1)];
double axes[LIBINPUT_TABLET_AXIS_MAX + 1];
+ double deltas[LIBINPUT_TABLET_AXIS_MAX + 1];
unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_AXIS_MAX + 1)];
/* Only used for tablets that don't report serial numbers */
@@ -101,6 +102,23 @@ evcode_to_axis(const uint32_t evcode)
return axis;
}
+static inline enum libinput_tablet_axis
+rel_evcode_to_axis(const uint32_t evcode)
+{
+ enum libinput_tablet_axis axis;
+
+ switch (evcode) {
+ case REL_WHEEL:
+ axis = LIBINPUT_TABLET_AXIS_REL_WHEEL;
+ break;
+ default:
+ axis = LIBINPUT_TABLET_AXIS_NONE;
+ break;
+ }
+
+ return axis;
+}
+
static inline uint32_t
axis_to_evcode(const enum libinput_tablet_axis axis)
{
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 84e5aaa..071204e 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -30,7 +30,7 @@
#include "libinput.h"
#include "libinput-util.h"
-#define LIBINPUT_TABLET_AXIS_MAX LIBINPUT_TABLET_AXIS_SLIDER
+#define LIBINPUT_TABLET_AXIS_MAX LIBINPUT_TABLET_AXIS_REL_WHEEL
struct libinput_source;
diff --git a/src/libinput.c b/src/libinput.c
index 9df3d48..2640321 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -586,6 +586,7 @@ libinput_event_tablet_get_axis_value(struct libinput_event_tablet *event,
case LIBINPUT_TABLET_AXIS_TILT_Y:
case LIBINPUT_TABLET_AXIS_ROTATION_Z:
case LIBINPUT_TABLET_AXIS_SLIDER:
+ case LIBINPUT_TABLET_AXIS_REL_WHEEL:
return event->axes[axis];
default:
return 0;
diff --git a/src/libinput.h b/src/libinput.h
index 87d220b..5737873 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -144,6 +144,7 @@ enum libinput_tablet_axis {
LIBINPUT_TABLET_AXIS_TILT_Y = 6,
LIBINPUT_TABLET_AXIS_ROTATION_Z = 7,
LIBINPUT_TABLET_AXIS_SLIDER = 8,
+ LIBINPUT_TABLET_AXIS_REL_WHEEL = 9,
};
/**
@@ -1060,6 +1061,9 @@ libinput_event_tablet_axis_has_changed(struct libinput_event_tablet *event,
* 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.
+ * - @ref LIBINPUT_TABLET_AXIS_REL_WHEEL - A relative wheel on the tool,
+ * similar or equivalent to a mouse wheel. The value is a delta from the
+ * device's previous position, in degrees.
*
* @note This function may be called for a specific axis even if
* libinput_event_tablet_axis_has_changed() returns 0 for that axis.
diff --git a/test/tablet.c b/test/tablet.c
index afc654e..e46314a 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -1273,6 +1273,59 @@ START_TEST(mouse_rotation)
}
END_TEST
+START_TEST(mouse_wheel)
+{
+ 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;
+ double val;
+
+ if (!libevdev_has_event_code(dev->evdev,
+ EV_REL,
+ REL_WHEEL))
+ return;
+
+ litest_drain_events(li);
+
+ litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
+ litest_event(dev, EV_ABS, ABS_MISC, 0x806); /* 5-button mouse tool_id */
+ 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);
+ libinput_tool_ref(tool);
+
+ libinput_event_destroy(event);
+
+ ck_assert(libinput_tool_has_axis(tool,
+ LIBINPUT_TABLET_AXIS_REL_WHEEL));
+
+ litest_event(dev, EV_REL, REL_WHEEL, -1);
+ 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_REL_WHEEL));
+ val = libinput_event_tablet_get_axis_value(tev,
+ LIBINPUT_TABLET_AXIS_REL_WHEEL);
+ ck_assert_int_eq(val, 15);
+ libinput_event_destroy(event);
+
+ libinput_tool_unref(tool);
+}
+END_TEST
+
START_TEST(airbrush_tool)
{
struct litest_device *dev = litest_current_device();
@@ -1475,6 +1528,7 @@ main(int argc, char **argv)
litest_add("tablet:mouse", mouse_tool, LITEST_TABLET, LITEST_ANY);
litest_add("tablet:mouse", mouse_buttons, LITEST_TABLET, LITEST_ANY);
litest_add("tablet:mouse", mouse_rotation, LITEST_TABLET, LITEST_ANY);
+ litest_add("tablet:mouse", mouse_wheel, 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);
diff --git a/tools/event-debug.c b/tools/event-debug.c
index 94a90ec..09edac0 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -293,7 +293,7 @@ print_tablet_axes(struct libinput_event_tablet *t)
struct libinput_tool *tool = libinput_event_tablet_get_tool(t);
double x, y;
double dist, pressure;
- double rotation, slider;
+ double rotation, slider, wheel;
x = libinput_event_tablet_get_axis_value(t, LIBINPUT_TABLET_AXIS_X);
y = libinput_event_tablet_get_axis_value(t, LIBINPUT_TABLET_AXIS_Y);
@@ -350,6 +350,15 @@ print_tablet_axes(struct libinput_event_tablet *t)
tablet_axis_changed_sym(t,
LIBINPUT_TABLET_AXIS_SLIDER));
}
+
+ if (libinput_tool_has_axis(tool, LIBINPUT_TABLET_AXIS_REL_WHEEL)) {
+ wheel = libinput_event_tablet_get_axis_value(t,
+ LIBINPUT_TABLET_AXIS_REL_WHEEL);
+ printf("\twheel: %.2f%s",
+ wheel,
+ tablet_axis_changed_sym(t,
+ LIBINPUT_TABLET_AXIS_REL_WHEEL));
+ }
}
static void
--
2.1.0
More information about the wayland-devel
mailing list