diff --git a/src/cthulhu/braille.py b/src/cthulhu/braille.py index cbaf5d3..139d0e6 100644 --- a/src/cthulhu/braille.py +++ b/src/cthulhu/braille.py @@ -540,7 +540,7 @@ class Component(Region): been scrolled off the display.""" if cthulhu_state.activeScript and cthulhu_state.activeScript.utilities.\ - grabFocusBeforeRouting(self.accessible, offset): + grabFocusBeforeRouting(self.accessible): if AXObject.supports_component(self.accessible): try: Atspi.Component.grab_focus(self.accessible) diff --git a/src/cthulhu/script_utilities.py b/src/cthulhu/script_utilities.py index 8c9233e..9df07ff 100644 --- a/src/cthulhu/script_utilities.py +++ b/src/cthulhu/script_utilities.py @@ -560,13 +560,12 @@ class Utilities: return False - def grabFocusBeforeRouting(self, obj, offset): + def grabFocusBeforeRouting(self, obj): """Whether or not we should perform a grabFocus before routing the cursor via the braille cursor routing keys. Arguments: - 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 to routing the cursor. diff --git a/src/cthulhu/scripts/web/speech_generator.py b/src/cthulhu/scripts/web/speech_generator.py index 824d0c5..3f0c39f 100644 --- a/src/cthulhu/scripts/web/speech_generator.py +++ b/src/cthulhu/scripts/web/speech_generator.py @@ -81,9 +81,6 @@ class SpeechGenerator(speech_generator.SpeechGenerator): if not self._script.utilities.inDocumentContent(obj): return super()._generateAncestors(obj, **args) - if self._script.inSayAll() and obj == cthulhu_state.locusOfFocus: - return [] - result = [] priorObj = args.get('priorObj') if priorObj and self._script.utilities.inDocumentContent(priorObj): diff --git a/src/cthulhu/speech_generator.py b/src/cthulhu/speech_generator.py index a364ae4..f277ea7 100644 --- a/src/cthulhu/speech_generator.py +++ b/src/cthulhu/speech_generator.py @@ -651,6 +651,10 @@ class SpeechGenerator(generator.Generator): Note that a 'role' attribute in args will override the 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'): return [] diff --git a/src/cthulhu/structural_navigation.py b/src/cthulhu/structural_navigation.py index e48a812..55e414d 100644 --- a/src/cthulhu/structural_navigation.py +++ b/src/cthulhu/structural_navigation.py @@ -596,15 +596,11 @@ class StructuralNavigation: # self.lastTableCell = [-1, -1] - self._objectCache = {} - self._inModalDialog = False def clearCache(self, document=None): - if document: - self._objectCache[hash(document)] = {} - else: - self._objectCache = {} + """No-op for backwards compatibility. Caching has been removed.""" + pass def structuralNavigationObjectCreator(self, name): """This convenience method creates a StructuralNavigationObject @@ -794,7 +790,11 @@ class StructuralNavigation: structuralNavigationObject.present(cell, arg) 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) inModalDialog = bool(modalDialog) @@ -804,29 +804,11 @@ class StructuralNavigation: f"{self._inModalDialog} to {inModalDialog}" ) debug.printMessage(debug.LEVEL_INFO, msg, True) - self.clearCache() 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() - cache = self._objectCache.get(hash(document), {}) - key = f"{structuralNavigationObject.objType}:{arg}" - 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 not document: + return [] if structuralNavigationObject.getter: matches = structuralNavigationObject.getter(document, arg) @@ -843,15 +825,12 @@ class StructuralNavigation: if inModalDialog: originalSize = len(matches) 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] debug.printTokens(debug.LEVEL_INFO, tokens, True) - matches = filterZombies(matches) - rv = matches.copy() - cache[key] = matches - self._objectCache[hash(document)] = cache - return rv + # Filter out zombie objects and return + return [m for m in matches if not self._script.utilities.isZombie(m)] def goEdge(self, structuralNavigationObject, isStart, container=None, arg=None): if container is None: