Started porting over some bug fixes and modernizations from Orca.
This commit is contained in:
@@ -540,7 +540,7 @@ class Component(Region):
|
|||||||
been scrolled off the display."""
|
been scrolled off the display."""
|
||||||
|
|
||||||
if cthulhu_state.activeScript and cthulhu_state.activeScript.utilities.\
|
if cthulhu_state.activeScript and cthulhu_state.activeScript.utilities.\
|
||||||
grabFocusBeforeRouting(self.accessible, offset):
|
grabFocusBeforeRouting(self.accessible):
|
||||||
if AXObject.supports_component(self.accessible):
|
if AXObject.supports_component(self.accessible):
|
||||||
try:
|
try:
|
||||||
Atspi.Component.grab_focus(self.accessible)
|
Atspi.Component.grab_focus(self.accessible)
|
||||||
|
|||||||
@@ -560,13 +560,12 @@ class Utilities:
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def grabFocusBeforeRouting(self, obj, offset):
|
def grabFocusBeforeRouting(self, obj):
|
||||||
"""Whether or not we should perform a grabFocus before routing
|
"""Whether or not we should perform a grabFocus before routing
|
||||||
the cursor via the braille cursor routing keys.
|
the cursor via the braille cursor routing keys.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
- obj: the accessible object where the cursor should be routed
|
- obj: the accessible object where the cursor should be routed
|
||||||
- offset: the offset to which it should be routed
|
|
||||||
|
|
||||||
Returns True if we should do an explicit grabFocus on obj prior
|
Returns True if we should do an explicit grabFocus on obj prior
|
||||||
to routing the cursor.
|
to routing the cursor.
|
||||||
|
|||||||
@@ -81,9 +81,6 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
|
|||||||
if not self._script.utilities.inDocumentContent(obj):
|
if not self._script.utilities.inDocumentContent(obj):
|
||||||
return super()._generateAncestors(obj, **args)
|
return super()._generateAncestors(obj, **args)
|
||||||
|
|
||||||
if self._script.inSayAll() and obj == cthulhu_state.locusOfFocus:
|
|
||||||
return []
|
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
priorObj = args.get('priorObj')
|
priorObj = args.get('priorObj')
|
||||||
if priorObj and self._script.utilities.inDocumentContent(priorObj):
|
if priorObj and self._script.utilities.inDocumentContent(priorObj):
|
||||||
|
|||||||
@@ -651,6 +651,10 @@ class SpeechGenerator(generator.Generator):
|
|||||||
Note that a 'role' attribute in args will override the
|
Note that a 'role' attribute in args will override the
|
||||||
accessible role of the obj.
|
accessible role of the obj.
|
||||||
"""
|
"""
|
||||||
|
# Prevent role repetition when object is same as prior object
|
||||||
|
if obj == args.get("priorObj"):
|
||||||
|
return []
|
||||||
|
|
||||||
if _settingsManager.getSetting('onlySpeakDisplayedText'):
|
if _settingsManager.getSetting('onlySpeakDisplayedText'):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|||||||
@@ -596,15 +596,11 @@ class StructuralNavigation:
|
|||||||
#
|
#
|
||||||
self.lastTableCell = [-1, -1]
|
self.lastTableCell = [-1, -1]
|
||||||
|
|
||||||
self._objectCache = {}
|
|
||||||
|
|
||||||
self._inModalDialog = False
|
self._inModalDialog = False
|
||||||
|
|
||||||
def clearCache(self, document=None):
|
def clearCache(self, document=None):
|
||||||
if document:
|
"""No-op for backwards compatibility. Caching has been removed."""
|
||||||
self._objectCache[hash(document)] = {}
|
pass
|
||||||
else:
|
|
||||||
self._objectCache = {}
|
|
||||||
|
|
||||||
def structuralNavigationObjectCreator(self, name):
|
def structuralNavigationObjectCreator(self, name):
|
||||||
"""This convenience method creates a StructuralNavigationObject
|
"""This convenience method creates a StructuralNavigationObject
|
||||||
@@ -794,7 +790,11 @@ class StructuralNavigation:
|
|||||||
structuralNavigationObject.present(cell, arg)
|
structuralNavigationObject.present(cell, arg)
|
||||||
|
|
||||||
def _getAll(self, structuralNavigationObject, arg=None):
|
def _getAll(self, structuralNavigationObject, arg=None):
|
||||||
"""Returns all the instances of structuralNavigationObject."""
|
"""Returns all the instances of structuralNavigationObject.
|
||||||
|
|
||||||
|
Queries fresh each time without caching to ensure accurate results
|
||||||
|
when returning to a page after switching applications.
|
||||||
|
"""
|
||||||
|
|
||||||
modalDialog = self._script.utilities.getModalDialog(cthulhu_state.locusOfFocus)
|
modalDialog = self._script.utilities.getModalDialog(cthulhu_state.locusOfFocus)
|
||||||
inModalDialog = bool(modalDialog)
|
inModalDialog = bool(modalDialog)
|
||||||
@@ -804,29 +804,11 @@ class StructuralNavigation:
|
|||||||
f"{self._inModalDialog} to {inModalDialog}"
|
f"{self._inModalDialog} to {inModalDialog}"
|
||||||
)
|
)
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
self.clearCache()
|
|
||||||
self._inModalDialog = inModalDialog
|
self._inModalDialog = inModalDialog
|
||||||
|
|
||||||
def filterZombies(matchList):
|
|
||||||
if not matchList:
|
|
||||||
return []
|
|
||||||
return [match for match in matchList if not self._script.utilities.isZombie(match)]
|
|
||||||
|
|
||||||
document = self._script.utilities.documentFrame()
|
document = self._script.utilities.documentFrame()
|
||||||
cache = self._objectCache.get(hash(document), {})
|
if not document:
|
||||||
key = f"{structuralNavigationObject.objType}:{arg}"
|
return []
|
||||||
matches = cache.get(key, [])
|
|
||||||
if matches:
|
|
||||||
matches = filterZombies(matches)
|
|
||||||
if matches:
|
|
||||||
tokens = ["STRUCTURAL NAVIGATION: Returning", len(matches), "matches from cache"]
|
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return matches.copy()
|
|
||||||
|
|
||||||
tokens = ["STRUCTURAL NAVIGATION: Cached matches are zombies; refreshing"]
|
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
cache.pop(key, None)
|
|
||||||
self._objectCache[hash(document)] = cache
|
|
||||||
|
|
||||||
if structuralNavigationObject.getter:
|
if structuralNavigationObject.getter:
|
||||||
matches = structuralNavigationObject.getter(document, arg)
|
matches = structuralNavigationObject.getter(document, arg)
|
||||||
@@ -843,15 +825,12 @@ class StructuralNavigation:
|
|||||||
if inModalDialog:
|
if inModalDialog:
|
||||||
originalSize = len(matches)
|
originalSize = len(matches)
|
||||||
matches = [m for m in matches if AXObject.find_ancestor(m, lambda x: x == modalDialog)]
|
matches = [m for m in matches if AXObject.find_ancestor(m, lambda x: x == modalDialog)]
|
||||||
tokens = ["STRUCTURAL NAVIGATION: Removed", {originalSize - len(matches)},
|
tokens = ["STRUCTURAL NAVIGATION: Removed", originalSize - len(matches),
|
||||||
"objects outside of modal dialog", modalDialog]
|
"objects outside of modal dialog", modalDialog]
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
|
||||||
matches = filterZombies(matches)
|
# Filter out zombie objects and return
|
||||||
rv = matches.copy()
|
return [m for m in matches if not self._script.utilities.isZombie(m)]
|
||||||
cache[key] = matches
|
|
||||||
self._objectCache[hash(document)] = cache
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def goEdge(self, structuralNavigationObject, isStart, container=None, arg=None):
|
def goEdge(self, structuralNavigationObject, isStart, container=None, arg=None):
|
||||||
if container is None:
|
if container is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user