Skip to content

When handling caret movement, fetch the new caret info after checking for a pending caret event.#16711

Merged
seanbudd merged 2 commits intonvaccess:masterfrom
jcsteh:caretAfterEvent
Jun 18, 2024
Merged

When handling caret movement, fetch the new caret info after checking for a pending caret event.#16711
seanbudd merged 2 commits intonvaccess:masterfrom
jcsteh:caretAfterEvent

Conversation

@jcsteh
Copy link
Contributor

@jcsteh jcsteh commented Jun 17, 2024

Link to issue number:

None.

Summary of the issue:

In Firefox's in-progress UIA implementation, moving with the cursor keys in editable text boxes sometimes reports the character at the old position of the caret instead of the new position of the caret. For example, on the line:
abcdef
with the cursor positioned on "a", pressing right arrow several times might read a, b, c instead of b, c, d.
I don't anticipate that NVDA will ever move to using UIA in Firefox. Nevertheless, this is an NVDA bug which might impact other things.

Description of user facing changes

When navigating with the cursor keys in text boxes in applications which use UI Automation, NVDA no longer sometimes reports the wrong character, word, etc.

Description of development approach

Previously, EditableText._hasCaretMoved fetched the caret before checking for a pending caret event. It then returned this fetched caret. The following race condition could occur:

  1. In NVDA's main thread, NVDA queries the caret. The caret hasn't updated yet in the app, so this is the old position.
  2. The app fires a caret event.
  3. NVDA receives this caret event on a background UIA thread and queues it.
  4. Back in NVDA's main thread, NVDA checks for a pending caret event. That check passes because of 3).
  5. NVDA returns the old caret info retrieved in 1).

This can't happen with other APIs because they all queue events on the main thread, which can't be preempted during _hasCaretMoved. However, UIA queues events from a background thread.

Testing strategy:

I tested caret navigation in various apps: normal Firefox, Edge, Windows Run dialog, Notepad++, Windows Settings, Windows Start Menu. Everything worked as expected.
I tested caret navigation in Firefox's in-progress UIA implementation. After this change, everything worked as expected.

Known issues with pull request:

None.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

Summary by CodeRabbit

  • Bug Fixes
    • Improved caret movement detection to prevent NVDA from reporting incorrect characters or words when navigating with cursor keys in text boxes using UI Automation.

@jcsteh jcsteh requested a review from a team as a code owner June 17, 2024 06:35
@jcsteh jcsteh requested a review from seanbudd June 17, 2024 06:35
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2024

Walkthrough

Recent changes to the project include updates to improve the reliability of caret movement detection in editable text areas. This is achieved by adding a check for elapsed time and specific event types before fetching caret information. Additionally, documentation has been updated to reflect that NVDA now correctly reports characters, words, and other navigation elements when using cursor keys in text boxes within UI Automation-based applications.

Changes

File Change Summary
source/editableText.py Reordered logic for caret movement detection to include checks for elapsed time and specific event types.
user_docs/en/changes.md Updated documentation to mention that NVDA now reports correct elements when navigating in UI Automation-based text boxes.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@jcsteh jcsteh force-pushed the caretAfterEvent branch from 7c5581b to cef63ab Compare June 17, 2024 06:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

@LeonarddeR
Copy link
Collaborator

I wonder whether we should re-investigate all cases where caretMovementDetectionUsesEvents is currently set to False, especially in InaccurateTextChangeEventEmittingEditableText. It could be that the assumption in there is/was just wrong.

@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 17, 2024

It turns out that I can reproduce this in text boxes in web content in Edge when NVDA is using UIA for Edge.

@seanbudd seanbudd added the merge-early Merge Early in a developer cycle label Jun 17, 2024
@codeofdusk
Copy link
Contributor

codeofdusk commented Jun 17, 2024

In particular, I'd like to play with this branch in UIA terminals. I disabled caret events there because when quickly backspacing, the last character of the prompt was sometimes eroneously read. Leaving this here and will do so soon

@seanbudd
Copy link
Member

@jcsteh - does this mean this PR should not be merged and a different approach is found?

@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 18, 2024

Sorry for the lack of clarity. I meant that the original issue (without this PR) can be reproduced in Edge + UIA. This PR should fix the problem for both Firefox and Edge when using UIA. I thought this worth noting because while UIA in Firefox is not likely to be used "in the real world", NVDA does have explicit support for UIA in Edge and that is the only option for certain use cases, so that increases the user impact of this bug from theoretical to practical.

@seanbudd seanbudd merged commit 283856b into nvaccess:master Jun 18, 2024
@jcsteh jcsteh deleted the caretAfterEvent branch June 26, 2024 04:42
seanbudd pushed a commit that referenced this pull request Jul 11, 2024
Partially reverts #14888, #15838

Summary of the issue:
In #14888, XamlEditableText was added to ensure that UIA events wouldn't be used to determine caret changes, as the hypothesis was that they were fired too early. In #15838, I expanded this workaround for WPF (Visual Studio) text controls.
It turns out @jcsteh found the actual cause of these issues and fixed them in #16711, allowing us to rely on events again.

Description of user facing changes
None, though caret movement would possibly be detected a little bit faster in XAML and WPF controls.

Description of development approach
Mostly reverts.
seanbudd pushed a commit that referenced this pull request Jul 18, 2024
Follow-up of #16711, #16817.

Summary of the issue:
UIA caret events in Windows Terminal were unreliable before #16711. In particular, when rapidly pressing backspace, sometimes the last character of the prompt would be erroneously read.

Description of how this pull request fixes the issue:
Re-enable caret events in Windows Terminal specifically. Note that caret events are still broken in this way in Conhost and are therefore left disabled.
@burakyuksek
Copy link
Contributor

@jcsteh Can this fix also be applied to notepad please? The same issue occurs in notepad, too.

@codeofdusk
Copy link
Contributor

@burakyuksek Notepad is a UIA app.

@burakyuksek
Copy link
Contributor

@codeofdusk I'm aware, however the issue still occurs.

@jcsteh
Copy link
Contributor Author

jcsteh commented Aug 28, 2024

This PR should apply to all UIA implementations, so if this is still happening in Notepad for you, that would suggest it is a different issue. A couple of possibilities:

  1. The cursor is taking too long to move, so NVDA times out and reports the old caret position.
  2. I think there might be some bugs when moving the caret across wrapped lines. Are the issues you're seeing at the end of wrapped lines?

Otherwise, I have no idea.

@burakyuksek
Copy link
Contributor

@jcsteh Hello,
I noticed that like you said, the issue usually occurs in at or end of lines. Disabling word wrap makes it less frequent.

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

Labels

merge-early Merge Early in a developer cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants