Use NVDA 2026.3's injected flag for the client caps lock veto - #81
Open
LeonarddeR wants to merge 4 commits into
Open
Use NVDA 2026.3's injected flag for the client caps lock veto#81LeonarddeR wants to merge 4 commits into
LeonarddeR wants to merge 4 commits into
Conversation
The client now swallows software-generated caps lock key events through inputCore.decide_handleRawKey, which NVDA 2026.3 supplies with the injected flag, instead of vetoing the bypassed caps lock gesture behind a full screen window heuristic. The client side of the synchronization requires NVDA 2026.3; the server side keeps working on every supported version. Bump the add-on version to 2.0.3. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvK8A5MrcwxdM5Y6aCdWLc
NVDA 2026.3 builds from before the injected flag was added call raw key handlers without it. Default the parameter to None so the veto degrades to pass-through there instead of raising on every key event. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvK8A5MrcwxdM5Y6aCdWLc
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The new raw-key handler’s decide signature should explicitly accept the raw-key kwargs NVDA/Decider may pass (e.g., scanCode, pressed) to avoid runtime incompatibility and align with the new test harness.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This pull request updates RDAccess’s client-side Caps Lock synchronization to rely on NVDA 2026.3’s new raw-key injected flag, allowing the add-on to reliably suppress remote-desktop “fed back” Caps Lock events without guessing based on fullscreen window geometry.
Changes:
- Add
InjectedCapsLockVetoand register it oninputCore.decide_handleRawKey(NVDA 2026.3+) to swallow software-injected Caps Lock events from focused remote desktop clients. - Introduce
nvdaCompat.CAPS_LOCK_SYNC_SUPPORTEDand gate client-side Caps Lock synchronization (including applying mirrored state) on NVDA 2026.3+. - Update unit tests and stubs for the new gating and veto behavior; refresh documentation and bump add-on version to 2.0.3.
File summaries
| File | Description |
|---|---|
| tests/test_nvdaCompat.py | Adds unit tests for the NVDA version gate controlling Caps Lock sync support. |
| tests/test_capsLockVeto.py | Adds unit tests for the raw-key injected Caps Lock veto behavior. |
| tests/_stubs.py | Extends NVDA runtime stubs to include minimal winUser/keyboardHandler symbols for the veto tests and nvdaCompat reload paths. |
| readme.md | Documents 2.0.3 and updates the Caps Lock sync setting description and NVDA 2026.3 client requirement. |
| changelog.md | Updates the changelog entry to reflect the 2.0.3 Caps Lock sync change. |
| buildVars.py | Bumps add-on version to 2.0.3. |
| addon/lib/windowHelpers.py | Removes fullscreen detection helper, leaving only the shell window process helper. |
| addon/lib/nvdaCompat.py | Adds CAPS_LOCK_SYNC_SUPPORTED and updates module docstring to include the new gate. |
| addon/lib/capsLock.py | Introduces InjectedCapsLockVeto used to swallow injected Caps Lock raw key events. |
| addon/globalPlugins/rdAccess/handlers/_remoteHandler.py | Gates application of mirrored Caps Lock state on CAPS_LOCK_SYNC_SUPPORTED. |
| addon/globalPlugins/rdAccess/init.py | Registers/unregisters the raw-key veto on NVDA 2026.3+ and removes the gesture-level veto/fullscreen check path. |
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| self._isEnabled = isEnabled | ||
| self._remoteProcessHasFocus = remoteProcessHasFocus | ||
|
|
||
| def decide(self, vkCode: int, extended: bool, injected: bool | None = None) -> bool: |
Fold the veto back into RDGlobalPlugin next to its server-side counterpart, registered as a bound method on decide_handleRawKey, instead of a lib class that took its inputs as callables. Drop the reload-based version test and the stub scaffolding it needed, and compute the 2026.3 version check once in nvdaCompat. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvK8A5MrcwxdM5Y6aCdWLc
…tion The shell window helper moves into namedPipe, its only user, so the module that held the deleted full screen check goes away. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvK8A5MrcwxdM5Y6aCdWLc
LeonarddeR
enabled auto-merge (squash)
August 27, 2026 07:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What exists
RDAccess keeps the caps lock key in sync between the client and the server. When a full screen remote desktop session captures the keyboard, the remote desktop client feeds every caps lock press back into the client system as a software-generated key event. NVDA on the client treats that fed back press as its own modifier key, and a quick second press then toggles caps lock on the client only.
Since version 2.0.2, the client swallows the caps lock gesture that NVDA is about to pass to the operating system (
_vetoCapsLockToggle, registered oninputCore.decide_executeGesture), and the server reports its real caps lock state to the client, which applies it as soon as the session loses focus.NVDA's raw keyboard extension point did not tell the client whether a key event was generated by software. The client therefore guessed whether the remote desktop client was capturing the keyboard from the shape of the foreground window: it only swallowed presses while that window covered its whole monitor (
windowHelpers.isForegroundWindowFullScreen). Two gaps followed from that guess. Sessions that are not full screen but apply Windows key combinations on the remote computer still went out of sync. And with the NVDA setting "Handle keys from other applications" disabled, NVDA ignores software-generated keys before the gesture stage, so the veto never ran.What is needed
NVDA 2026.3 passes the
injectedflag to handlers ofinputCore.decide_handleRawKey(nvaccess/nvda#20748). That handler runs before NVDA looks at the "Handle keys from other applications" setting and before it turns the key into a gesture. A fed back caps lock press is always a software-generated event; a real press never is. The client can now tell them apart per key event instead of guessing from the window geometry.What changes
_vetoInjectedCapsLock, registered oninputCore.decide_handleRawKey; it replaces_vetoCapsLockToggleand the full screen check.lib.nvdaCompatasCAPS_LOCK_SYNC_SUPPORTED, sharing the version comparison the braille compatibility code already makes. The server side does not depend on the new NVDA version and keeps working on every supported version, so a client on NVDA 2026.3 gets the full feature against an older server.windowHelpersis removed. Its shell window helper moves into the named pipe code, its only user.changelog.mdnow holds the 2.0.3 entry only; the readme gains sections for 2.0.2 and 2.0.3, and its description of the setting no longer mentions full screen sessions or the "Handle keys from other applications" limitation. It now states that the client side needs NVDA 2026.3 and that caps lock presses sent by other software while a session window has focus are suppressed as well.Tests
The existing protocol tests for the caps lock attribute are unchanged. The new handler is NVDA keyboard hook glue that the unit test harness cannot import; it is verified manually against a remote session, like the rest of the plugin.
Known consequence
While a remote desktop session window has focus, the client now also swallows caps lock presses that other software sends, for example a leader in NVDA Remote Access. Turning the synchronization setting off restores the previous behavior.
Assisted by Claude
https://claude.ai/code/session_01TvK8A5MrcwxdM5Y6aCdWLc