[orca] Add support for INSERTION, DELETION, and MARK roles
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Add support for INSERTION, DELETION, and MARK roles
- Date: Thu, 23 Jan 2020 17:25:38 +0000 (UTC)
commit ab5fe1e453eb3ab281d63d10524484bb95aa6a5b
Author: Joanmarie Diggs <joanmarie diggs gmail com>
Date: Thu Jan 23 12:24:42 2020 -0500
Add support for INSERTION, DELETION, and MARK roles
src/orca/formatting.py | 12 +++++
src/orca/generator.py | 6 +++
src/orca/messages.py | 30 ++++++++++++
src/orca/script_utilities.py | 9 ++++
src/orca/scripts/web/script_utilities.py | 39 ++++++++++++++++
src/orca/speech_generator.py | 78 ++++++++++++++++++++++++++++++++
6 files changed, 174 insertions(+)
---
diff --git a/src/orca/formatting.py b/src/orca/formatting.py
index a90404c55..1aa151ac1 100644
--- a/src/orca/formatting.py
+++ b/src/orca/formatting.py
@@ -178,6 +178,18 @@ formatting = {
'focused': 'labelOrName + roleName',
'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection',
},
+ # TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one.
+ 'ROLE_CONTENT_DELETION': {
+ 'unfocused': 'deletionStart + pause + displayedText + pause + deletionEnd',
+ },
+ # TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one.
+ 'ROLE_CONTENT_INSERTION': {
+ 'unfocused': 'insertionStart + pause + displayedText + pause + insertionEnd',
+ },
+ # TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one.
+ 'ROLE_CONTENT_MARK': {
+ 'unfocused': 'markStart + pause + displayedText + pause + markEnd',
+ },
pyatspi.ROLE_DESCRIPTION_TERM: {
'unfocused': '(labelOrName or (displayedText + allTextSelection))',
},
diff --git a/src/orca/generator.py b/src/orca/generator.py
index d7b6f5bef..34cf3fedd 100644
--- a/src/orca/generator.py
+++ b/src/orca/generator.py
@@ -1220,6 +1220,12 @@ class Generator:
return pyatspi.ROLE_STATIC
if self._script.utilities.isBlockquote(obj):
return pyatspi.ROLE_BLOCK_QUOTE
+ if self._script.utilities.isContentDeletion(obj):
+ return 'ROLE_CONTENT_DELETION'
+ if self._script.utilities.isContentInsertion(obj):
+ return 'ROLE_CONTENT_INSERTION'
+ if self._script.utilities.isContentMarked(obj):
+ return 'ROLE_CONTENT_MARK'
if self._script.utilities.isLandmark(obj):
return pyatspi.ROLE_LANDMARK
if self._script.utilities.isFocusableLabel(obj):
diff --git a/src/orca/messages.py b/src/orca/messages.py
index dbe8811bf..42e12a221 100644
--- a/src/orca/messages.py
+++ b/src/orca/messages.py
@@ -412,6 +412,36 @@ DATE_FORMAT_ABBREVIATED_DMY = "%a, %-d %b, %Y"
DATE_FORMAT_ABBREVIATED_MDY = "%a, %b %-d, %Y"
DATE_FORMAT_ABBREVIATED_YMD = "%Y. %b %-d, %a."
+# Translators: This phrase is spoken to inform the user that what is about to
+# be said is content marked for deletion in a document, such as content which
+# is inside an HTML 'del' element, or the removed code in a diff.
+CONTENT_DELETION_START = C_("content", "deletion start")
+
+# Translators: This phrase is spoken to inform the user that they have reached
+# the end of content marked for deletion in a document, such as content which
+# is inside an HTML 'del' element, or the removed code in a diff.
+CONTENT_DELETION_END = C_("content", "deletion end")
+
+# Translators: This phrase is spoken to inform the user that what is about to
+# be said is content marked for insertion in a document, such as content which
+# is inside an HTML 'ins' element, or the added code in a diff.
+CONTENT_INSERTION_START = C_("content", "insertion start")
+
+# Translators: This phrase is spoken to inform the user that they have reached
+# the end of content marked for deletion in a document, such as content which
+# is inside an HTML 'ins' element, or the added code in a diff.
+CONTENT_INSERTION_END = C_("content", "insertion end")
+
+# Translators: This phrase is spoken to inform the user that what is about to
+# be said is content marked/highlighted in a document, such as content which
+# is inside an HTML 'mark' element.
+CONTENT_MARK_START = C_("content", "highlight start")
+
+# Translators: This phrase is spoken to inform the user that they have reached
+# the end of content marked/highlighted in a document, such as content which
+# is inside an HTML 'mark' element.
+CONTENT_MARK_END = C_("content", "highlight end")
+
# Translators: This is for navigating document content by moving to the start
# or end of a container. Examples of containers include tables, lists, and
# blockquotes. When moving to the end of a container, Orca attempts to place
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 01ceb1856..cd513c677 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -770,6 +770,15 @@ class Utilities:
return False
+ def isContentDeletion(self, obj):
+ return False
+
+ def isContentInsertion(self, obj):
+ return False
+
+ def isContentMarked(self, obj):
+ return False
+
def isEmpty(self, obj):
return False
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index 921f3369a..2b4957188 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -2113,6 +2113,45 @@ class Utilities(script_utilities.Utilities):
return self._getTag(obj) == 'blockquote'
+ def isContentDeletion(self, obj):
+ if not (obj and self.inDocumentContent(obj)):
+ return super().isContentDeletion(obj)
+
+ # Remove this check when we bump dependencies to 2.34
+ try:
+ if obj.getRole() == pyatspi.ROLE_CONTENT_DELETION:
+ return True
+ except:
+ pass
+
+ return 'deletion' in self._getXMLRoles(obj) or 'del' in self._getTag(obj)
+
+ def isContentInsertion(self, obj):
+ if not (obj and self.inDocumentContent(obj)):
+ return super().isContentInsertion(obj)
+
+ # Remove this check when we bump dependencies to 2.34
+ try:
+ if obj.getRole() == pyatspi.ROLE_CONTENT_INSERTION:
+ return True
+ except:
+ pass
+
+ return 'insertion' in self._getXMLRoles(obj) or 'ins' in self._getTag(obj)
+
+ def isContentMarked(self, obj):
+ if not (obj and self.inDocumentContent(obj)):
+ return super().isContentMarked(obj)
+
+ # Remove this check when we bump dependencies to 2.36
+ try:
+ if obj.getRole() == pyatspi.ROLE_MARK:
+ return True
+ except:
+ pass
+
+ return 'mark' in self._getXMLRoles(obj) or 'mark' in self._getTag(obj)
+
def speakMathSymbolNames(self, obj=None):
obj = obj or orca_state.locusOfFocus
return self.isMath(obj)
diff --git a/src/orca/speech_generator.py b/src/orca/speech_generator.py
index 1f9d05208..6e41be127 100644
--- a/src/orca/speech_generator.py
+++ b/src/orca/speech_generator.py
@@ -306,6 +306,84 @@ class SpeechGenerator(generator.Generator):
result.extend(acss)
return result
+ def _generateDeletionStart(self, obj, **args):
+ if _settingsManager.getSetting('onlySpeakDisplayedText'):
+ return []
+
+ startOffset = args.get('startOffset', 0)
+ if startOffset != 0:
+ return []
+
+ result = [messages.CONTENT_DELETION_START]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateDeletionEnd(self, obj, **args):
+ if _settingsManager.getSetting('onlySpeakDisplayedText'):
+ return []
+
+ endOffset = args.get('endOffset')
+ if endOffset is not None:
+ text = self._script.utilities.queryNonEmptyText(obj)
+ if text and text.characterCount != endOffset:
+ return []
+
+ result = [messages.CONTENT_DELETION_END]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateInsertionStart(self, obj, **args):
+ if _settingsManager.getSetting('onlySpeakDisplayedText'):
+ return []
+
+ startOffset = args.get('startOffset', 0)
+ if startOffset != 0:
+ return []
+
+ result = [messages.CONTENT_INSERTION_START]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateInsertionEnd(self, obj, **args):
+ if _settingsManager.getSetting('onlySpeakDisplayedText'):
+ return []
+
+ endOffset = args.get('endOffset')
+ if endOffset is not None:
+ text = self._script.utilities.queryNonEmptyText(obj)
+ if text and text.characterCount != endOffset:
+ return []
+
+ result = [messages.CONTENT_INSERTION_END]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateMarkStart(self, obj, **args):
+ if _settingsManager.getSetting('onlySpeakDisplayedText'):
+ return []
+
+ startOffset = args.get('startOffset', 0)
+ if startOffset != 0:
+ return []
+
+ result = [messages.CONTENT_MARK_START]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateMarkEnd(self, obj, **args):
+ if _settingsManager.getSetting('onlySpeakDisplayedText'):
+ return []
+
+ endOffset = args.get('endOffset')
+ if endOffset is not None:
+ text = self._script.utilities.queryNonEmptyText(obj)
+ if text and text.characterCount != endOffset:
+ return []
+
+ result = [messages.CONTENT_MARK_END]
+ result.extend(self.voice(SYSTEM))
+ return result
+
def _generateAvailability(self, obj, **args):
if _settingsManager.getSetting('onlySpeakDisplayedText'):
return []
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]