diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index bfdbcc4a..0e92ee47 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -107,6 +107,7 @@ tablet_process_absolute(struct tablet_dispatch *tablet, case ABS_TILT_X: case ABS_TILT_Y: case ABS_DISTANCE: + case ABS_WHEEL: axis = evcode_to_axis(e->code); if (axis == LIBINPUT_TABLET_AXIS_NONE) { log_bug_libinput(device->base.seat->libinput, @@ -189,7 +190,7 @@ tablet_update_tool(struct tablet_dispatch *tablet, } static inline double -normalize_pressure_or_dist(const struct input_absinfo *absinfo) +normalize_pressure_dist_slider(const struct input_absinfo *absinfo) { double range = absinfo->maximum - absinfo->minimum; double value = (absinfo->value - absinfo->minimum) / range; @@ -286,7 +287,8 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, break; case LIBINPUT_TABLET_AXIS_DISTANCE: case LIBINPUT_TABLET_AXIS_PRESSURE: - tablet->axes[a] = normalize_pressure_or_dist(absinfo); + case LIBINPUT_TABLET_AXIS_SLIDER: + tablet->axes[a] = normalize_pressure_dist_slider(absinfo); break; case LIBINPUT_TABLET_AXIS_TILT_X: case LIBINPUT_TABLET_AXIS_TILT_Y: @@ -502,6 +504,8 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet, separately. */ switch(type) { case WSTYLUS_AIRBRUSH: + copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_SLIDER); + /* fall-through */ case WSTYLUS_MARKER: case WSTYLUS_GENERAL: case WSTYLUS_INKING: @@ -551,6 +555,7 @@ tool_set_bits(const struct tablet_dispatch *tablet, copy_axis_cap(tablet, tool, LIBINPUT_TABLET_AXIS_DISTANCE); 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); break; case LIBINPUT_TOOL_MOUSE: case LIBINPUT_TOOL_LENS: diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index d2806b4d..d86bf9e6 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -87,6 +87,9 @@ evcode_to_axis(const uint32_t evcode) case ABS_TILT_Y: axis = LIBINPUT_TABLET_AXIS_TILT_Y; break; + case ABS_WHEEL: + axis = LIBINPUT_TABLET_AXIS_SLIDER; + break; default: axis = LIBINPUT_TABLET_AXIS_NONE; break; @@ -119,6 +122,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_SLIDER: + evcode = ABS_WHEEL; + break; default: abort(); } diff --git a/src/libinput-private.h b/src/libinput-private.h index 20d9e43b..84e5aaaa 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_ROTATION_Z +#define LIBINPUT_TABLET_AXIS_MAX LIBINPUT_TABLET_AXIS_SLIDER struct libinput_source; diff --git a/src/libinput.c b/src/libinput.c index 87ddc69c..9df3d484 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -585,6 +585,7 @@ libinput_event_tablet_get_axis_value(struct libinput_event_tablet *event, case LIBINPUT_TABLET_AXIS_TILT_X: case LIBINPUT_TABLET_AXIS_TILT_Y: case LIBINPUT_TABLET_AXIS_ROTATION_Z: + case LIBINPUT_TABLET_AXIS_SLIDER: return event->axes[axis]; default: return 0; diff --git a/src/libinput.h b/src/libinput.h index bbefc38f..a74b651a 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -143,6 +143,7 @@ enum libinput_tablet_axis { LIBINPUT_TABLET_AXIS_TILT_X = 5, LIBINPUT_TABLET_AXIS_TILT_Y = 6, LIBINPUT_TABLET_AXIS_ROTATION_Z = 7, + LIBINPUT_TABLET_AXIS_SLIDER = 8, }; /** @@ -1056,6 +1057,8 @@ libinput_event_tablet_axis_has_changed(struct libinput_event_tablet *event, * @ref LIBINPUT_TOOL_MOUSE and @ref LIBINPUT_TOOL_LENS tools the logical * neutral position is pointing to the current logical north of the * tablet. + * - @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. * * @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 6eca5c42..fef4fc50 100644 --- a/test/tablet.c +++ b/test/tablet.c @@ -1273,6 +1273,92 @@ START_TEST(mouse_rotation) } END_TEST +START_TEST(airbrush_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_AIRBRUSH)) + return; + + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_TOOL_AIRBRUSH, 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_AIRBRUSH); + + libinput_event_destroy(event); +} +END_TEST + +START_TEST(airbrush_wheel) +{ + 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 v; + + if (!libevdev_has_event_code(dev->evdev, + EV_KEY, + BTN_TOOL_AIRBRUSH)) + return; + + litest_drain_events(li); + + abs = libevdev_get_abs_info(dev->evdev, ABS_WHEEL); + ck_assert_notnull(abs); + + litest_event(dev, EV_KEY, BTN_TOOL_AIRBRUSH, 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_WHEEL, 10); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + + litest_drain_events(li); + + scale = abs->maximum - abs->minimum; + for (v = abs->minimum; v < abs->maximum; v += 8) { + litest_event(dev, EV_ABS, ABS_WHEEL, v); + 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_SLIDER)); + val = libinput_event_tablet_get_axis_value(tev, + LIBINPUT_TABLET_AXIS_SLIDER); + + ck_assert_int_eq(val, (v - abs->minimum)/scale); + libinput_event_destroy(event); + litest_assert_empty_queue(li); + } +} +END_TEST + int main(int argc, char **argv) { @@ -1296,6 +1382,8 @@ 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:airbrush", airbrush_tool, LITEST_TABLET, LITEST_ANY); + litest_add("tablet:airbrush", airbrush_wheel, LITEST_TABLET, LITEST_ANY); return litest_run(argc, argv); } diff --git a/tools/event-debug.c b/tools/event-debug.c index 3503143e..e3f7baa1 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -293,7 +293,7 @@ print_tablet_axis_event(struct libinput_event *ev) struct libinput_event_tablet *t = libinput_event_get_tablet_event(ev); double x, y; double dist, pressure; - double rotation; + double rotation, slider; print_event_time(libinput_event_tablet_get_time(t)); @@ -324,6 +324,12 @@ print_tablet_axis_event(struct libinput_event *ev) rotation, tablet_axis_changed_sym(t, LIBINPUT_TABLET_AXIS_ROTATION_Z)); + slider = libinput_event_tablet_get_axis_value(t, + LIBINPUT_TABLET_AXIS_SLIDER); + printf(" slider: %.2f%s", + slider, + tablet_axis_changed_sym(t, LIBINPUT_TABLET_AXIS_SLIDER)); + printf("\n"); }