plugin: always disable wheel debouncing on request

The WHEEL_STATE_NONE check was effectively always false:
- if we didn't receive any event yet, wheel_maybe_disable() wasn't
  called in any code path
- if we did receive a scroll event, the wheel state was either
  WHEEL_STATE_SCROLLING or WHEEL_STATE_ACCUMULATING_SCROLL

Fix this two-pronged: remove the check for WHEEL_STATE_NONE but also
immediately call disable when we disable the feature. We don't carry
enough state in this plugin to really worry about the device being in
a fully neutral state (and realistically the vast majority of use-cases
will likely disable wheel debouncing on new device anyway).

Closes #1241

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1408>
This commit is contained in:
Peter Hutterer 2026-01-13 12:34:41 +10:00 committed by Marge Bot
parent 005a3e5622
commit 6b4d1905b6
2 changed files with 62 additions and 6 deletions

View file

@ -147,9 +147,6 @@ wheel_cancel_scroll_timer(struct plugin_device *pd)
static inline void
wheel_maybe_disable(struct plugin_device *device)
{
if (device->state != WHEEL_STATE_NONE)
return;
if (device->want_feature_disabled) {
plugin_log_debug(device->parent->plugin,
"%s: disabled wheel debouncing on request\n",
@ -157,9 +154,11 @@ wheel_maybe_disable(struct plugin_device *device)
libinput_plugin_enable_device_event_frame(device->parent->plugin,
device->device,
false);
libinput_plugin_timer_cancel(device->scroll_timer);
device->scroll_timer =
libinput_plugin_timer_unref(device->scroll_timer);
if (device->scroll_timer) {
libinput_plugin_timer_cancel(device->scroll_timer);
device->scroll_timer =
libinput_plugin_timer_unref(device->scroll_timer);
}
}
}
@ -626,6 +625,7 @@ wheel_plugin_feature_disabled(struct libinput_plugin *libinput_plugin,
list_for_each(pd, &plugin->devices, link) {
if (pd->device == device) {
pd->want_feature_disabled = true;
wheel_maybe_disable(pd);
return;
}
}

View file

@ -1048,6 +1048,61 @@ START_TEST(lua_disable_touchpad_jump_detection)
}
END_TEST
START_TEST(lua_disable_wheel_debouncing)
{
enum when when = litest_test_param_get_i32(test_env->params, "when");
_destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
_autofree_ char *lua = strdup_printf(
"libinput:register({1})\n"
"function frame_handler(device, _, _)\n"
" device:disable_feature(\"wheel-debouncing\")\n"
"end\n"
"function new_device(device)\n"
" %s device:disable_feature(\"wheel-debouncing\")\n"
" %s device:connect(\"evdev-frame\", frame_handler)\n"
"end\n"
"libinput:connect(\"new-evdev-device\", new_device)\n",
when == DEVICE_NEW ? "" : "--",
when == FIRST_FRAME ? "" : "--");
_autofree_ char *path = litest_write_plugin(tmpdir->path, lua);
_litest_context_destroy_ struct libinput *li =
litest_create_context_with_plugindir(tmpdir->path);
if (libinput_log_get_priority(li) > LIBINPUT_LOG_PRIORITY_DEBUG)
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
litest_with_logcapture(li, capture) {
libinput_plugin_system_load_plugins(li,
LIBINPUT_PLUGIN_SYSTEM_FLAG_NONE);
_destroy_(litest_device) *dev = litest_add_device(li, LITEST_MOUSE);
litest_drain_events(li);
for (size_t i = 0; i < 4; i++) {
/* Send a small wheel events - when debouncing is disabled, they
* should all be delivered immediately without delay */
litest_event(dev, EV_REL, REL_WHEEL_HI_RES, 10);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
litest_dispatch(li);
_destroy_(libinput_event) *ev = libinput_get_event(li);
auto ptrev = litest_is_axis_event(
ev,
LIBINPUT_EVENT_POINTER_SCROLL_WHEEL,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
0);
double v120 = libinput_event_pointer_get_scroll_value_v120(
ptrev,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
litest_assert_double_eq(v120, -10);
}
litest_assert_empty_queue(li);
litest_assert_strv_substring(capture->debugs,
"disabled wheel debouncing on request");
}
}
END_TEST
TEST_COLLECTION(lua)
{
/* clang-format off */
@ -1119,6 +1174,7 @@ TEST_COLLECTION(lua)
litest_named_i32(FIRST_FRAME)) {
litest_add_parametrized_no_device(lua_disable_button_debounce, params);
litest_add_parametrized_no_device(lua_disable_touchpad_jump_detection, params);
litest_add_parametrized_no_device(lua_disable_wheel_debouncing, params);
}
/* clang-format on */
}