Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase default caret move timeout from 30 to 100 ms and make it configurable #7201

Merged
merged 5 commits into from
Jul 10, 2017

Conversation

jcsteh
Copy link
Contributor

@jcsteh jcsteh commented May 24, 2017

Link to issue number:

Summary of the issue:

NVDA has a very conservative cursor movement timeout of 30 ms. That is, when the user presses a cursor key, backspace, etc., we check the caret position, send the key press and then wait about 30 ms for the caret to move. 30 ms was chosen to ensure maximum responsiveness, but this just isn't enough in the wild; e.g. in complex web editors (particularly in Chrome) or when connecting to remote terminals with connection latency.

Description of how this pull request fixes the issue:

  • Previously, the default was hard-coded to 30 ms in editableText.EditableText._hasCaretMoved.
  • This is now configurable via config.conf["editableText"]["caretMoveTimeout"]. It is not exposed in the GUI, as this should only be changed by advanced users. The value is in ms, not seconds, as that's a better unit for this purpose. However, the function continues to use seconds for its arguments for backwards compatibility.
  • The default is now 100 ms.
  • Previously, _hasCaretMoved slept at the end of the loop but didn't check for caret movement again. This meant that it could return False even if the caret did actually move during the last sleep. Now, the timeout check happens after the caret movement check, ensuring the correct result.
  • _hasCaretMoved now works with ms rather than seconds to avoid floating point precision errors. These precision errors could result in an extraneous additional retry.
  • Added some debug logging to help diagnose caret tracking problems in future.

Testing performed:

  1. In Notepad, tested cursoring through text, cursoring when already at the edge (e.g. left arrow at start of document) and backspacing. All worked as expected. Delay when already at edge was longer, which is expected.
  2. Tested in Chrome with the test case from related Chromium issue 725051. Observed that cursor tracking was more reliable with this PR. Saw some cases where debug logging shows the caret took longer than 30 ms to move, which explains the increased accuracy with this PR.
  3. Tested in Firefox as per point 1 and received expected results.
  4. Tested backspacing while composing a message in Chrome, particularly when there's only one character in the message. In NVDA next, this often says nothing. With this PR, this works as expected. Again, observed debug logging shows the caret took longer than 30 ms to move in some cases.

Known issues with pull request:

None known.

Change log entry:

In Bug Fixes:

- In editable text, when moving the caret (e.g. with the cursor keys or backspace), NVDA's spoken feedback is now more accurate in many cases, particularly in Chrome and terminal applications. (#6424)

@jcsteh
Copy link
Contributor Author

jcsteh commented May 24, 2017

Ug. Accidentally clicked submit before I was finished. I've updated the initial comment.

@jcsteh jcsteh requested a review from feerrenrut May 24, 2017 04:35
…figurable.

- 30 ms was chosen to ensure maximum responsiveness, but this just isn't enough in the wild; e.g. in complex web editors (particularly in Chrome) or when connecting to remote terminals with connection latency.
- This is configurable via config.conf["editableText"]["caretMoveTimeout"]. It is not exposed in the GUI, as this should only be changed by advanced users. The value is in ms, not seconds, as that's a better unit for this purpose. However, the function continues to use seconds for its arguments for backwards compatibility.
- Previously, _hasCaretMoved slept at the end of the loop but didn't check for caret movement again. This meant that it could return False even if the caret did actually move during the last sleep. Now, the timeout check happens after the caret movement check, ensuring the correct result.
- _hasCaretMoved now works with ms rather than seconds to avoid floating point precision errors. These precision errors could result in an extraneous additional retry.
- Added some debug logging to help diagnose caret tracking problems in future.
@alexdima
Copy link

@jcsteh Thank you very much!

Copy link
Contributor

@feerrenrut feerrenrut left a comment

Choose a reason for hiding this comment

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

Looks good. Another PR with a great description!

@@ -192,6 +192,9 @@

[upgrade]
newLaptopKeyboardLayout = boolean(default=false)

[editableText]
caretMoveTimeout = integer(min=0, max=2000, default=100)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would be tempted to mention the units as part of the name for this config option, something like caretMoveTimeoutMS or caretMoveTimeoutMilliSec

timeout = config.conf["editableText"]["caretMoveTimeout"]
else:
# This function's arguments are in seconds, but we want ms.
timeout *= 1000
Copy link
Contributor

Choose a reason for hiding this comment

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

Since timeout is documented on the function to be in seconds, I think it could be easy to miss that its converted into milliseconds. Perhaps store the milliseconds in a new var, timeoutMs

