Reset stale touchpad contacts after interrupted input

This commit is contained in:
ajp_anton
2026-09-07 19:47:28 +00:00
parent a8d68238bd
commit 93607d749f
3 changed files with 58 additions and 6 deletions
+23 -5
View File
@@ -153,13 +153,18 @@ local function emit_action()
return true return true
end end
local function reset_contacts(state)
state.mode = "idle"
state.contacts = {}
state.anchor_slot = nil
state.candidate_slot = nil
state.candidate_anchor_x = nil
state.candidate_anchor_y = nil
end
local function reset_if_clear(state) local function reset_if_clear(state)
if contact_count(state, false) == 0 then if contact_count(state, false) == 0 then
state.mode = "idle" reset_contacts(state)
state.anchor_slot = nil
state.candidate_slot = nil
state.candidate_anchor_x = nil
state.candidate_anchor_y = nil
end end
end end
@@ -178,6 +183,12 @@ local function new_contact(state, slot, tracking_id, timestamp)
end end
local function handle_tracking_begin(device, state, tracking_id, timestamp) local function handle_tracking_begin(device, state, tracking_id, timestamp)
if state.contacts[state.source_slot] then
libinput:log_debug(
"touchpad-hold-tap: resetting stale contact state")
reset_contacts(state)
end
if state.mode == "candidate" then if state.mode == "candidate" then
restore_candidate(device, state, "extra contact") restore_candidate(device, state, "extra contact")
end end
@@ -361,6 +372,13 @@ local function handle_frame(device, frame, timestamp)
else else
modified = true modified = true
end end
elseif event.usage == evdev.BTN_TOUCH and event.value == 0 then
table.insert(output, event)
if contact_count(state, false) > 0 then
libinput:log_debug(
"touchpad-hold-tap: resetting empty touch state")
reset_contacts(state)
end
elseif tool_counts[event.usage] then elseif tool_counts[event.usage] then
if state.mode == "candidate" or override_tools then if state.mode == "candidate" or override_tools then
local desired = tool_counts[event.usage] == local desired = tool_counts[event.usage] ==
@@ -307,6 +307,37 @@ function tests.rejected_tap_does_not_poison_anchor()
up(device, 300000, 0, 0) up(device, 300000, 0, 0)
end end
function tests.empty_touch_state_clears_stale_contacts()
local device = new_device("touchpad")
-- A suspend may interrupt the stream without individual tracking-ID
-- releases. The following no-touch report must still reset the plugin.
down(device, 0, 1, 70, 1000, 1000, 1)
feed(device, 100000, {
event(evdev.BTN_TOUCH, 0),
event(evdev.BTN_TOOL_FINGER, 0),
})
down(device, 200000, 0, 71, 1000, 1000, 1)
down(device, 400000, 1, 72, 1400, 1000, 2)
up(device, 450000, 1, 1)
assert(action_count() == 1)
up(device, 500000, 0, 0)
end
function tests.reused_slot_clears_stale_contacts()
local device = new_device("touchpad")
down(device, 0, 0, 73, 1000, 1000, 1)
-- A new tracking ID in an occupied slot also proves that the previous
-- contact disappeared without a complete event sequence.
down(device, 200000, 0, 74, 1000, 1000, 1)
down(device, 400000, 1, 75, 1400, 1000, 2)
up(device, 450000, 1, 1)
assert(action_count() == 1)
up(device, 500000, 0, 0)
end
function tests.tap_while_moving_does_not_poison_anchor() function tests.tap_while_moving_does_not_poison_anchor()
if allow_moving_anchor then if allow_moving_anchor then
return return
+4 -1
View File
@@ -1,6 +1,6 @@
Name: touchpad-hold-tap Name: touchpad-hold-tap
Version: 0.1.0 Version: 0.1.0
Release: 9%{?dist} Release: 10%{?dist}
Summary: Hold-tap middle-click gesture for touchpads Summary: Hold-tap middle-click gesture for touchpads
License: MIT License: MIT
@@ -57,6 +57,9 @@ if [ "$1" -eq 0 ]; then
fi fi
%changelog %changelog
* Sat Sep 05 2026 fedora-tools contributors - 0.1.0-10
- Reset stale touch contacts after an interrupted input stream
* Sat Sep 05 2026 fedora-tools contributors - 0.1.0-9 * Sat Sep 05 2026 fedora-tools contributors - 0.1.0-9
- Separate minimum anchor age from the optional stationary period - Separate minimum anchor age from the optional stationary period
- Allow a held anchor to recover after rejected taps - Allow a held anchor to recover after rejected taps