mirror of
https://github.com/games-on-whales/inputtino.git
synced 2026-10-15 12:52:02 +00:00
[PR #47] [MERGED] fix(touch): don't reuse an active MT slot when placing a new finger #48
Labels
No labels
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
games-on-whales/inputtino#48
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/games-on-whales/inputtino/pull/47
Author: @c127dev
Created: 7/11/2026
Status: ✅ Merged
Merged: 7/13/2026
Merged by: @ABeltramo
Base:
stable← Head:fix/touchscreen-place-finger-overwritten📝 Commits (1)
309c68efix(touch): don't reuse an active MT slot when placing a new finger📊 Changes
4 files changed (+99 additions, -15 deletions)
View changed files
📝
src/uinput/include/inputtino/protected_types.hpp(+25 -2)📝
src/uinput/touchscreen.cpp(+16 -5)📝
src/uinput/trackpad.cpp(+16 -5)📝
tests/testLibinput.cpp(+42 -3)📄 Description
Problem
While streaming a game from Sunshine to an Android device with Moonlight (touch passthrough), multi-touch gestures would occasionally glitch: two distinct fingers were treated as the same contact. With two fingers down, lifting one and placing it again made both fingers share a single MT slot — their coordinates alternated inside one contact, so the remaining finger appeared to "teleport" between the two positions.
Root cause chain
Slot allocation (
TouchScreen::place_finger()/Trackpad::place_finger()): a new finger was assigned the slotfingers.size() + 1. This is only correct when fingers are released in reverse order of placement. Sequence that breaks it: place finger A → slot 1, place finger B → slot 2, release A (fingers.size()is now 1), place A again → slot1 + 1 = 2— the same slot finger B is still using. Twofinger_ids now map to one MT slot.Tracking ID reuse:
ABS_MT_TRACKING_IDwas set to the slot number itself. In the evdev MT protocol the tracking id must uniquely identify a contact for its lifetime; reusing slot numbers as tracking ids means a re-placed finger can resurrect the identity of a previous contact instead of starting a new one.current_slotdesync: when a new finger selected its slot viaABS_MT_SLOT,current_slotwas not updated, so a following event for another finger could skip theABS_MT_SLOTwrite and land in the wrong slot.release_finger()also resetcurrent_slotto-1after emittingABS_MT_SLOT, even though the kernel's slot state remained at the released slot.release_finger()on unknown ids: it used_state->fingers[finger_nr], so releasing a finger id that was never placed default-constructed an entry mapping it to slot 0 and emittedMT_TRACKING_ID = -1there — killing an unrelated active contact.Trackpadshared the exact same allocation logic, so it had the same bug.Fix
first_free_mt_slot()) instead offingers.size() + 1. As a side effect slots are now 0-based, matching the evdev convention.ABS_MT_TRACKING_ID(wrapping at 65536) instead of reusing the slot number, so every new contact has a unique identity.current_slotin sync: set it when a new contact selects its slot, and track the actual kernel slot state inrelease_finger()instead of resetting to-1.release_finger()now ignores unknown finger ids instead of implicitly mapping them to slot 0 and corrupting another contact.TouchScreenandTrackpad.Verified
tests/testLibinput.cppto cover the exact failure sequence: two fingers down, first one lifted and placed again — it must get its own free slot back (slot 0) while the second finger keeps being tracked in its own slot (slot 1). All libinput tests pass.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.