Files
jasonwitty ec9a9a8892 Capture a contact's start position per axis, not with a (0,0) sentinel
Every swipe on the rack display classified as up-to-down. The first one took
the display from the top row to the bottom row, and from there "down" is a
no-op, so it was stuck permanently -- looking like dead gestures while the
process was alive and the panel still grabbed.

X and Y arrive as SEPARATE events, so a new contact's opening frame is
ABS_MT_POSITION_X then ABS_MT_POSITION_Y. Treating (0, 0) as "start not yet
known" meant the start was captured on the X event alone, recording a Y of
zero. Every later comparison then measured from the top edge of the panel
rather than from the finger: dy became the absolute Y coordinate, dwarfed dx,
and the gesture came out vertical. A swipe at y=360 on a 720-tall panel
reported 360 pixels of downward travel that never happened.

The start position is now Option per axis. An axis that never reports
contributes no displacement, so there is no sentinel to collide with a real
coordinate.

The slot bookkeeping moves into a SlotTracker fed by a small Touched enum
rather than evdev's types, because it was untestable before and that is exactly
where the bug lived -- the existing classifier tests built Track tuples by hand
and skipped the decoding entirely. Six new tests drive realistic protocol-B
streams: the regression itself, per-axis start capture, all four directions
end to end, ghost contacts decoding as one swipe of the correct length,
completion only once every contact lifts, and reset between gestures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 13:48:37 -07:00
..