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:

  • Fixes #6424.
  • Probably also addresses #5725, #6699.
  • Should address #4481 for terminal connections with <= 100 ms latency. It doesn't directly handle latency beyond 100 ms, but the ability to configure the timeout means this can be handled with user intervention.
  • Probably addresses microsoft/vscode#26730 (at least in some cases).

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 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
…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.
@jcsteh jcsteh force-pushed the i6424CaretMoveTimeout branch from 963c3c8 to a65c5b9 May 24, 2017
@alexdima
Copy link

@alexdima alexdima commented May 24, 2017

@jcsteh Thank you very much!

Copy link
Contributor

@feerrenrut feerrenrut left a comment

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)

This comment has been minimized.

@feerrenrut

feerrenrut May 25, 2017
Contributor

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

This comment has been minimized.

@feerrenrut

feerrenrut May 25, 2017
Contributor

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):

This comment has been minimized.

@feerrenrut

feerrenrut May 25, 2017
Contributor

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

This comment has been minimized.

@jcsteh

jcsteh Jun 1, 2017
Author Contributor

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 bhavyashah commented May 25, 2017

@jcsteh
Copy link
Contributor Author

@jcsteh jcsteh commented May 25, 2017

@jcsteh
Copy link
Contributor Author

@jcsteh jcsteh commented Jun 1, 2017

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

@jcsteh jcsteh requested a review from feerrenrut Jun 1, 2017
jcsteh added a commit that referenced this pull request Jun 7, 2017
…figurable. Incubates #7201 (issue #6424).
…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 Jun 21, 2017
@jcsteh
Copy link
Contributor Author

@jcsteh 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 added a commit that referenced this pull request Jun 21, 2017
@jcsteh
Copy link
Contributor Author

@jcsteh 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 Jun 22, 2017
@jcsteh
Copy link
Contributor Author

@jcsteh 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 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 Jun 26, 2017
jcsteh added a commit that referenced this pull request Jun 26, 2017
… Incubates #7201 (issue #6424). Fixes #7323.
@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 Jul 10, 2017
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

@amaniahmad amaniahmad commented Jun 7, 2018

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

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

Successfully merging this pull request may close these issues.

6 participants