Skip to content

Commit

Permalink
Fix regression of Automatic focus mode for caret movement in Firefox.…
Browse files Browse the repository at this point in the history
… Incubates #7201 (issue #6424). Fixes #7323.
  • Loading branch information
jcsteh committed Jun 26, 2017
2 parents 104d2ff + 4a908f3 commit 1102092
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 32 deletions.
8 changes: 2 additions & 6 deletions source/IAccessibleHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,12 +613,8 @@ def processGenericWinEvent(eventID,window,objectID,childID):
appModuleHandler.update(winUser.getWindowThreadProcessID(window)[0])
#Handle particular events for the special MSAA caret object just as if they were for the focus object
focus=eventHandler.lastQueuedFocusObject
if objectID==winUser.OBJID_CARET and eventID in (winUser.EVENT_OBJECT_LOCATIONCHANGE,winUser.EVENT_OBJECT_SHOW):
if isinstance(focus,NVDAObjects.window.Window) and focus.shouldAllowSystemCaretEvent:
NVDAEvent=("caret",focus)
else:
# No focus or the focus doesn't want these caret events.
return
if focus and objectID==winUser.OBJID_CARET and eventID in (winUser.EVENT_OBJECT_LOCATIONCHANGE,winUser.EVENT_OBJECT_SHOW):
NVDAEvent=("caret",focus)
else:
NVDAEvent=winEventToNVDAEvent(eventID,window,objectID,childID)
if not NVDAEvent:
Expand Down
6 changes: 0 additions & 6 deletions source/NVDAObjects/IAccessible/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,12 +647,6 @@ def _get_TextInfo(self):
return IA2TextTextInfo
return super(IAccessible,self).TextInfo

def _get_shouldAllowSystemCaretEvent(self):
if hasattr(self, 'IAccessibleTextObject'):
# IAccessibleText implementations fire IA2 caret events which are more reliable.
return False
return super(IAccessible, self).shouldAllowSystemCaretEvent

def _isEqual(self,other):
if self.IAccessibleChildID!=other.IAccessibleChildID:
return False
Expand Down
4 changes: 0 additions & 4 deletions source/NVDAObjects/window/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,6 @@ def _get_devInfo(self):
info.append("displayText: %s" % ret)
return info

#: Whether to allow caret events generated by the system caret;
#: i.e. as triggered by the Win32 functions ShowCaret and SetCaretPos.
shouldAllowSystemCaretEvent = True

class Desktop(Window):

isPresentableFocusAncestor = False
Expand Down
33 changes: 17 additions & 16 deletions source/editableText.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ 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=None):
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None, origWord=None):
"""
Waits for the caret to move, for a timeout to elapse, or for a new focus event or script to be queued.
@param bookmark: a bookmark representing the position of the caret before it was instructed to move
Expand All @@ -53,6 +53,9 @@ def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None):
@param timeout: the over all amount of time in seconds the method should wait before giving up completely,
C{None} to use the value from the configuration.
@type timeout: float
@param origWord: The word at the caret before the movement command,
C{None} if the word at the caret should not be used to detect movement.
This is intended for use with the delete key.
@return: a tuple containing a boolean denoting whether this method timed out, and a TextInfo representing the old or updated caret position or None if interupted by a script or focus event.
@rtype: tuple
"""
Expand All @@ -79,19 +82,7 @@ def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None):
newInfo = self.makeTextInfo(textInfos.POSITION_CARET)
except (RuntimeError,NotImplementedError):
newInfo = None
if eventHandler.isPendingEvents("caret"):
log.debug("caret event. Elapsed: %d ms" % elapsed)
return (True, newInfo)
if eventHandler.isPendingEvents("valueChange"):
# When pressing delete, the caret might not physically move,
# so the control might not fire a caret event,
# even though the text under the caret changes.
# We still want to treat this as a caret move.
# Otherwise, the user will have to wait
# the full timeout for feedback after pressing delete.
log.debug("valueChange event. Elapsed: %d ms" % elapsed)
return (True, newInfo)
# Some controls don't fire caret events.
# Caret events are unreliable in some controls.
# Try to detect with bookmarks.
newBookmark = None
if newInfo:
Expand All @@ -102,7 +93,15 @@ def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None):
if newBookmark and newBookmark!=bookmark:
log.debug("Caret move detected using bookmarks. Elapsed: %d ms" % elapsed)
return (True, newInfo)
if elapsed >= timeoutMs:
if origWord is not None and newInfo:
# When pressing delete, bookmarks might not be enough to detect caret movement.
wordInfo = newInfo.copy()
wordInfo.expand(textInfos.UNIT_WORD)
word = wordInfo.text
if word != origWord:
log.debug("Word at caret changed. Elapsed: %d ms" % elapsed)
return (True, newInfo)
if elapsed >= timeoutMs:
break
time.sleep(retryInterval)
elapsed += retryMs
Expand Down Expand Up @@ -232,9 +231,11 @@ def script_caret_delete(self,gesture):
gesture.send()
return
bookmark=info.bookmark
info.expand(textInfos.UNIT_WORD)
word=info.text
gesture.send()
# We'll try waiting for the caret to move, but we don't care if it doesn't.
caretMoved,newInfo=self._hasCaretMoved(bookmark)
caretMoved,newInfo=self._hasCaretMoved(bookmark,origWord=word)
self._caretScriptPostMovedHelper(textInfos.UNIT_CHARACTER,gesture,newInfo)
braille.handler.handleCaretMove(self)

Expand Down

0 comments on commit 1102092

Please sign in to comment.