tablet: only apply eraser button settings if we have a device

If the device is unplugged, our tool's last_device is NULL. If a caller
then tries to the toggle the eraser button setting libinput would crash.
Fix this by simply skipping the configuration until the tool goes back
into proximity over some other device (if any).

Closes #1223

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1370>
This commit is contained in:
Peter Hutterer 2025-11-26 10:33:38 +10:00
parent a6ad084280
commit 1e8901d009
2 changed files with 53 additions and 3 deletions

View file

@ -1272,11 +1272,14 @@ static void
eraser_button_toggle(struct libinput_tablet_tool *tool)
{
struct libinput_device *libinput_device = tool->last_device;
if (libinput_device) {
struct evdev_device *device = evdev_device(libinput_device);
struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
tablet_tool_apply_eraser_button(tablet, tool);
}
}
static enum libinput_config_status
eraser_button_set_mode(struct libinput_tablet_tool *tool,

View file

@ -7722,6 +7722,51 @@ START_TEST(tablet_eraser_button_disabled)
}
END_TEST
START_TEST(tablet_eraser_button_config_after_device_removal)
{
_litest_context_destroy_ struct libinput *li = litest_create_context();
struct litest_device *tablet = litest_add_device(li, LITEST_ELAN_TABLET);
struct axis_replacement axes[] = {
{ ABS_DISTANCE, 10 },
{ ABS_PRESSURE, 0 },
{ -1, -1 },
};
litest_drain_events(li);
litest_tablet_set_tool_type(tablet, BTN_TOOL_RUBBER);
litest_tablet_proximity_in(tablet, 10, 10, axes);
litest_dispatch(li);
auto event = libinput_get_event(li);
auto tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
auto tool = libinput_event_tablet_tool_get_tool(tev);
libinput_tablet_tool_ref(tool);
libinput_event_destroy(event);
litest_device_destroy(tablet);
litest_drain_events(li);
/* Tool isn't associated with a device but config should take effect anyway */
auto status = libinput_tablet_tool_config_eraser_button_set_mode(
tool,
LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
status =
libinput_tablet_tool_config_eraser_button_set_button(tool, BTN_STYLUS2);
litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
litest_assert_enum_eq(libinput_tablet_tool_config_eraser_button_get_mode(tool),
LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
litest_assert_int_eq(libinput_tablet_tool_config_eraser_button_get_button(tool),
(unsigned)BTN_STYLUS2);
litest_drain_events(li);
libinput_tablet_tool_unref(tool);
}
END_TEST
TEST_COLLECTION(tablet)
{
/* clang-format off */
@ -7886,6 +7931,8 @@ TEST_COLLECTION(tablet_eraser)
"with-motion-events", 'b') {
litest_add_parametrized(tablet_eraser_button_disabled, LITEST_TABLET, LITEST_TOTEM|LITEST_FORCED_PROXOUT, params);
}
litest_add_no_device(tablet_eraser_button_config_after_device_removal);
/* clang-format on */
}