@@ -42,21 +43,30 @@ class EditableText(ScriptableObject):
#: Whether or not to announce text found before the caret on a new line (e.g. auto numbering)
announceNewLineText=True

def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=0.03):
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

In the description of this PR you mention backwards compat for this function I think? Changing timeout to None will risk breaking that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's certainly a valid point, but I think it's a negligible/acceptable risk.

  1. It's most likely that a caller would call this function either accepting the defaults or passing its own timeout, both of which will still work as expected.
  2. This doesn't call super, so there's no chance that some method will receive None that wasn't expecting it.
  3. The only risk I can think of is that a subclass might have hard-coded the old 0.03 default, in which case they won't get the user's configured value. However, at worst, this means some subclass won't behave consistently with the rest of NVDA, and this would be pretty clear from the debug log if caret movement started timing out. I also think the likelihood of someone having done this is unlikely.
  4. Since it's a private method, maintaining backwards compat is a courtesy anyway, not an obligation. :)

@bhavyashah
Copy link

bhavyashah commented May 25, 2017 via email

@jcsteh
Copy link
Contributor Author

jcsteh commented May 25, 2017 via email

@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 1, 2017

@feerrenrut, this is ready for review round 2. Thanks! :)

@jcsteh jcsteh requested a review from feerrenrut June 1, 2017 12:29
…g valueChange events as caret moves. Also, treat caret events as caret moves as well, as this should be more reliable than comparing bookmarks in some cases.
@jcsteh jcsteh requested a review from feerrenrut June 21, 2017 01:31
@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 21, 2017

@feerrenrut, would you remind reviewing the latest commit? @tspivey reported that this change was making the delete key feel laggy, which I've now fixed for most cases.

@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 21, 2017

Arrrg. This latest change breaks Chrome again. Looks like caret events get fired even though Chrome hasn't updated the caret yet. I'm guessing they're MSAA system caret events, rather than IA2 caret events.

… uses the system caret, but this moves before IA2 is updated. Ignore system caret events for IA2 implementations and rely only on IA2 caret events.
@jcsteh jcsteh requested a review from feerrenrut June 22, 2017 05:43
@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 22, 2017

@feerrenrut, it's not my week. Review latest commit pretty please? :)

…sed by c967b21.

Firefox fires caret events even when you use caret movement commands when already at the edge of the control. That means we don't fire caretMovementFailed events in these cases. Furthermore, it seems quite a few things (e.g. Wordpad, Notepad++) don't fire valueChange or caret events when you press delete.
To work around this, drop the checks for caret and valueChange events (and revert the shouldAllowSystemCaretEvent stuff). Instead, when pressing delete, compare the word at the caret (in addition to bookmarks) to detect movement.
@jcsteh
Copy link
Contributor Author

jcsteh commented Jun 26, 2017

@feerrenrut, yet another regression fix for you to review when you have a chance. Thanks.

@jcsteh jcsteh requested a review from feerrenrut June 26, 2017 03:02
jcsteh added a commit that referenced this pull request Jun 26, 2017
@jcsteh jcsteh merged commit e45c36a into master Jul 10, 2017
@nvaccessAuto nvaccessAuto added this to the 2017.3 milestone Jul 10, 2017
@jcsteh jcsteh deleted the i6424CaretMoveTimeout branch July 10, 2017 06:57
michaelDCurran added a commit that referenced this pull request Aug 15, 2017
…if the word at the caret has changed once _hasCaretMoved_minWordTimeoutMs has elapsed. I.e. 30 ms must elapse before starting to check the word.

This fixes a regression introduced by #7201 where deleting characters in Mozilla Gecko editable controls would cause the character being deleted to be spoken rather than the character that followed.
michaelDCurran added a commit that referenced this pull request Aug 15, 2017
…if the word at the caret has changed once _hasCaretMoved_minWordTimeoutMs has elapsed. I.e. 30 ms must elapse before starting to check the word. (#7496)

This fixes a regression introduced by #7201 where deleting characters in Mozilla Gecko editable controls would cause the character being deleted to be spoken rather than the character that followed.
@amaniahmad
Copy link

Dear
Please could help me
how make website accessibility
step by step
thanks for all

@zahra21
Copy link

zahra21 commented May 9, 2021

Dear
Please could help me
how make website accessibility
step by step
thanks for all

hello and pardon me for very late reply.
today, i opened this link and read your comment.
i searched in the internet and found a helpful page for you.
i studied the content and found it useful.
here you are the link. hope that helps. God bless you!
https://www.searchenginejournal.com/make-website-more-accessible/347450/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NVDA unable to track cursor in the GMail message composer when using Chrome
7 participants