From 941aa9f99757a00d4ac36189646d1d6ada2d543f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 3 Nov 2025 16:39:35 +1000 Subject: [PATCH] plugins: add an example for using a wheel to trigger button scrolling See https://gitlab.freedesktop.org/libinput/libinput/-/issues/1206 Part-of: --- plugins/10-wheel-to-button.lua | 64 ++++++++++++++++++++++++++++++++++ plugins/meson.build | 1 + 2 files changed, 65 insertions(+) create mode 100644 plugins/10-wheel-to-button.lua diff --git a/plugins/10-wheel-to-button.lua b/plugins/10-wheel-to-button.lua new file mode 100644 index 00000000..f6d3623b --- /dev/null +++ b/plugins/10-wheel-to-button.lua @@ -0,0 +1,64 @@ +-- SPDX-License-Identifier: MIT +-- +-- This is an example libinput plugin +-- +-- This plugin maps a downwards mouse wheel to a button down event and +-- an upwards wheel movement to a button up event. + +-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN +-- libinput:register({1}) + +-- The button we want to press on wheel events +local wheel_button = evdev.BTN_EXTRA +local button_states = {} + +local function evdev_frame(device, frame, timestamp) + local events = {} + local modified = false + + for _, v in ipairs(frame) do + if v.usage == evdev.REL_WHEEL then + -- REL_WHEEL is inverted, neg value -> down, pos value -> up + if v.value < 0 then + if not button_states[device] then + table.insert(events, { usage = wheel_button, value = 1 }) + button_states[device] = true + end + else + if button_states[device] then + table.insert(events, { usage = wheel_button, value = 0 }) + button_states[device] = false + end + end + modified = true + -- Because REL_WHEEL is no longer a wheel, the high-res + -- events are dropped + elseif v.usage == evdev.REL_WHEEL_HI_RES then + modified = true + else + table.insert(events, v) + end + end + + if modified then + return events + else + return nil + end +end + +local function device_new(device) + local usages = device:usages() + if usages[evdev.REL_WHEEL] then + button_states[device] = false + if not usages[wheel_button] then + device:enable_evdev_usage(wheel_button) + end + device:connect("evdev-frame", evdev_frame) + device:connect("device-removed", function(dev) + button_states[dev] = nil + end) + end +end + +libinput:connect("new-evdev-device", device_new) diff --git a/plugins/meson.build b/plugins/meson.build index b502bce8..f559ff4e 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -7,6 +7,7 @@ plugins = [ '10-delay-motion.lua', '10-disable-feature.lua', '10-copilot-key-override.lua', + '10-wheel-to-button.lua', ] fs = import('fs')