Skip to content

Improve Windows Terminal caret tracking with delayed UIA updates#20398

Open
sheldon-im wants to merge 5 commits into
nvaccess:masterfrom
sheldon-im:fix-winterminal-caret-timeout
Open

Improve Windows Terminal caret tracking with delayed UIA updates#20398
sheldon-im wants to merge 5 commits into
nvaccess:masterfrom
sheldon-im:fix-winterminal-caret-timeout

Conversation

@sheldon-im

@sheldon-im sheldon-im commented Jun 24, 2026

Copy link
Copy Markdown

Link to issue number:

Related to #19503

Summary of the issue:

Windows Terminal can update its UIA selection / caret position after NVDA's default 100 ms caret movement timeout, especially in remote terminal sessions such as SSH.

When this happens, NVDA may speak from stale caret information after left/right arrow navigation. In practice, this can cause NVDA to report the previous or next character rather than the character at the current caret position.

Description of user facing changes:

NVDA should be less likely to report stale characters when moving the caret in Windows Terminal, including remote SSH sessions.

This change is scoped to Windows Terminal controls. It does not change the default editable text caret movement timeout for other applications.

Description of developer facing changes:

Windows Terminal UIA overlays now use the existing editable text caret movement timeout multiplier mechanism.

The _caretMovementTimeoutMultiplier class attribute is set to 3.0 for both Windows Terminal UIA strategies:

  • _DiffBasedWinTerminalUIA
  • _NotificationsBasedWinTerminalUIA

With the default 100 ms editable text caret movement timeout, this gives Windows Terminal up to 300 ms for delayed UIA caret updates while reusing the existing _hasCaretMoved timeout path.

This covers both the diff-based path shown in #19503 and the notification-based path tested locally.

Description of development approach:

The existing caret movement timeout workaround was first validated manually. Raising the timeout to 300 ms avoided stale character reporting in a high-latency Windows Terminal SSH session.

A local scratchpad appModule prototype then applied a 0.300 second Windows Terminal-only timeout. This confirmed that giving Windows Terminal more time to update its UIA caret position works when applied to a Windows Terminal TermControl.

The final change does not add a separate _hasCaretMoved wrapper. Instead, it reuses NVDA's existing _caretMovementTimeoutMultiplier mechanism, matching the approach already used elsewhere in winConsoleUIA.py.

Testing strategy:

Manual testing:

  • Reproduced stale character reporting in Windows Terminal over SSH with the default caret movement timeout.
  • Verified that increasing the caret movement timeout to 300 ms avoids the stale character reporting.
  • Verified a Windows Terminal-only scratchpad prototype using a 0.300 second timeout.
  • Confirmed the prototype applied to a TermControl object using _NotificationsBasedWinTerminalUIA.
  • Confirmed the _hasCaretMoved path ran with a 0.300 second timeout.

Representative log excerpts from the prototype:

  • Windows Terminal caret latency prototype appModule loaded from scratchpad/source
  • Windows Terminal caret latency prototype overlay inserted for UIA class 'TermControl'; appName='windowsterminal'
  • Windows Terminal caret latency prototype active: using minimum caret movement timeout 0.300 sec

NVDA+F1 developer info confirmed:

  • UIA className: TermControl
  • appModule.productName: Microsoft.WindowsTerminal
  • appModule.productVersion: 1.24.11321.0
  • MRO included _NotificationsBasedWinTerminalUIA

Local checks run:

  • python -m py_compile source/NVDAObjects/UIA/winConsoleUIA.py
  • git diff --check
  • uvx ruff check --config pyproject.toml source/NVDAObjects/UIA/winConsoleUIA.py

Unit/system tests were not added for this small timing-specific UIA behavior change. The behavior depends on Windows Terminal UIA caret timing and was validated manually.

Known issues with pull request:

This uses a fixed multiplier of 3 for Windows Terminal. Further adjustments may be needed if maintainers prefer a different multiplier or a profile-only workaround.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation (Windows Console / Windows Terminal section updated)
    • Developer / Technical Documentation (not applicable: internal Windows Terminal behavior change)
    • Context sensitive help for GUI changes (not applicable: no GUI changes)
  • Testing:
    • Unit tests (not added; timing/UIA behavior validated manually)
    • System (end to end) tests (not added; requires Windows Terminal/SSH/UIA timing)
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille (no intentional change; existing caret handling remains delegated after timeout adjustment)
    • Low Vision (no intentional change)
    • Different web browsers (not applicable)
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

@sheldon-im sheldon-im marked this pull request as ready for review June 24, 2026 12:53
@sheldon-im sheldon-im requested a review from a team as a code owner June 24, 2026 12:53
@sheldon-im sheldon-im requested a review from SaschaCowley June 24, 2026 12:53
@LeonarddeR

Copy link
Copy Markdown
Collaborator

Thanks for your contribution!

I have some concerns about this route:

  1. Have you considered overriding the _caretMovementTimeoutMultiplier instead? Given you want to use a timeout of 0.3 sec, it makes sense to use a multiplier of 3.

A workaround suggested on the issue is increasing the global caret movement timeout. However, doing so affects all editable text controls.

  1. Not per se. Have you considered that people who want to increase the timeout can also do so in a profile that is bound to terminal applications?

I think I prefer the multiplier approach instead of introducing yet another mechanism to fiddle with the timeout. In fact, the multiplier is already used for older editions of winConsoleUIA.

