diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index e28412eb..fded69e4 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -278,6 +278,11 @@ tablet_update_tool(struct tablet_dispatch *tablet, assert(tool != LIBINPUT_TOOL_NONE); if (enabled) { + if (tablet->current_tool.is_active) + evdev_log_bug_kernel(device, + "Tool directly switched from %d to %d", + tablet->current_tool.type, + tool); tablet->current_tool.type = tool; tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); tablet_unset_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); @@ -285,6 +290,8 @@ tablet_update_tool(struct tablet_dispatch *tablet, else if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) { tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); } + + tablet->current_tool.is_active = enabled; } static inline double @@ -2158,6 +2165,7 @@ tablet_init(struct tablet_dispatch *tablet, tablet->device = device; tablet->status = TABLET_NONE; tablet->current_tool.type = LIBINPUT_TOOL_NONE; + tablet->current_tool.is_active = false; list_init(&tablet->tool_list); if (tablet_reject_device(device)) diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 080546e0..0cf8efca 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -78,6 +78,8 @@ struct tablet_dispatch { enum libinput_tablet_tool_type type; uint32_t id; uint32_t serial; + + bool is_active; /* evdev protocol state */ } current_tool; uint32_t cursor_proximity_threshold; diff --git a/test/test-tablet.c b/test/test-tablet.c index 5c7edb7b..7ed3b00d 100644 --- a/test/test-tablet.c +++ b/test/test-tablet.c @@ -2684,6 +2684,48 @@ START_TEST(tool_in_prox_before_start) } END_TEST +static void tool_switch_warning(struct libinput *libinput, + enum libinput_log_priority priority, + const char *format, + va_list args) +{ + int *warning_triggered = (int*)libinput_get_user_data(libinput); + + if (priority == LIBINPUT_LOG_PRIORITY_ERROR && + strstr(format, "Tool directly switched")) + (*warning_triggered)++; +} + + +START_TEST(tool_direct_switch) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_DISTANCE, 10 }, + { ABS_PRESSURE, 0 }, + { -1, -1 } + }; + int warning_triggered = 0; + + if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER)) + return; + + libinput_set_user_data(li, &warning_triggered); + libinput_log_set_handler(li, tool_switch_warning); + + litest_tablet_proximity_in(dev, 10, 10, axes); + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + ck_assert_int_eq(warning_triggered, 1); + litest_restore_log_handler(li); +} +END_TEST + START_TEST(mouse_tool) { struct litest_device *dev = litest_current_device(); @@ -4952,6 +4994,7 @@ TEST_COLLECTION(tablet) litest_add_no_device("tablet:tool", tool_capabilities); litest_add("tablet:tool", tool_type, LITEST_TABLET, LITEST_ANY); litest_add("tablet:tool", tool_in_prox_before_start, LITEST_TABLET, LITEST_ANY); + litest_add("tablet:tool", tool_direct_switch, LITEST_TABLET, LITEST_ANY); litest_add("tablet:tool_serial", tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add("tablet:tool_serial", tool_id, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);