mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-29 05:30:07 +01:00
tablet: support artpen rotation
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Stephen Chandler Paul <thatslyude@gmail.com>
This commit is contained in:
parent
0d87dd8121
commit
3407226804
4 changed files with 130 additions and 9 deletions
|
|
@ -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);
|
||||
|
|
@ -507,6 +521,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:
|
||||
|
|
@ -556,6 +574,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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue