nvda
dd9efcac - Add sequential two-flick touch gestures (#20086)

Commit
70 days ago
Add sequential two-flick touch gestures (#20086) #19938 Summary of the issue: This is the second of 3 PRs to address the above issue. Adds twelve sequential two-flick gestures (opposite-direction and perpendicular L-shaped pairs) that can be bound to scripts. The two flicks may be performed either by lifting the finger between strokes or as a single continuous swipe with a sharp change in direction. Description of user facing changes: Touch screen users can now perform two flicks in quick succession to trigger a sequential flick gesture. This expands the number of touch gestures that can be assigned to NVDA commands. Twelve combinations are recognised: • Four opposite-direction pairs: flick right then left, flick left then right, flick up then down, flick down then up. • Eight perpendicular L-shaped pairs: flick right then up, flick right then down, flick left then up, flick left then down, flick up then right, flick up then left, flick down then right, flick down then left. The two flicks can be performed either by lifting the finger between strokes (within the multi-touch timeout) or as a single continuous swipe that sharply changes direction. Description of developer facing changes: • Twelve new action_flickThen constants in touchTracker, with translatable labels in actionLabels. • SingleTouchTracker now records peakX/peakY (farthest point reached on each axis) and a rolling window of recent samples for velocity calculation. getVelocity() returns velocity in pixels per second using least-squares linear regression. • SingleTouchTracker.update() now uses velocity direction rather than total displacement direction to classify flicks, so late-stroke direction changes are reflected correctly. • TrackerManager._checkContinuousFlick() detects a direction change without a finger lift; when the finger has moved far enough away from its peak, the first flick is queued and the tracker is reset to track the return stroke as the second gesture. • TouchHandler.pump() now combines two matching flicks that arrive in the same pump cycle into a single sequential gesture using _flickSequenceMap. Single flicks that aren't followed by a second flick still fire immediately at end of cycle, so normal flick latency is unchanged. • New tunables in touchTracker: minFlickVelocity (100 px/s), continuousFlickTimeout (0.6 s), _VELOCITY_SAMPLE_WINDOW (0.1 s). Description of development approach: The detection is split between the two layers that already existed: • The low-level layer (touchTracker) classifies a single finger as a flick using velocity direction and detects mid-swipe direction changes. The first flick of a continuous gesture is emitted as soon as the second stroke begins; the tracker is then reset so the return stroke is classified independently. • The high-level layer (touchHandler.pump) combines two flicks emitted in the same pump cycle into a compound action. This is a local pump-cycle decision — no timer, no cross-pump buffering — so a single flick fires immediately at end of cycle without waiting for a possible second flick. This keeps single-flick latency unchanged while still allowing sequential flicks to be detected reliably.
Author
Parents
Loading