[orca] Implement initial recovery from the current focused object being removed
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Implement initial recovery from the current focused object being removed
- Date: Fri, 1 May 2020 21:35:45 +0000 (UTC)
commit cfb12731ea747f6b523028bb7471a3da3a9d65aa
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Fri May 1 17:28:12 2020 -0400
Implement initial recovery from the current focused object being removed
If we get a child-removed event for the removal of the current focus,
and if that removal immediately followed line nav, attempt to locate
the nearest object to the removed child based on the direction of
navigation. If we find such an object, move there and present the line.
Note: The goal of this recovery is not perfection; it's to improve
unpredictable jumping around when the web author destroys the object
we're in.
This seems to improve the situation when we wander into Riot's Message
Actions toolbar in Chromium and then that toolbar gets destroyed while
we're in it. (The issue with our getting stuck in that same toolbar is
a different issue which still needs to be solved.)
src/orca/script_utilities.py | 4 +-
src/orca/scripts/web/script.py | 23 ++++++----
src/orca/scripts/web/script_utilities.py | 79 ++++++++++++++++++++++++++++++++
3 files changed, 95 insertions(+), 11 deletions(-)
---
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 25ee8e941..97264ff2f 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -2617,7 +2617,7 @@ class Utilities:
return relation.getTarget(0)
index = obj.getIndexInParent() - 1
- if obj.parent and not (0 <= index < obj.parent.childCount - 1):
+ while obj.parent and not (0 <= index < obj.parent.childCount - 1):
obj = obj.parent
index = obj.getIndexInParent() - 1
@@ -2642,7 +2642,7 @@ class Utilities:
return relation.getTarget(0)
index = obj.getIndexInParent() + 1
- if obj.parent and not (0 < index < obj.parent.childCount):
+ while obj.parent and not (0 < index < obj.parent.childCount):
obj = obj.parent
index = obj.getIndexInParent() + 1
diff --git a/src/orca/scripts/web/script.py b/src/orca/scripts/web/script.py
index 5f1021714..65497a141 100644
--- a/src/orca/scripts/web/script.py
+++ b/src/orca/scripts/web/script.py
@@ -1271,6 +1271,12 @@ class Script(default.Script):
debug.println(debug.LEVEL_INFO, msg, True)
contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset)
utterances = self.speechGenerator.generateContents(contents)
+ elif self.utilities.lastInputEventWasLineNav() and event \
+ and event.type.startswith("object:children-changed"):
+ msg = "WEB: Last input event was line nav and children changed. Generating line contents."
+ debug.println(debug.LEVEL_INFO, msg, True)
+ contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset)
+ utterances = self.speechGenerator.generateContents(contents)
else:
msg = "WEB: New focus %s is not a special case. Generating speech." % newFocus
debug.println(debug.LEVEL_INFO, msg, True)
@@ -1739,11 +1745,15 @@ class Script(default.Script):
debug.println(debug.LEVEL_INFO, msg, True)
return False
- # TODO - JD: Handle this case.
- if event.any_data == orca_state.locusOfFocus:
- msg = "WEB: Removed child is locusOfFocus."
+ if self._loadingDocumentContent:
+ msg = "WEB: Ignoring because document content is being loaded."
debug.println(debug.LEVEL_INFO, msg, True)
- return False
+ return True
+
+ if self.utilities.handleEventForRemovedChild(event):
+ msg = "WEB: Event handled for removed child."
+ debug.println(debug.LEVEL_INFO, msg, True)
+ return True
# TODO - JD: Handle this case.
if event.source == orca_state.locusOfFocus:
@@ -1756,11 +1766,6 @@ class Script(default.Script):
debug.println(debug.LEVEL_INFO, msg, True)
return True
- if self._loadingDocumentContent:
- msg = "WEB: Ignoring because document content is being loaded."
- debug.println(debug.LEVEL_INFO, msg, True)
- return True
-
return False
def onDocumentLoadComplete(self, event):
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index 94a4c9147..3ac4bdd93 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -890,6 +890,36 @@ class Utilities(script_utilities.Utilities):
return -1
+ def findPreviousObject(self, obj):
+ result = super().findPreviousObject(obj)
+ if not (obj and self.inDocumentContent(obj)):
+ return result
+
+ if not (result and self.inDocumentContent(result)):
+ return None
+
+ if self.getTopLevelDocumentForObject(result) != self.getTopLevelDocumentForObject(obj):
+ return None
+
+ msg = "WEB: Previous object for %s is %s." % (obj, result)
+ debug.println(debug.LEVEL_INFO, msg, True)
+ return result
+
+ def findNextObject(self, obj):
+ result = super().findNextObject(obj)
+ if not (obj and self.inDocumentContent(obj)):
+ return result
+
+ if not (result and self.inDocumentContent(result)):
+ return None
+
+ if self.getTopLevelDocumentForObject(result) != self.getTopLevelDocumentForObject(obj):
+ return None
+
+ msg = "WEB: Next object for %s is %s." % (obj, result)
+ debug.println(debug.LEVEL_INFO, msg, True)
+ return result
+
def isNonEntryTextWidget(self, obj):
rv = self._isNonEntryTextWidget.get(hash(obj))
if rv is not None:
@@ -4541,6 +4571,55 @@ class Utilities(script_utilities.Utilities):
self.setCaretContext(replicant, offset, documentFrame)
return True
+ def handleEventForRemovedChild(self, event):
+ if event.any_data != orca_state.locusOfFocus:
+ return False
+
+ msg = "WEB: Removed child is locusOfFocus."
+ debug.println(debug.LEVEL_INFO, msg, True)
+
+ obj, offset = None, -1
+ keyString, mods = self.lastKeyAndModifiers()
+ if keyString == "Up":
+ if event.detail1 >= event.source.childCount:
+ msg = "WEB: Last child removed. Getting new location from end of parent."
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj, offset = self.previousContext(event.source, -1)
+ elif 0 <= event.detail1 - 1 < event.source.childCount:
+ child = event.source[event.detail1 - 1]
+ msg = "WEB: Getting new location from end of previous child %s." % child
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj, offset = self.previousContext(child, -1)
+ else:
+ prevObj = self.findPreviousObject(event.source)
+ msg = "WEB: Getting new location from end of source's previous object %s." % prevObj
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj, offset = self.previousContext(prevObj, -1)
+
+ elif keyString == "Down":
+ if event.detail1 == 0:
+ msg = "WEB: First child removed. Getting new location from start of parent."
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj, offset = self.nextContext(event.source, -1)
+ elif 0 < event.detail1 < event.source.childCount:
+ child = event.source[event.detail1]
+ msg = "WEB: Getting new location from start of child %i %s." % (child, event.detail1)
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj, offset = self.nextContext(child, -1)
+ else:
+ nextObj = self.findNextObject(event.source)
+ msg = "WEB: Getting new location from start of source's next object %s." % nextObj
+ debug.println(debug.LEVEL_INFO, msg, True)
+ obj, offset = self.nextContext(nextObj, -1)
+
+ if obj:
+ msg = "WEB: Setting locusOfFocus and context to: %s, %i" % (obj, offset)
+ orca.setLocusOfFocus(event, obj, True)
+ self.setCaretContext(obj, offset)
+ return True
+
+ return False
+
def findContextReplicant(self, documentFrame=None, matchRole=True, matchName=True):
path, oldRole, oldName = self.getCaretContextPathRoleAndName(documentFrame)
obj = self.getObjectFromPath(path)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]