@LeonarddeR LeonarddeR added app/windows-terminal New terminal app, potentially supersedes app/windows-console (repo: microsoft/terminal) blocked/needs-product-decision A product decision needs to be made. Decisions about NVDA UX or supported use-cases. labels Jun 24, 2026
@LeonarddeR

Copy link
Copy Markdown
Collaborator

cc @codeofdusk

@sheldon-im

Copy link
Copy Markdown
Author

Thanks for taking a look and for the detailed feedback.

I missed the existing _caretMovementTimeoutMultiplier mechanism and hadn't considered the terminal-bound configuration profile case. I agree that using the existing multiplier is more consistent with the current editable text / winConsoleUIA design than adding a separate _hasCaretMoved timeout path.

I've updated the PR to use the existing multiplier mechanism for the Windows Terminal UIA overlays and removed the custom timeout wrapper. Happy to adjust further depending on @codeofdusk's thoughts.

@LeonarddeR

Copy link
Copy Markdown
Collaborator

Thanks for applying my feedback.
I wonder whether it makes sense to apply this to terminals in general. In that case the best place to apply this would be NVDAObjects.behaviors.Terminal.

I also think that you don't need to use an AutoPropertyGetter _get_x, but you can safely use a class level override.

@codeofdusk

Copy link
Copy Markdown
Contributor

We used to have a caret movement multiplier before auto select detection was added to these objects, but it can make caret movement slow. See #12453.

@sheldon-im

Copy link
Copy Markdown
Author

Thanks for the follow-up.

I agree that the class-level override is simpler for the fixed multiplier case, and I can update that.

For applying this to terminals in general, I think that needs a bit more consideration. I initially scoped this PR to Windows Terminal because that is where I could reproduce and manually validate the issue, and it kept the change small and reviewable.

Broadening this to the shared Terminal behavior seems like a larger behavior change, so my preference would be to keep this PR Windows Terminal-specific for now. Would it make sense to discuss or handle the broader terminal behavior in a separate PR?

@SaschaCowley

Copy link
Copy Markdown
Member

We used to have a caret movement multiplier before auto select detection was added to these objects, but it can make caret movement slow. See #12453.

True, but in a certain way that's kind of the point here. When using SSH, there may often be over 100ms of round-trip latency, so NVDA will end up reporting inaccurate caret positions. At least in Windows Terminal, cranking up the caret movement timeout doesn't seem to hurt perceived performance for me, though I only tested it briefly.

That being said, on some connections there may be over 300ms of round-trip latency, in which case the same issue is going to come up. So I guess the goal here is to find a sweet spot that balances performance in local consoles where we don't get caret movement events, but works correctly over most remote connections. Clearly from my own experience and the comments of others, 100ms is too low for a lot of SSH connections, but 300ms feels almost uncomfortably high to me.

@LeonarddeR, @codeofdusk, @seanbudd, @michaelDCurran, thoughts?

Comment thread source/NVDAObjects/UIA/winConsoleUIA.py Outdated
"""

def _get__caretMovementTimeoutMultiplier(self):
"Windows Terminal sessions can take a while to update the UIA caret. (#19503)"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Windows Terminal sessions can take a while to update the UIA caret. (#19503)"
"""Caret updates can take a while, particularly over remote connections such as SSH. (#19503)"""

Comment thread source/NVDAObjects/UIA/winConsoleUIA.py Outdated
"""

def _get__caretMovementTimeoutMultiplier(self):
"Windows Terminal sessions can take a while to update the UIA caret. (#19503)"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Windows Terminal sessions can take a while to update the UIA caret. (#19503)"
"""Caret updates can take a while, particularly over remote connections such as SSH. (#19503)"""

@seanbudd

Copy link
Copy Markdown
Member

Can we make sure this is documented clearly in the user guide?

@seanbudd seanbudd added conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. and removed blocked/needs-product-decision A product decision needs to be made. Decisions about NVDA UX or supported use-cases. labels Jun 30, 2026
@sheldon-im sheldon-im requested a review from a team as a code owner June 30, 2026 01:12
@sheldon-im sheldon-im requested a review from Qchristensen June 30, 2026 01:12
@sheldon-im

Copy link
Copy Markdown
Author

Thanks, that makes sense.

I've updated the User Guide to document the Windows Terminal caret behavior, including delayed UIA caret updates over SSH, the related Caret move timeout setting, and the trade-off that increasing the timeout may make caret movement feel slower.

I also changed the multiplier implementation to a class-level override as previously suggested.

@sheldon-im sheldon-im force-pushed the fix-winterminal-caret-timeout branch from 0a8f13e to 7cd2ae8 Compare July 2, 2026 02:02
Comment thread user_docs/en/userGuide.md
Windows Terminal may delay UIA caret updates, especially in remote sessions over SSH.
NVDA waits slightly longer for caret movement in Windows Terminal, so it is less likely to report stale characters.
If caret reporting is still inaccurate, try increasing [Caret move timeout](#AdvancedSettingsCaretMoveTimeout) in Advanced settings.
Increasing this value may make caret movement feel slower, so consider changing it in a configuration profile for terminal applications.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think you need to keep an empty line belone.

Suggested change
Increasing this value may make caret movement feel slower, so consider changing it in a configuration profile for terminal applications.
Increasing this value may make caret movement feel slower, so consider changing it in a configuration profile for terminal applications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app/windows-terminal New terminal app, potentially supersedes app/windows-console (repo: microsoft/terminal) conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants