[orca] Web: Attempt to work around object destruction during structural nav
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Web: Attempt to work around object destruction during structural nav
- Date: Tue, 4 Jan 2022 13:56:32 +0000 (UTC)
commit 174658e377b3e6d8446d61ee51c9c37635ed12ae
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Tue Jan 4 14:48:15 2022 +0100
Web: Attempt to work around object destruction during structural nav
Browsers sometimes destroy objects as a result of our grabbing focus
and/or setting the caret in those elements. When this happens, Orca
fails to present the new object correctly because it either no longer
exists at all, or lacks information it once had (like its name) due to
the destruction process having been started.
This commit attempts to work around that problem during structural
navigation by detecting the condition and then looking for a
replacement object at the same accessible path and with the same role.
Note that this work around sometimes fails due to timing and/or browser
bugs. More specifically, if AT-SPI2 has not received a children-changed
event from the parent of the element in question at the time we look for
that replacement, we'll still wind up with the defunct object we had
before. That said, this workaround seems to make things suck a bit less
than doing nothing at all to recover.
src/orca/script_utilities.py | 15 ++++++++
src/orca/scripts/web/script_utilities.py | 15 --------
src/orca/structural_navigation.py | 62 ++++++++++++++++++++++----------
3 files changed, 59 insertions(+), 33 deletions(-)
---
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index f5a32bfbb..290cb8874 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -1660,6 +1660,21 @@ class Utilities:
def isSwitch(self, obj):
return False
+ def getObjectFromPath(self, path):
+ start = self._script.app
+ rv = None
+ for p in path:
+ if p == -1:
+ continue
+ try:
+ start = start[p]
+ except:
+ break
+ else:
+ rv = start
+
+ return rv
+
def _hasSamePath(self, obj1, obj2):
path1 = pyatspi.utils.getPath(obj1)
path2 = pyatspi.utils.getPath(obj2)
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index 7e3516582..5509c8835 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -4896,21 +4896,6 @@ class Utilities(script_utilities.Utilities):
return rv
- def getObjectFromPath(self, path):
- start = self._script.app
- rv = None
- for p in path:
- if p == -1:
- continue
- try:
- start = start[p]
- except:
- break
- else:
- rv = start
-
- return rv
-
def clearCaretContext(self, documentFrame=None):
self.clearContentCache()
documentFrame = documentFrame or self.documentFrame()
diff --git a/src/orca/structural_navigation.py b/src/orca/structural_navigation.py
index c93c419cb..11b16cad3 100644
--- a/src/orca/structural_navigation.py
+++ b/src/orca/structural_navigation.py
@@ -1217,8 +1217,34 @@ class StructuralNavigation:
def _setCaretPosition(self, obj, characterOffset):
"""Sets the caret at the specified offset within obj."""
+ try:
+ objPath = pyatspi.getPath(obj)
+ objRole = obj.getRole()
+ except:
+ return obj, characterOffset
+
self._script.utilities.setCaretPosition(obj, characterOffset)
+ try:
+ obj.clearCache()
+ isDefunct = obj.getState().contains(pyatspi.STATE_DEFUNCT)
+ except:
+ isDefunct = True
+
+ if not isDefunct:
+ return obj, characterOffset
+
+ msg = "STRUCTURAL NAVIGATION: %s became defunct after setting caret position" % obj
+ debug.println(debug.LEVEL_INFO, msg, True)
+
+ replicant = self._script.utilities.getObjectFromPath(objPath)
+ if replicant and replicant.getRole() == objRole:
+ msg = "STRUCTURAL NAVIGATION: Updating obj to replicant %s" % replicant
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj = replicant
+
+ return obj, characterOffset
+
def _presentLine(self, obj, offset):
"""Presents the first line of the object to the user.
@@ -1439,7 +1465,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_BLOCKQUOTES
@@ -1522,7 +1548,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_BUTTONS
@@ -1606,7 +1632,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_CHECK_BOXES
@@ -1788,7 +1814,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_COMBO_BOXES
@@ -1871,7 +1897,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_ENTRIES
@@ -1971,7 +1997,7 @@ class StructuralNavigation:
if obj.getRole() == pyatspi.ROLE_TEXT and obj.childCount:
obj = obj[0]
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_FORM_FIELDS
@@ -2093,7 +2119,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
elif not arg:
full = messages.NO_MORE_HEADINGS
@@ -2269,7 +2295,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._script.presentMessage(obj.name)
self._presentLine(obj, characterOffset)
else:
@@ -2356,7 +2382,7 @@ class StructuralNavigation:
if obj:
self._script.speakMessage(self._getListDescription(obj))
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentLine(obj, characterOffset)
else:
full = messages.NO_MORE_LISTS
@@ -2440,7 +2466,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentLine(obj, characterOffset)
else:
full = messages.NO_MORE_LIST_ITEMS
@@ -2522,7 +2548,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_LIVE_REGIONS
@@ -2695,7 +2721,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_RADIO_BUTTONS
@@ -2950,7 +2976,7 @@ class StructuralNavigation:
self._presentCellHeaders(cell, arg)
[obj, characterOffset] = self._getCaretPosition(cell)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._script.updateBraille(obj)
blank = self._isBlankCell(cell)
@@ -3042,7 +3068,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_UNVISITED_LINKS
@@ -3130,7 +3156,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_VISITED_LINKS
@@ -3213,7 +3239,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
else:
full = messages.NO_MORE_LINKS
@@ -3298,7 +3324,7 @@ class StructuralNavigation:
if obj:
[obj, characterOffset] = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentObject(obj, characterOffset)
elif not arg:
full = messages.NO_MORE_CLICKABLES
@@ -3348,5 +3374,5 @@ class StructuralNavigation:
if characterOffset is None:
obj, characterOffset = self._getCaretPosition(obj)
- self._setCaretPosition(obj, characterOffset)
+ obj, characterOffset = self._setCaretPosition(obj, characterOffset)
self._presentLine(obj, characterOffset)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]