Added edge gestures: a set of gestures that only work at the edge of the screen (#20551)
closes #19938
Summary of the issue:
As discussed in #19938, NVDA needs more gestures. This is the 3rd and final PR in that issue to address that gap. For this PR, we've created a way to distinguish gestures that begin near the screen edge, so those edge regions can serve as additional gesture space.
Description of user facing changes:
A new "Enable edge gestures" checkbox has been added to the Touch Interaction settings panel (disabled by default).
When enabled, gestures that begin within 15 mm of any screen edge are recognized as distinct gestures (e.g. "left edge flick right") and can be bound independently in the Input Gestures dialog.
I wanted to use 5 mm as suggested by @SaschaCowley but it was too small, I couldn't use more than one finger.
All four edges are supported. Note that the Windows taskbar may override gestures on an edge; gestures from the taskbar edge open the Start menu or Action Center and NVDA will not receive them.
Description of developer facing changes:
Added TouchEdge DisplayStringStrEnum to touchTracker for identifying and labelling edge regions (values: left, right, top, bottom).
Added _EDGE_MARGIN_MM = 15.0 constant to touchTracker; the pixel margin is computed at call time using GetDeviceCaps(LOGPIXELSX) for DPI awareness.
Added _getEdge(x, y) helper in touchHandler that returns the edge identifier or None, and respects the edgeGestures config key.
TouchInputGesture._get_identifiers() now inserts the edge prefix (e.g. left_) before the action name when the touch origin falls within an edge region.
TouchInputGesture.getDisplayTextForIdentifier() resolves edge labels from the TouchEdge enum for display in the Input Gestures dialog.
New config key: [touch] edgeGestures = boolean(default=False).
Description of development approach:
Edge detection runs at gesture-identifier generation time using the tracker's starting x/y coordinates. The margin is converted from millimetres to pixels at call time using the screen DPI retrieved via GetDeviceCaps(LOGPIXELSX), ensuring the physical margin is consistent across displays of different resolutions and pixel densities. When an edge is detected, the edge name is prepended to the action in the gesture identifier (e.g. ts(object):left_flickright), keeping the format compatible with the existing gesture binding infrastructure and requiring no changes to the gesture map lookup logic.