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.hutte...@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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel