Block touch input while the magnifier is running#20357
Conversation
|
@Boumtchack this approach will not work. Disabling NVDA's touch support does *NOT disable touchscreen input, it simply disables NVDA's processing of touch events. Arguably this makes the situation worse, as touching the screen in this state will silently perform actions. While we have no way of preventing this in portable copies (we can't intercept touch inputs in portables), we already intercept all touch events when touch support is enabled in installed copies. What we need to do is continue to block touch inputs but alert the user that touch support is unavailable. Of course, if NVDA's touch support is disabled, or NVDA is running from source, portable, or (I think) without UI access, we still need to pop up a dialog alerting the user that the touch screen will not behave as expected while the magnifier is running. |
|
@SaschaCowley - can you check the approach now? |
SaschaCowley
left a comment
There was a problem hiding this comment.
I think the logic is flawed, but this is the right direction.
|
Please change the title of this PR to avoid confusion. |
|
how would you change the title? it seems ok to me |
|
For example: “Block touch input while the magnifier is running”? |
There was a problem hiding this comment.
Pull request overview
This PR aims to prevent mis-mapped touchscreen behavior while NVDA’s magnifier is active by blocking NVDA touch gesture execution when touch interception is available, and warning the user when interception isn’t possible (portable/source/no UI access scenarios).
Changes:
- Add a
touchHandler.blockTouchInputflag and skip gesture execution inTouchHandler.pump()while the flag is set. - Update magnifier start/stop logic to enable/disable touch blocking, or show a warning dialog when touch input can’t be intercepted.
- Add/adjust unit tests covering magnifier + touchscreen interactions.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| tests/unit/test_magnifier/test_magnifierTouchscreen.py | New unit tests for touch blocking / warning behavior when magnifier starts/stops. |
| tests/unit/test_magnifier/test_magnifier.py | Test setup/teardown adjustments and focus coordinate mocking to support magnifier behavior in tests. |
| source/touchHandler.py | Add global blockTouchInput and block gesture execution (with feedback) during pump. |
| source/_magnifier/magnifier.py | Toggle touch blocking on magnifier start/stop; warn when touch interception isn’t available. |
| reason = pgettext( | ||
| "magnifier", | ||
| # Translators: Warning when the magnifier starts on a portable/source copy with a touchscreen. | ||
| "Touch screen input cannot be used because NVDA is not installed. ", | ||
| ) |
There was a problem hiding this comment.
| reason = pgettext( | |
| "magnifier", | |
| # Translators: Warning when the magnifier starts on a portable/source copy with a touchscreen. | |
| "Touch screen input cannot be used because NVDA is not installed. ", | |
| ) | |
| reason = pgettext( | |
| "magnifier", | |
| # Translators: Warning when the magnifier starts on a portable/source copy with a touchscreen. | |
| "Touch screen input is not supported in this version of NVDA. ", | |
| ) |
| self._stopTimer() | ||
| self._isActive = False | ||
| if touchHandler.handler is not None: | ||
| touchHandler.blockTouchInput = False |
| for preheldTracker, tracker in self.trackerManager.emitTrackers(): | ||
| if blockTouchInput: | ||
| winsound.MessageBeep(winsound.MB_ICONASTERISK) | ||
| continue |
There was a problem hiding this comment.
Yes I think this might be too noisy.
There was a problem hiding this comment.
| for preheldTracker, tracker in self.trackerManager.emitTrackers(): | |
| if blockTouchInput: | |
| winsound.MessageBeep(winsound.MB_ICONASTERISK) | |
| continue | |
| if blockTouchInput: | |
| winsound.MessageBeep(winsound.MB_ICONASTERISK) | |
| return | |
| for preheldTracker, tracker in self.trackerManager.emitTrackers(): |
| def testStopMagnifierUnblocksTouchInput(self): | ||
| """blockTouchInput is reset to False when the magnifier stops with the touch handler active.""" | ||
| self.magnifier._stopTimer = MagicMock() | ||
| self.magnifier._isActive = True | ||
| touchHandler.blockTouchInput = True | ||
| self.addCleanup(setattr, touchHandler, "blockTouchInput", False) | ||
|
|
||
| with patch("touchHandler.handler", new=MagicMock()): | ||
| self.magnifier._stopMagnifier() | ||
|
|
||
| self.assertFalse(touchHandler.blockTouchInput) |
| "magnifier", | ||
| # Translators: Warning when magnifier is started on a device with a touch screen but NVDA's touch support is disabled. | ||
| "Touch screen input cannot be used because NVDA touch support is disabled. ", | ||
| ) |
There was a problem hiding this comment.
wouldn't this message also appear if touch support is enabled?
also maybe I missed it but do we have a warning message for when we block touch input
Link to issue number:
Closes #20038
Summary of the issue:
Touch screen input causes incorrect mappings when the NVDA magnifier is running. Touch input must be disabled while the magnifier is active to prevent this conflict.
Description of user facing changes:
On installed copies of NVDA, touch gestures are silently blocked while the magnifier is running. An earcon plays on each blocked gesture so the user knows the touch was received but suppressed. On portable copies, copies running from source, or without UI access, a warning dialog appears when the magnifier starts to inform the user that touch input cannot be intercepted and may not behave as expected.
Description of developer facing changes:
A blockTouchInput: bool flag is added to touchHandler. In TouchHandler.pump(), when the flag is True, gestures are skipped and an earcon is played instead of executing the gesture. Magnifier._startMagnifier sets touchHandler.blockTouchInput = True if the handler is active, or schedules a gui.messageBox warning via wx.CallAfter otherwise. Magnifier._stopMagnifier unconditionally resets the flag to False.
Description of development approach:
Keeps the touch handler running and blocks only at the gesture execution layer in pump(), which runs on the main thread and avoids any threading concerns with audio feedback.
Testing strategy:
unit
Known issues with pull request:
Code Review Checklist: