From 8bb53150a994acf65925ce091dd8b9619a74e43a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 23 Jan 2024 20:09:04 +1000 Subject: [PATCH] tablet: handle BTN_STYLUS3 And add a test to make sure the tool we know that has three buttons (Pro Pen 3) can send all those. Enough to run that test one one compatible device, no real benefit of running it on all tablet devices. --- src/evdev-tablet.c | 4 ++++ test/test-tablet.c | 59 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 3f976ffb..e42bd5fe 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -773,6 +773,7 @@ tablet_update_button(struct tablet_dispatch *tablet, case BTN_TASK: case BTN_STYLUS: case BTN_STYLUS2: + case BTN_STYLUS3: break; default: evdev_log_info(tablet->device, @@ -958,6 +959,8 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet, code++) copy_button_cap(tablet, tool, code); } else { + if (libwacom_stylus_get_num_buttons(s) >= 3) + copy_button_cap(tablet, tool, BTN_STYLUS3); if (libwacom_stylus_get_num_buttons(s) >= 2) copy_button_cap(tablet, tool, BTN_STYLUS2); if (libwacom_stylus_get_num_buttons(s) >= 1) @@ -1057,6 +1060,7 @@ tool_set_bits(const struct tablet_dispatch *tablet, case LIBINPUT_TABLET_TOOL_TYPE_ERASER: copy_button_cap(tablet, tool, BTN_STYLUS); copy_button_cap(tablet, tool, BTN_STYLUS2); + copy_button_cap(tablet, tool, BTN_STYLUS3); break; case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: case LIBINPUT_TABLET_TOOL_TYPE_LENS: diff --git a/test/test-tablet.c b/test/test-tablet.c index 743b9e9b..15a8c648 100644 --- a/test/test-tablet.c +++ b/test/test-tablet.c @@ -1097,12 +1097,12 @@ START_TEST(proximity_out_clear_buttons) struct libinput *li = dev->libinput; struct libinput_event_tablet_tool *tablet_event; struct libinput_event *event; - uint32_t button; struct axis_replacement axes[] = { { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { -1, -1 } }; + uint32_t stylus_buttons[] = {BTN_STYLUS, BTN_STYLUS2, BTN_STYLUS3}; bool have_proximity = false; double x = 50, y = 50; @@ -1111,18 +1111,18 @@ START_TEST(proximity_out_clear_buttons) /* Test that proximity out events send button releases for any currently * pressed stylus buttons */ - for (button = BTN_STYLUS; button <= BTN_STYLUS2; button++) { + ARRAY_FOR_EACH(stylus_buttons, button) { bool button_released = false; uint32_t event_button = 0; enum libinput_button_state state; - if (!libevdev_has_event_code(dev->evdev, EV_KEY, button)) + if (!libevdev_has_event_code(dev->evdev, EV_KEY, *button)) continue; litest_tablet_proximity_in(dev, x++, y++, axes); litest_drain_events(li); - litest_event(dev, EV_KEY, button, 1); + litest_event(dev, EV_KEY, *button, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_tablet_proximity_out(dev); libinput_dispatch(li); @@ -1145,7 +1145,7 @@ START_TEST(proximity_out_clear_buttons) event_button = libinput_event_tablet_tool_get_button(tablet_event); state = libinput_event_tablet_tool_get_button_state(tablet_event); - if (event_button == button && + if (event_button == *button && state == LIBINPUT_BUTTON_STATE_RELEASED) button_released = true; } @@ -1155,7 +1155,7 @@ START_TEST(proximity_out_clear_buttons) ck_assert_msg(button_released, "Button %s (%d) was not released.", - libevdev_event_code_get_name(EV_KEY, button), + libevdev_event_code_get_name(EV_KEY, *button), event_button); litest_assert(have_proximity); litest_assert_empty_queue(li); @@ -3166,6 +3166,52 @@ START_TEST(tool_direct_switch_with_forced_proxout) } END_TEST +START_TEST(stylus_buttons) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_tablet_tool *tev; + struct libinput_tablet_tool *tool; + uint32_t stylus_buttons[] = {BTN_STYLUS, BTN_STYLUS2, BTN_STYLUS3}; + + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1); + litest_event(dev, EV_ABS, ABS_MISC, 0x200); /* 3-button stylus tool_id */ + litest_event(dev, EV_MSC, MSC_SERIAL, 1000); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + event = libinput_get_event(li); + tev = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY); + tool = libinput_event_tablet_tool_get_tool(tev); + ck_assert_notnull(tool); + libinput_tablet_tool_ref(tool); + + libinput_event_destroy(event); + + ARRAY_FOR_EACH(stylus_buttons, code) { + litest_event(dev, EV_KEY, *code, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + litest_event(dev, EV_KEY, *code, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + litest_assert_tablet_button_event(li, + *code, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_tablet_button_event(li, + *code, + LIBINPUT_BUTTON_STATE_RELEASED); + } + + libinput_tablet_tool_unref(tool); +} +END_TEST + START_TEST(mouse_tool) { struct litest_device *dev = litest_current_device(); @@ -6176,6 +6222,7 @@ TEST_COLLECTION(tablet) litest_add_for_device(left_handed_artpen_rotation, LITEST_WACOM_INTUOS); litest_add_for_device(no_left_handed, LITEST_WACOM_CINTIQ); litest_add(pad_buttons_ignored, LITEST_TABLET, LITEST_TOTEM); + litest_add_for_device(stylus_buttons, LITEST_WACOM_CINTIQ_PRO16_PEN); litest_add(mouse_tool, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); litest_add(mouse_buttons, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); litest_add(mouse_rotation, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);