Dispatch browse mode alt+arrow gestures between collapse or expand and sentence navigation - #20751
Dispatch browse mode alt+arrow gestures between collapse or expand and sentence navigation#20751LeonarddeR wants to merge 4 commits into
Conversation
720118c to
0b60882
Compare
…d sentence navigation alt+upArrow and alt+downArrow now run script_moveBySentence_back/forward, which collapse or expand the focusable control at the caret when it takes these keys itself and navigate by sentence otherwise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0b60882 to
20c19ce
Compare
There was a problem hiding this comment.
Pull request overview
This PR resolves a long-standing key gesture conflict in browse mode so alt+upArrow / alt+downArrow can perform sentence navigation in document content while still allowing interactive controls (e.g. comboboxes/popups) to use those keys for collapse/expand behavior.
Changes:
- Adds browse mode dispatch logic (
_isExpandableControlAtCaret+getAlternativeScript) to choose between sentence navigation and collapse/expand at gesture resolution time. - Improves sentence navigation scripts in
cursorManagerby handling missing sentence support (NotImplementedError) with a consistent user-facing message. - Updates user documentation and changelog, and adds unit tests for the browse mode dispatch decision.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| user_docs/en/userGuide.md | Updates sentence navigation documentation and “say all reads by” wording to reflect broader availability. |
| user_docs/en/changes.md | Adds a changelog entry for expanded sentence navigation support. |
| tests/unit/test_browseModeSentenceDispatch.py | Adds unit coverage for the new browse mode sentence-vs-collapse/expand dispatch logic. |
| source/NVDAObjects/UIA/wordDocument.py | Generalizes the translator comment to match the new cross-document messaging. |
| source/cursorManager.py | Routes sentence scripts through a helper that reports unsupported documents consistently. |
| source/browseMode.py | Implements browse mode alternative-script dispatch and removes the conflicting fixed gesture bindings. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if ( | ||
| not self.passThrough | ||
| and script | ||
| in ( | ||
| self.script_moveBySentence_back, | ||
| self.script_moveBySentence_forward, | ||
| ) | ||
| and self._isExpandableControlAtCaret() | ||
| ): | ||
| return self.script_collapseOrExpandControl | ||
| return super().getAlternativeScript(gesture, script) |
There was a problem hiding this comment.
I don't think this is possible without hacking. Because the script_moveBySentence scripts don't have descriptions, they can't be rebound from NVDA's input gestures dialog. Of course someone can hack in gestures.ini by hand, but he could also have done that for the previous script in current master.
# Conflicts: # source/browseMode.py
Qchristensen
left a comment
There was a problem hiding this comment.
User Guide changes read well. I like Sean's second option for line 791/2 but either is fine.
Link to issue number:
Part of #18901.
Follow up for #20603.
Supersedes #16384.
Summary of the issue:
NVDA binds
alt+upArrowandalt+downArrowto sentence navigation commands. Browse mode inherits these commands from the cursor manager. Browse mode also bound the same keys to the command that collapses or expands the current control. Bindings from more derived classes win, so the collapse or expand binding shadowed the sentence commands. Sentence navigation was therefore unreachable in browse mode, even with the working backend added in #20603.Description of user facing changes:
In browse mode,
alt+upArrowandalt+downArrownow move the caret by sentence in document content. Controls that use these keys themselves keep the old behaviour: they still collapse or expand. This covers comboboxes and other controls that are collapsed, expanded, have a popup, or offer autocompletion. Where a document does not support sentences at all, NVDA now says so rather than doing nothing. Microsoft Word already reported this, and the same message is now used everywhere. The user guide no longer limits sentence navigation to Word and Outlook. A changelog entry is added.Description of developer facing changes:
BrowseModeDocumentTreeInterceptoroverridesgetAlternativeScript. It returnsscript_collapseOrExpandControlin place of the sentence script when a control at the caret takes these keys itself. A new helper,_isExpandableControlAtCaret, makes that decision. The two static gesture bindings tocollapseOrExpandControlare removed. The sentence scripts themselves are not overridden. Instead the ones incursorManagerroute through a new_moveBySentence_scriptHelper. It catches aNotImplementedErrorfrom the text info and reports it, reusing the message Microsoft Word already shows. Every cursor manager gains this, not only browse mode. This also has the advantage that PowerPoint slideshows no longer raise NotImplementedError when pressing sentence navigation gestures.Description of development approach:
The keys are no longer bound to one fixed command. Instead the choice is made while NVDA is still working out which command a key press belongs to. Browse mode already has a hook for that, used today for single letter navigation. The hook looks at the focusable control at the caret. That is the same object the collapse or expand script acts on. If that control takes these keys itself, the hook hands the key to the collapse or expand command. Otherwise the sentence command runs unchanged. Choosing this early means the command NVDA reports is the command that runs. It also means only sentence navigation resumes say all. In documents without sentence support, the keys say so instead of raising an error. The SentenceNav add-on resolves the same conflict in the same way.
Comparison with the earlier attempt in #16384:
Sentence navigation was attempted before in #16384 by @mltony. It was closed in September 2024 because it had stalled, not because the approach was rejected.
That work found sentence boundaries with a regular expression. It carried a list of non-breaking prefixes, so that abbreviations did not end a sentence. Users could edit that list per language from the Document Navigation panel. During review, a stale value of such an expression in an existing configuration file made sentence navigation raise an error. Reviewers also asked whether a prefix list can be maintained for every language and every language variant.
This work asks the Windows built-in ICU library for the boundaries instead. The rules come from the Unicode standard and are the same for every language. There is nothing to configure, so nothing can be misconfigured, and no language needs its own list. The cost is that an abbreviation such as "Dr." ends a sentence. Only locale specific tailoring avoids that, which is left for later.
#16384 also allowed a sentence to span several paragraphs, with a setting to choose how far it may reach. This work segments within the containing paragraph only.
#16384 changed browse mode, offsets based TextInfos, UIA TextInfos and editable text controls in one pull request. This work is split. The backend landed in #20603. This pull request only routes the browse mode gestures. One thing from #16384 is not carried over: a command to speak the current sentence in an editable text control.
Both resolve the same gesture conflict, but at different moments. #16384 made the choice inside the collapse or expand command. That command therefore ran even when the caret moved by sentence, so its description and its say all behaviour applied to both outcomes. This pull request makes the choice before a command is picked, so the command that runs is the command that acts. The object tested is the one the collapse or expand script acts on. The test also covers autocomplete fields and controls with a popup, which #16384 did not.
Testing strategy:
New unit tests cover the decision helper. Controls such as comboboxes, sliders, autocomplete fields, and collapsed controls keep collapse or expand. Plain content, links, and buttons fall through to sentence navigation. The binding order was also checked to confirm the sentence scripts now receive the keys. Manual verification in Firefox, Chrome and Word browse mode confirmed that plain text moves by sentence and (for browsers) that comboboxes still collapse or expand.
Known issues with pull request:
The current approach binds alt+upArrow and alt+downArrow to two different outcomes. Personally I don't think this is ideal, but I have no idea how to do this elsewhere and this wasn't a show stopper in #16384
Code Review Checklist: