[orca] Web: Support presentation of child position for description list terms
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Web: Support presentation of child position for description list terms
- Date: Wed, 22 Jun 2022 13:49:28 +0000 (UTC)
commit 40d15d91b57398dc95d955dd137131a43fafa9b6
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Wed Jun 22 15:42:49 2022 +0200
Web: Support presentation of child position for description list terms
NOTE: This functionality requires "speak child position" to be enabled
on the "Speech" page in Orca's preferences dialog (it is not enabled by
default).
* Try to get the posinset and setsize values via object attribute
(works for Chrome)
* Fall back on calculating it by iterating through all children
(needed for Firefox)
* Cache results so we don't have to do this iteration every time
See issue #248
src/orca/formatting.py | 2 +-
src/orca/script_utilities.py | 32 +++++++++++++++++++++---------
src/orca/scripts/web/script_utilities.py | 34 ++++++++++++++++++++++++++++++++
src/orca/scripts/web/speech_generator.py | 2 +-
4 files changed, 59 insertions(+), 11 deletions(-)
---
diff --git a/src/orca/formatting.py b/src/orca/formatting.py
index 7e0ff7cff..ac43e7a29 100644
--- a/src/orca/formatting.py
+++ b/src/orca/formatting.py
@@ -209,7 +209,7 @@ formatting = {
'unfocused': 'labelOrName + pause + focusedItem + pause + multiselectableState +
(numberOfChildren or roleName) + pause'
},
pyatspi.ROLE_DESCRIPTION_TERM: {
- 'unfocused': '(labelOrName or (displayedText + allTextSelection) + roleName + pause +
termValueCount)',
+ 'unfocused': '(labelOrName or (displayedText + allTextSelection)) + roleName + pause +
termValueCount + pause + positionInList',
},
pyatspi.ROLE_DESCRIPTION_VALUE: {
'unfocused': '(labelOrName or (displayedText + allTextSelection) + roleName)',
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 496d633bb..4190f741f 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -1229,6 +1229,12 @@ class Utilities:
def isDescriptionListDescription(self, obj):
return obj and obj.getRole() == pyatspi.ROLE_DESCRIPTION_VALUE
+ def descriptionListTerms(self, obj):
+ if not self.isDescriptionList(obj):
+ return []
+
+ return [x for x in obj if self.isDescriptionListTerm(x)]
+
def isDocumentList(self, obj):
if not (obj and obj.getRole() in [pyatspi.ROLE_LIST, pyatspi.ROLE_DESCRIPTION_LIST]):
return False
@@ -5130,7 +5136,7 @@ class Utilities:
return obj.childCount
- def getFunctionalChildren(self, obj):
+ def getFunctionalChildren(self, obj, sibling=None):
if not obj:
return None
@@ -5141,6 +5147,10 @@ class Utilities:
r = relations[0]
result = [r.getTarget(i) for i in range(r.getNTargets())]
+ if not result:
+ if self.isDescriptionListTerm(sibling):
+ return self.descriptionListTerms(obj)
+
return result or [child for child in obj]
def getFunctionalParent(self, obj):
@@ -5182,7 +5192,7 @@ class Utilities:
if childCount > 100 and parent == obj.parent:
return obj.getIndexInParent(), childCount
- siblings = self.getFunctionalChildren(parent)
+ siblings = self.getFunctionalChildren(parent, obj)
if len(siblings) < 100 and not pyatspi.utils.findAncestor(obj, isComboBox):
layoutRoles = [pyatspi.ROLE_SEPARATOR, pyatspi.ROLE_TEAROFF_MENU_ITEM]
isNotLayoutOnly = lambda x: not (self.isZombie(x) or x.getRole() in layoutRoles)
@@ -5200,9 +5210,9 @@ class Utilities:
setSize = len(siblings)
return position, setSize
- def getValueCountForTerm(self, obj):
+ def valuesForTerm(self, obj):
if not self.isDescriptionListTerm(obj):
- return -1
+ return []
try:
index = obj.getIndexInParent()
@@ -5210,15 +5220,19 @@ class Utilities:
except:
msg = "ERROR: Exception getting index and sibling count for %s" % obj
debug.println(debug.LEVEL_INFO, msg, True)
- return -1
+ return []
- count = 0
+ values = []
for i in range(index + 1, total):
- if not self.isDescriptionListDescription(obj.parent[i]):
+ child = obj.parent[i]
+ if not self.isDescriptionListDescription(child):
break
- count += 1
+ values.append(child)
- return count
+ return values
+
+ def getValueCountForTerm(self, obj):
+ return len(self.valuesForTerm(obj))
def getRoleDescription(self, obj, isBraille=False):
return ""
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index 10fb35e41..45c0bc81a 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -106,6 +106,8 @@ class Utilities(script_utilities.Utilities):
self._inferredLabels = {}
self._labelsForObject = {}
self._labelTargets = {}
+ self._descriptionListTerms = {}
+ self._valuesForTerm = {}
self._displayedLabelText = {}
self._mimeType = {}
self._preferDescriptionOverName = {}
@@ -201,6 +203,8 @@ class Utilities(script_utilities.Utilities):
self._inferredLabels = {}
self._labelsForObject = {}
self._labelTargets = {}
+ self._descriptionListTerms = {}
+ self._valuesForTerm = {}
self._displayedLabelText = {}
self._mimeType = {}
self._preferDescriptionOverName = {}
@@ -3666,6 +3670,36 @@ class Utilities(script_utilities.Utilities):
return self._getTag(obj) == "dd"
+ def descriptionListTerms(self, obj):
+ if not obj:
+ return []
+
+ rv = self._descriptionListTerms.get(hash(obj))
+ if rv is not None:
+ return rv
+
+ rv = super().descriptionListTerms(obj)
+ if not self.inDocumentContent(obj):
+ return rv
+
+ self._descriptionListTerms[hash(obj)] = rv
+ return rv
+
+ def valuesForTerm(self, obj):
+ if not obj:
+ return []
+
+ rv = self._valuesForTerm.get(hash(obj))
+ if rv is not None:
+ return rv
+
+ rv = super().valuesForTerm(obj)
+ if not self.inDocumentContent(obj):
+ return rv
+
+ self._valuesForTerm[hash(obj)] = rv
+ return rv
+
def getComboBoxValue(self, obj):
attrs = self.objectAttributes(obj, False)
return attrs.get("valuetext", super().getComboBoxValue(obj))
diff --git a/src/orca/scripts/web/speech_generator.py b/src/orca/scripts/web/speech_generator.py
index 84521589e..ac3d45f0c 100644
--- a/src/orca/scripts/web/speech_generator.py
+++ b/src/orca/scripts/web/speech_generator.py
@@ -471,7 +471,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
setsize = self._script.utilities.getSetSize(obj[0])
if setsize is None:
if self._script.utilities.isDescriptionList(obj):
- children = [x for x in obj if self._script.utilities.isDescriptionListTerm(x)]
+ children = self._script.utilities.descriptionListTerms(obj)
elif role in [pyatspi.ROLE_LIST, pyatspi.ROLE_LIST_BOX]:
children = [x for x in obj if x.getRole() == pyatspi.ROLE_LIST_ITEM]
setsize = len(children)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]