Getting very close to final refactor push. I think one more after this one will do it.

This commit is contained in:
Storm Dragon
2026-01-16 11:14:32 -05:00
parent fde43df2d0
commit 1862de64ee
12 changed files with 232 additions and 113 deletions
+2 -1
View File
@@ -40,6 +40,7 @@ from gi.repository import Atspi
from . import debug from . import debug
from . import object_properties from . import object_properties
from . import role_keys
from .ax_object import AXObject from .ax_object import AXObject
from .ax_utilities_state import AXUtilitiesState from .ax_utilities_state import AXUtilitiesState
@@ -386,7 +387,7 @@ class AXUtilitiesRole:
return object_properties.ROLE_PROLOGUE return object_properties.ROLE_PROLOGUE
if AXUtilitiesRole.is_dpub_toc(obj, role): if AXUtilitiesRole.is_dpub_toc(obj, role):
return object_properties.ROLE_TOC return object_properties.ROLE_TOC
elif role == "ROLE_DPUB_SECTION": elif role == role_keys.ROLE_DPUB_SECTION:
if AXUtilitiesRole.is_dpub_abstract(obj, role): if AXUtilitiesRole.is_dpub_abstract(obj, role):
return object_properties.ROLE_ABSTRACT return object_properties.ROLE_ABSTRACT
if AXUtilitiesRole.is_dpub_colophon(obj, role): if AXUtilitiesRole.is_dpub_colophon(obj, role):
+2 -1
View File
@@ -40,6 +40,7 @@ from . import debug
from . import generator from . import generator
from . import messages from . import messages
from . import object_properties from . import object_properties
from . import role_keys
from . import cthulhu_state from . import cthulhu_state
from . import settings from . import settings
from . import settings_manager from . import settings_manager
@@ -453,7 +454,7 @@ class BrailleGenerator(generator.Generator):
# We will provide the support for someone to override this, # We will provide the support for someone to override this,
# however, so we use REAL_ROLE_SCROLL_PANE here. # however, so we use REAL_ROLE_SCROLL_PANE here.
# #
oldRole = self._overrideRole('REAL_ROLE_SCROLL_PANE', args) oldRole = self._overrideRole(role_keys.REAL_ROLE_SCROLL_PANE, args)
result.extend(self.generate(obj, **args)) result.extend(self.generate(obj, **args))
self._restoreRole(oldRole, args) self._restoreRole(oldRole, args)
return result return result
+24 -23
View File
@@ -44,6 +44,7 @@ gi.require_version("Atspi", "2.0")
from gi.repository import Atspi from gi.repository import Atspi
from . import object_properties from . import object_properties
from . import role_keys
TUTORIAL = '(tutorial and (pause + tutorial) or [])' TUTORIAL = '(tutorial and (pause + tutorial) or [])'
MNEMONIC = '(mnemonic and (pause + mnemonic + lineBreak) or [])' MNEMONIC = '(mnemonic and (pause + mnemonic + lineBreak) or [])'
@@ -153,7 +154,7 @@ formatting = {
'focused': 'labelOrName + roleName', 'focused': 'labelOrName + roleName',
'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection', 'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection',
}, },
'ROLE_ARTICLE_IN_FEED' : { role_keys.ROLE_ARTICLE_IN_FEED: {
'unfocused': '(labelOrName or currentLineText or roleName) + pause + positionInList', 'unfocused': '(labelOrName or currentLineText or roleName) + pause + positionInList',
}, },
Atspi.Role.BLOCK_QUOTE: { Atspi.Role.BLOCK_QUOTE: {
@@ -197,25 +198,25 @@ formatting = {
'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection', 'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection',
}, },
# TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one.
'ROLE_CONTENT_DELETION': { role_keys.ROLE_CONTENT_DELETION: {
'focused': 'leaving or deletionStart', 'focused': 'leaving or deletionStart',
'unfocused': 'deletionStart + pause + displayedText + pause + deletionEnd', 'unfocused': 'deletionStart + pause + displayedText + pause + deletionEnd',
}, },
'ROLE_CONTENT_ERROR': { role_keys.ROLE_CONTENT_ERROR: {
'unfocused': 'displayedText + pause + invalid', 'unfocused': 'displayedText + pause + invalid',
}, },
# TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one.
'ROLE_CONTENT_INSERTION': { role_keys.ROLE_CONTENT_INSERTION: {
'focused': 'leaving or insertionStart', 'focused': 'leaving or insertionStart',
'unfocused': 'insertionStart + pause + displayedText + pause + insertionEnd', 'unfocused': 'insertionStart + pause + displayedText + pause + insertionEnd',
}, },
# TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one.
'ROLE_CONTENT_MARK': { role_keys.ROLE_CONTENT_MARK: {
'focused': 'leaving or markStart', 'focused': 'leaving or markStart',
'unfocused': 'markStart + pause + displayedText + pause + markEnd', 'unfocused': 'markStart + pause + displayedText + pause + markEnd',
}, },
# TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one.
'ROLE_CONTENT_SUGGESTION': { role_keys.ROLE_CONTENT_SUGGESTION: {
'focused': 'leaving or roleName', 'focused': 'leaving or roleName',
}, },
Atspi.Role.DESCRIPTION_LIST: { Atspi.Role.DESCRIPTION_LIST: {
@@ -247,11 +248,11 @@ formatting = {
'basicWhereAmI': 'labelOrName + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC, 'basicWhereAmI': 'labelOrName + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
'detailedWhereAmI': 'labelorName + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC 'detailedWhereAmI': 'labelorName + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC
}, },
'ROLE_DPUB_LANDMARK': { role_keys.ROLE_DPUB_LANDMARK: {
'focused': 'leaving or labelOrName', 'focused': 'leaving or labelOrName',
'unfocused': 'labelOrName + currentLineText + allTextSelection' 'unfocused': 'labelOrName + currentLineText + allTextSelection'
}, },
'ROLE_DPUB_SECTION': { role_keys.ROLE_DPUB_SECTION: {
'focused': 'leaving or (labelOrName + roleName)', 'focused': 'leaving or (labelOrName + roleName)',
'unfocused': 'labelOrName + currentLineText + allTextSelection' 'unfocused': 'labelOrName + currentLineText + allTextSelection'
}, },
@@ -265,7 +266,7 @@ formatting = {
'basicWhereAmI': 'labelOrName + readOnly + textRole + (textContent or placeholderText) + anyTextSelection + required + pause + invalid + ' + MNEMONIC, 'basicWhereAmI': 'labelOrName + readOnly + textRole + (textContent or placeholderText) + anyTextSelection + required + pause + invalid + ' + MNEMONIC,
'detailedWhereAmI': 'labelOrName + readOnly + textRole + (textContentWithAttributes or placeholderText) + anyTextSelection + required + pause + invalid + ' + MNEMONIC, 'detailedWhereAmI': 'labelOrName + readOnly + textRole + (textContentWithAttributes or placeholderText) + anyTextSelection + required + pause + invalid + ' + MNEMONIC,
}, },
'ROLE_FEED': { role_keys.ROLE_FEED: {
'focused': 'leaving or (labelOrName + pause + (numberOfChildren or roleName))', 'focused': 'leaving or (labelOrName + pause + (numberOfChildren or roleName))',
'unfocused': 'labelOrName + pause + (numberOfChildren or roleName)', 'unfocused': 'labelOrName + pause + (numberOfChildren or roleName)',
}, },
@@ -341,11 +342,11 @@ formatting = {
'unfocused': 'math', 'unfocused': 'math',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_ENCLOSED': { role_keys.ROLE_MATH_ENCLOSED: {
'unfocused': 'enclosedBase + enclosedEnclosures', 'unfocused': 'enclosedBase + enclosedEnclosures',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_FENCED': { role_keys.ROLE_MATH_FENCED: {
'unfocused': 'fencedStart + pause + fencedContents + pause + fencedEnd', 'unfocused': 'fencedStart + pause + fencedContents + pause + fencedEnd',
}, },
Atspi.Role.MATH_FRACTION: { Atspi.Role.MATH_FRACTION: {
@@ -355,23 +356,23 @@ formatting = {
'unfocused': 'rootStart + rootBase + pause + rootEnd + pause', 'unfocused': 'rootStart + rootBase + pause + rootEnd + pause',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_MULTISCRIPT': { role_keys.ROLE_MATH_MULTISCRIPT: {
'unfocused': 'scriptBase + pause + scriptPrescripts + pause + scriptPostscripts + pause', 'unfocused': 'scriptBase + pause + scriptPrescripts + pause + scriptPostscripts + pause',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_SCRIPT_SUBSUPER': { role_keys.ROLE_MATH_SCRIPT_SUBSUPER: {
'unfocused': 'scriptBase + pause + scriptSubscript + pause + scriptSuperscript + pause', 'unfocused': 'scriptBase + pause + scriptSubscript + pause + scriptSuperscript + pause',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_SCRIPT_UNDEROVER': { role_keys.ROLE_MATH_SCRIPT_UNDEROVER: {
'unfocused': 'scriptBase + pause + scriptUnderscript + pause + scriptOverscript + pause', 'unfocused': 'scriptBase + pause + scriptUnderscript + pause + scriptOverscript + pause',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_TABLE': { role_keys.ROLE_MATH_TABLE: {
'unfocused': 'mathTableStart + pause + mathTableRows + pause + mathTableEnd + pause', 'unfocused': 'mathTableStart + pause + mathTableRows + pause + mathTableEnd + pause',
}, },
# TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one.
'ROLE_MATH_TABLE_ROW': { role_keys.ROLE_MATH_TABLE_ROW: {
'unfocused': 'mathRow', 'unfocused': 'mathRow',
}, },
Atspi.Role.MENU: { Atspi.Role.MENU: {
@@ -440,7 +441,7 @@ formatting = {
'unfocused': 'labelOrName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList', 'unfocused': 'labelOrName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
'basicWhereAmI': 'ancestors + labelOrName + roleName + radioState + accelerator + positionInList + ' + MNEMONIC 'basicWhereAmI': 'ancestors + labelOrName + roleName + radioState + accelerator + positionInList + ' + MNEMONIC
}, },
'ROLE_REGION': { role_keys.ROLE_REGION: {
'focused': 'leaving or (roleName + labelOrName)', 'focused': 'leaving or (roleName + labelOrName)',
'unfocused': 'labelOrName + roleName + currentLineText + allTextSelection' 'unfocused': 'labelOrName + roleName + currentLineText + allTextSelection'
}, },
@@ -492,7 +493,7 @@ formatting = {
Atspi.Role.SUPERSCRIPT: { Atspi.Role.SUPERSCRIPT: {
'unfocused': 'roleName + currentLineText + allTextSelection', 'unfocused': 'roleName + currentLineText + allTextSelection',
}, },
'ROLE_SWITCH': { role_keys.ROLE_SWITCH: {
'focused': 'switchState', 'focused': 'switchState',
'unfocused': 'labelOrName + roleName + switchState + availability + ' + MNEMONIC + ' + accelerator', 'unfocused': 'labelOrName + roleName + switchState + availability + ' + MNEMONIC + ' + accelerator',
'basicWhereAmI': 'labelOrName + roleName + switchState' 'basicWhereAmI': 'labelOrName + roleName + switchState'
@@ -509,7 +510,7 @@ formatting = {
'basicWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + expandableState + pause + nodeLevel + pause', 'basicWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + expandableState + pause + nodeLevel + pause',
'detailedWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + tableCellRow + pause + expandableState + pause + nodeLevel + pause', 'detailedWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + tableCellRow + pause + expandableState + pause + nodeLevel + pause',
}, },
'REAL_ROLE_TABLE_CELL': { role_keys.REAL_ROLE_TABLE_CELL: {
# the real cell information # the real cell information
# note that Atspi.Role.TABLE_CELL is used to work out if we need to # note that Atspi.Role.TABLE_CELL is used to work out if we need to
# read a whole row. It calls REAL_ROLE_TABLE_CELL internally. # read a whole row. It calls REAL_ROLE_TABLE_CELL internally.
@@ -630,7 +631,7 @@ formatting = {
or ([Component(obj, asString(labelAndName + roleName))]\ or ([Component(obj, asString(labelAndName + roleName))]\
+ (childWidget and ([Region(" ")] + childWidget))))' + (childWidget and ([Region(" ")] + childWidget))))'
}, },
'ROLE_ARTICLE_IN_FEED': { role_keys.ROLE_ARTICLE_IN_FEED: {
'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\
or ([Component(obj, asString(labelOrName + roleName))]))' or ([Component(obj, asString(labelOrName + roleName))]))'
}, },
@@ -830,7 +831,7 @@ formatting = {
'unfocused': '[Component(obj, asString(labelOrName + roleName))]\ 'unfocused': '[Component(obj, asString(labelOrName + roleName))]\
+ [Region(" ")] + statusBar', + [Region(" ")] + statusBar',
}, },
'ROLE_SWITCH' : { role_keys.ROLE_SWITCH: {
'unfocused': '[Component(obj,\ 'unfocused': '[Component(obj,\
asString((labelOrName or description) + roleName),\ asString((labelOrName or description) + roleName),\
indicator=asString(switchState))]' indicator=asString(switchState))]'
@@ -840,7 +841,7 @@ formatting = {
Atspi.Role.TABLE_CELL: { Atspi.Role.TABLE_CELL: {
'unfocused': '((substring and ' + BRAILLE_TEXT + ') or tableCellRow)', 'unfocused': '((substring and ' + BRAILLE_TEXT + ') or tableCellRow)',
}, },
'REAL_ROLE_TABLE_CELL': { role_keys.REAL_ROLE_TABLE_CELL: {
'unfocused': '((tableCell2ChildToggle + tableCell2ChildLabel)\ 'unfocused': '((tableCell2ChildToggle + tableCell2ChildLabel)\
or (substring and ' + BRAILLE_TEXT + ') \ or (substring and ' + BRAILLE_TEXT + ') \
or (cellCheckedState\ or (cellCheckedState\
@@ -992,7 +993,7 @@ formatting = {
'focused': 'percentage', 'focused': 'percentage',
'unfocused': 'roleName + percentage + availability', 'unfocused': 'roleName + percentage + availability',
}, },
'ROLE_SWITCH': { role_keys.ROLE_SWITCH: {
'focused': 'switchState', 'focused': 'switchState',
'unfocused': 'switchState + availability', 'unfocused': 'switchState + availability',
}, },
+91 -39
View File
@@ -48,6 +48,7 @@ from . import braille
from . import debug from . import debug
from . import messages from . import messages
from . import object_properties from . import object_properties
from . import role_keys
from . import settings from . import settings
from . import settings_manager from . import settings_manager
from .ax_object import AXObject from .ax_object import AXObject
@@ -954,7 +955,7 @@ class Generator:
cells. cells.
""" """
result = [] result = []
oldRole = self._overrideRole('REAL_ROLE_TABLE_CELL', args) oldRole = self._overrideRole(role_keys.REAL_ROLE_TABLE_CELL, args)
result.extend(self.generate(obj, **args)) result.extend(self.generate(obj, **args))
self._restoreRole(oldRole, args) self._restoreRole(oldRole, args)
return result return result
@@ -1299,62 +1300,113 @@ class Generator:
self._activeProgressBars[obj] = lastTime, lastValue self._activeProgressBars[obj] = lastTime, lastValue
def _getAlternativeRole(self, obj, **args): def _getAlternativeRole(self, obj, **args):
if self._script.utilities.isMath(obj): role = self._getMathAlternativeRole(obj)
if self._script.utilities.isMathSubOrSuperScript(obj): if role:
return 'ROLE_MATH_SCRIPT_SUBSUPER' return role
if self._script.utilities.isMathUnderOrOverScript(obj):
return 'ROLE_MATH_SCRIPT_UNDEROVER' role = self._getDPubAlternativeRole(obj)
if self._script.utilities.isMathMultiScript(obj): if role:
return 'ROLE_MATH_MULTISCRIPT' return role
if self._script.utilities.isMathEnclose(obj):
return 'ROLE_MATH_ENCLOSED' role = self._getSwitchOrSpecialRole(obj)
if self._script.utilities.isMathFenced(obj): if role:
return 'ROLE_MATH_FENCED' return role
if self._script.utilities.isMathTable(obj):
return 'ROLE_MATH_TABLE' role = self._getContentAlternativeRole(obj)
if self._script.utilities.isMathTableRow(obj): if role:
return 'ROLE_MATH_TABLE_ROW' return role
if self._script.utilities.isDPub(obj):
if self._script.utilities.isLandmark(obj): role = self._getDescriptionListRole(obj)
return 'ROLE_DPUB_LANDMARK' if role:
if AXUtilities.is_section(obj): return role
return 'ROLE_DPUB_SECTION'
role = self._getFeedAlternativeRole(obj)
if role:
return role
role = self._getLandmarkAlternativeRole(obj)
if role:
return role
if self._script.utilities.isDocument(obj) and AXObject.supports_image(obj):
return Atspi.Role.IMAGE
return args.get('role', AXObject.get_role(obj))
def _getMathAlternativeRole(self, obj):
if not self._script.utilities.isMath(obj):
return None
if self._script.utilities.isMathSubOrSuperScript(obj):
return role_keys.ROLE_MATH_SCRIPT_SUBSUPER
if self._script.utilities.isMathUnderOrOverScript(obj):
return role_keys.ROLE_MATH_SCRIPT_UNDEROVER
if self._script.utilities.isMathMultiScript(obj):
return role_keys.ROLE_MATH_MULTISCRIPT
if self._script.utilities.isMathEnclose(obj):
return role_keys.ROLE_MATH_ENCLOSED
if self._script.utilities.isMathFenced(obj):
return role_keys.ROLE_MATH_FENCED
if self._script.utilities.isMathTable(obj):
return role_keys.ROLE_MATH_TABLE
if self._script.utilities.isMathTableRow(obj):
return role_keys.ROLE_MATH_TABLE_ROW
return None
def _getDPubAlternativeRole(self, obj):
if not self._script.utilities.isDPub(obj):
return None
if self._script.utilities.isLandmark(obj):
return role_keys.ROLE_DPUB_LANDMARK
if AXUtilities.is_section(obj):
return role_keys.ROLE_DPUB_SECTION
return None
def _getSwitchOrSpecialRole(self, obj):
if self._script.utilities.isSwitch(obj): if self._script.utilities.isSwitch(obj):
return 'ROLE_SWITCH' return role_keys.ROLE_SWITCH
if self._script.utilities.isAnchor(obj): if self._script.utilities.isAnchor(obj):
return Atspi.Role.STATIC return Atspi.Role.STATIC
if self._script.utilities.isBlockquote(obj): if self._script.utilities.isBlockquote(obj):
return Atspi.Role.BLOCK_QUOTE return Atspi.Role.BLOCK_QUOTE
if self._script.utilities.isComment(obj): if self._script.utilities.isComment(obj):
return Atspi.Role.COMMENT return Atspi.Role.COMMENT
return None
def _getContentAlternativeRole(self, obj):
if self._script.utilities.isContentDeletion(obj): if self._script.utilities.isContentDeletion(obj):
return 'ROLE_CONTENT_DELETION' return role_keys.ROLE_CONTENT_DELETION
if self._script.utilities.isContentError(obj): if self._script.utilities.isContentError(obj):
return 'ROLE_CONTENT_ERROR' return role_keys.ROLE_CONTENT_ERROR
if self._script.utilities.isContentInsertion(obj): if self._script.utilities.isContentInsertion(obj):
return 'ROLE_CONTENT_INSERTION' return role_keys.ROLE_CONTENT_INSERTION
if self._script.utilities.isContentMarked(obj): if self._script.utilities.isContentMarked(obj):
return 'ROLE_CONTENT_MARK' return role_keys.ROLE_CONTENT_MARK
if self._script.utilities.isContentSuggestion(obj): if self._script.utilities.isContentSuggestion(obj):
return 'ROLE_CONTENT_SUGGESTION' return role_keys.ROLE_CONTENT_SUGGESTION
return None
def _getDescriptionListRole(self, obj):
if self._script.utilities.isDescriptionList(obj): if self._script.utilities.isDescriptionList(obj):
return Atspi.Role.DESCRIPTION_LIST return Atspi.Role.DESCRIPTION_LIST
if self._script.utilities.isDescriptionListTerm(obj): if self._script.utilities.isDescriptionListTerm(obj):
return Atspi.Role.DESCRIPTION_TERM return Atspi.Role.DESCRIPTION_TERM
if self._script.utilities.isDescriptionListDescription(obj): if self._script.utilities.isDescriptionListDescription(obj):
return Atspi.Role.DESCRIPTION_VALUE return Atspi.Role.DESCRIPTION_VALUE
if self._script.utilities.isFeedArticle(obj): return None
return 'ROLE_ARTICLE_IN_FEED'
if self._script.utilities.isFeed(obj):
return 'ROLE_FEED'
if self._script.utilities.isLandmark(obj):
if self._script.utilities.isLandmarkRegion(obj):
return 'ROLE_REGION'
return Atspi.Role.LANDMARK
if self._script.utilities.isDocument(obj) and AXObject.supports_image(obj):
return Atspi.Role.IMAGE
return args.get('role', AXObject.get_role(obj)) def _getFeedAlternativeRole(self, obj):
if self._script.utilities.isFeedArticle(obj):
return role_keys.ROLE_ARTICLE_IN_FEED
if self._script.utilities.isFeed(obj):
return role_keys.ROLE_FEED
return None
def _getLandmarkAlternativeRole(self, obj):
if not self._script.utilities.isLandmark(obj):
return None
if self._script.utilities.isLandmarkRegion(obj):
return role_keys.ROLE_REGION
return Atspi.Role.LANDMARK
def getLocalizedRoleName(self, obj, **args): def getLocalizedRoleName(self, obj, **args):
role = args.get('role', AXObject.get_role(obj)) role = args.get('role', AXObject.get_role(obj))
@@ -1435,7 +1487,7 @@ class Generator:
return object_properties.ROLE_PROLOGUE return object_properties.ROLE_PROLOGUE
if self._script.utilities.isDPubToc(obj): if self._script.utilities.isDPubToc(obj):
return object_properties.ROLE_TOC return object_properties.ROLE_TOC
elif role == "ROLE_DPUB_SECTION": elif role == role_keys.ROLE_DPUB_SECTION:
if self._script.utilities.isDPubAbstract(obj): if self._script.utilities.isDPubAbstract(obj):
return object_properties.ROLE_ABSTRACT return object_properties.ROLE_ABSTRACT
if self._script.utilities.isDPubColophon(obj): if self._script.utilities.isDPubColophon(obj):
+1
View File
@@ -77,6 +77,7 @@ cthulhu_python_sources = files([
'pronunciation_dict.py', 'pronunciation_dict.py',
'punctuation_settings.py', 'punctuation_settings.py',
'resource_manager.py', 'resource_manager.py',
'role_keys.py',
'script.py', 'script.py',
'script_manager.py', 'script_manager.py',
'script_utilities.py', 'script_utilities.py',
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
#
# Copyright (c) 2026 Stormux
# Copyright (c) 2010-2012 The Orca Team
# Copyright (c) 2012 Igalia, S.L.
# Copyright (c) 2005-2010 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
#
# Forked from Orca screen reader.
# Cthulhu project: https://git.stormux.org/storm/cthulhu
"""Shared role key constants for formatting and generators."""
__id__ = "$Id$"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
__license__ = "LGPL"
# Custom role keys used by formatting and role override logic.
ROLE_ARTICLE_IN_FEED = 'ROLE_ARTICLE_IN_FEED'
ROLE_CONTENT_DELETION = 'ROLE_CONTENT_DELETION'
ROLE_CONTENT_ERROR = 'ROLE_CONTENT_ERROR'
ROLE_CONTENT_INSERTION = 'ROLE_CONTENT_INSERTION'
ROLE_CONTENT_MARK = 'ROLE_CONTENT_MARK'
ROLE_CONTENT_SUGGESTION = 'ROLE_CONTENT_SUGGESTION'
ROLE_DPUB_LANDMARK = 'ROLE_DPUB_LANDMARK'
ROLE_DPUB_SECTION = 'ROLE_DPUB_SECTION'
ROLE_FEED = 'ROLE_FEED'
ROLE_MATH_ENCLOSED = 'ROLE_MATH_ENCLOSED'
ROLE_MATH_FENCED = 'ROLE_MATH_FENCED'
ROLE_MATH_MULTISCRIPT = 'ROLE_MATH_MULTISCRIPT'
ROLE_MATH_SCRIPT_SUBSUPER = 'ROLE_MATH_SCRIPT_SUBSUPER'
ROLE_MATH_SCRIPT_UNDEROVER = 'ROLE_MATH_SCRIPT_UNDEROVER'
ROLE_MATH_TABLE = 'ROLE_MATH_TABLE'
ROLE_MATH_TABLE_ROW = 'ROLE_MATH_TABLE_ROW'
ROLE_REGION = 'ROLE_REGION'
ROLE_SWITCH = 'ROLE_SWITCH'
ROLE_SPREADSHEET_CELL = 'ROLE_SPREADSHEET_CELL'
# Formatting override keys (not real Atspi roles).
REAL_ROLE_TABLE_CELL = 'REAL_ROLE_TABLE_CELL'
REAL_ROLE_SCROLL_PANE = 'REAL_ROLE_SCROLL_PANE'
@@ -43,6 +43,7 @@ gi.require_version("Atspi", "2.0")
from gi.repository import Atspi from gi.repository import Atspi
import cthulhu.formatting import cthulhu.formatting
import cthulhu.role_keys
import cthulhu.settings import cthulhu.settings
formatting = { formatting = {
@@ -53,11 +54,11 @@ formatting = {
'basicWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + expandableState + pause + nodeLevel + pause', 'basicWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + expandableState + pause + nodeLevel + pause',
'detailedWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + tableCellRow + pause + expandableState + pause + nodeLevel + pause' 'detailedWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + tableCellRow + pause + expandableState + pause + nodeLevel + pause'
}, },
'REAL_ROLE_TABLE_CELL': { cthulhu.role_keys.REAL_ROLE_TABLE_CELL: {
'focused': 'newRowHeader + newColumnHeader + realActiveDescendantDisplayedText', 'focused': 'newRowHeader + newColumnHeader + realActiveDescendantDisplayedText',
'unfocused': 'newRowHeader + newColumnHeader + realActiveDescendantDisplayedText', 'unfocused': 'newRowHeader + newColumnHeader + realActiveDescendantDisplayedText',
}, },
'ROLE_SPREADSHEET_CELL': { cthulhu.role_keys.ROLE_SPREADSHEET_CELL: {
# We treat spreadsheet cells differently from other table cells in # We treat spreadsheet cells differently from other table cells in
# whereAmI. # whereAmI.
# #
@@ -36,6 +36,7 @@ gi.require_version("Atspi", "2.0")
from gi.repository import Atspi from gi.repository import Atspi
import cthulhu.messages as messages import cthulhu.messages as messages
import cthulhu.role_keys as role_keys
import cthulhu.settings_manager as settings_manager import cthulhu.settings_manager as settings_manager
import cthulhu.speech_generator as speech_generator import cthulhu.speech_generator as speech_generator
from cthulhu.ax_object import AXObject from cthulhu.ax_object import AXObject
@@ -75,7 +76,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
# Treat a paragraph which is inside of a spreadsheet cell as # Treat a paragraph which is inside of a spreadsheet cell as
# a spreadsheet cell. # a spreadsheet cell.
# #
elif role == 'ROLE_SPREADSHEET_CELL': elif role == role_keys.ROLE_SPREADSHEET_CELL:
oldRole = self._overrideRole(Atspi.Role.TABLE_CELL, args) oldRole = self._overrideRole(Atspi.Role.TABLE_CELL, args)
override = True override = True
result.extend(speech_generator.SpeechGenerator._generateRoleName( result.extend(speech_generator.SpeechGenerator._generateRoleName(
@@ -502,7 +503,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
result = [] result = []
if args.get('formatType', 'unfocused') == 'basicWhereAmI' \ if args.get('formatType', 'unfocused') == 'basicWhereAmI' \
and self._script.utilities.isSpreadSheetCell(obj): and self._script.utilities.isSpreadSheetCell(obj):
oldRole = self._overrideRole('ROLE_SPREADSHEET_CELL', args) oldRole = self._overrideRole(role_keys.ROLE_SPREADSHEET_CELL, args)
# In addition, if focus is in a cell being edited, we cannot # In addition, if focus is in a cell being edited, we cannot
# query the accessible table interface for coordinates and the # query the accessible table interface for coordinates and the
# like because we're temporarily in an entirely different object # like because we're temporarily in an entirely different object
+4 -3
View File
@@ -41,6 +41,7 @@ from cthulhu import debug
from cthulhu import input_event_manager from cthulhu import input_event_manager
from cthulhu import messages from cthulhu import messages
from cthulhu import object_properties from cthulhu import object_properties
from cthulhu import role_keys
from cthulhu import cthulhu_state from cthulhu import cthulhu_state
from cthulhu import settings from cthulhu import settings
from cthulhu import settings_manager from cthulhu import settings_manager
@@ -491,7 +492,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
roles = [Atspi.Role.DESCRIPTION_LIST, roles = [Atspi.Role.DESCRIPTION_LIST,
Atspi.Role.LIST, Atspi.Role.LIST,
Atspi.Role.LIST_BOX, Atspi.Role.LIST_BOX,
'ROLE_FEED'] role_keys.ROLE_FEED]
role = args.get('role', AXObject.get_role(obj)) role = args.get('role', AXObject.get_role(obj))
if role not in roles: if role not in roles:
return super()._generateNumberOfChildren(obj, **args) return super()._generateNumberOfChildren(obj, **args)
@@ -510,7 +511,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
if self._script.utilities.isDescriptionList(obj): if self._script.utilities.isDescriptionList(obj):
result = [messages.descriptionListTermCount(setsize)] result = [messages.descriptionListTermCount(setsize)]
elif role == 'ROLE_FEED': elif role == role_keys.ROLE_FEED:
result = [messages.feedArticleCount(setsize)] result = [messages.feedArticleCount(setsize)]
else: else:
result = [messages.listItemCount(setsize)] result = [messages.listItemCount(setsize)]
@@ -597,7 +598,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
doNotSpeak.append(Atspi.Role.TEXT) doNotSpeak.append(Atspi.Role.TEXT)
doNotSpeak.append(Atspi.Role.STATIC) doNotSpeak.append(Atspi.Role.STATIC)
if args.get('string'): if args.get('string'):
doNotSpeak.append("ROLE_CONTENT_SUGGESTION") doNotSpeak.append(role_keys.ROLE_CONTENT_SUGGESTION)
if args.get('formatType', 'unfocused') != 'basicWhereAmI': if args.get('formatType', 'unfocused') != 'basicWhereAmI':
doNotSpeak.append(Atspi.Role.LIST_ITEM) doNotSpeak.append(Atspi.Role.LIST_ITEM)
doNotSpeak.append(Atspi.Role.LIST) doNotSpeak.append(Atspi.Role.LIST)
+2 -1
View File
@@ -39,6 +39,7 @@ import os
from . import cthulhu # Need access to cthulhuApp from . import cthulhu # Need access to cthulhuApp
from . import generator from . import generator
from . import role_keys
from . import settings_manager from . import settings_manager
from .ax_object import AXObject from .ax_object import AXObject
from .ax_utilities import AXUtilities from .ax_utilities import AXUtilities
@@ -373,7 +374,7 @@ class SoundGenerator(generator.Generator):
role = args.get('role', AXObject.get_role(obj)) role = args.get('role', AXObject.get_role(obj))
if isinstance(role, str): if isinstance(role, str):
if role == "ROLE_SWITCH": if role == role_keys.ROLE_SWITCH:
role = Atspi.Role.SWITCH role = Atspi.Role.SWITCH
else: else:
return [] return []
+2 -2
View File
@@ -41,6 +41,7 @@ from gi.repository import GLib
from gi.repository import Atspi from gi.repository import Atspi
from . import debug from . import debug
from . import role_keys
from . import sound from . import sound
from .sound_generator import Icon from .sound_generator import Icon
@@ -244,7 +245,7 @@ class SoundThemeManager:
def _normalizeRole(self, role): def _normalizeRole(self, role):
if isinstance(role, str): if isinstance(role, str):
if role == "ROLE_SWITCH": if role == role_keys.ROLE_SWITCH:
return Atspi.Role.SWITCH return Atspi.Role.SWITCH
return None return None
return role return role
@@ -395,4 +396,3 @@ def getManager():
_manager = SoundThemeManager(cthulhu.cthulhuApp) _manager = SoundThemeManager(cthulhu.cthulhuApp)
return _manager return _manager
+41 -39
View File
@@ -48,6 +48,7 @@ from . import debug
from . import generator from . import generator
from . import messages from . import messages
from . import object_properties from . import object_properties
from . import role_keys
from . import settings from . import settings
from . import settings_manager from . import settings_manager
from . import sound_theme_manager from . import sound_theme_manager
@@ -275,7 +276,7 @@ class SpeechGenerator(generator.Generator):
def _getRoleNameStripCandidates(self, obj, role=None): def _getRoleNameStripCandidates(self, obj, role=None):
normalizedRole = role normalizedRole = role
if isinstance(normalizedRole, str): if isinstance(normalizedRole, str):
if normalizedRole == "ROLE_SWITCH": if normalizedRole == role_keys.ROLE_SWITCH:
normalizedRole = Atspi.Role.SWITCH normalizedRole = Atspi.Role.SWITCH
else: else:
normalizedRole = None normalizedRole = None
@@ -1199,7 +1200,7 @@ class SpeechGenerator(generator.Generator):
cell itself. The string, 'blank', is added for empty cells. cell itself. The string, 'blank', is added for empty cells.
""" """
result = [] result = []
oldRole = self._overrideRole('REAL_ROLE_TABLE_CELL', args) oldRole = self._overrideRole(role_keys.REAL_ROLE_TABLE_CELL, args)
result.extend(self.generate(obj, **args)) result.extend(self.generate(obj, **args))
self._restoreRole(oldRole, args) self._restoreRole(oldRole, args)
if not (result and result[0]) \ if not (result and result[0]) \
@@ -1970,19 +1971,19 @@ class SpeechGenerator(generator.Generator):
def _getEnabledAndDisabledContextRoles(self): def _getEnabledAndDisabledContextRoles(self):
allRoles = [Atspi.Role.BLOCK_QUOTE, allRoles = [Atspi.Role.BLOCK_QUOTE,
'ROLE_CONTENT_DELETION', role_keys.ROLE_CONTENT_DELETION,
'ROLE_CONTENT_INSERTION', role_keys.ROLE_CONTENT_INSERTION,
'ROLE_CONTENT_MARK', role_keys.ROLE_CONTENT_MARK,
'ROLE_CONTENT_SUGGESTION', role_keys.ROLE_CONTENT_SUGGESTION,
'ROLE_DPUB_LANDMARK', role_keys.ROLE_DPUB_LANDMARK,
'ROLE_DPUB_SECTION', role_keys.ROLE_DPUB_SECTION,
Atspi.Role.DESCRIPTION_LIST, Atspi.Role.DESCRIPTION_LIST,
'ROLE_FEED', role_keys.ROLE_FEED,
Atspi.Role.FORM, Atspi.Role.FORM,
Atspi.Role.LANDMARK, Atspi.Role.LANDMARK,
Atspi.Role.LIST, Atspi.Role.LIST,
Atspi.Role.PANEL, Atspi.Role.PANEL,
'ROLE_REGION', role_keys.ROLE_REGION,
Atspi.Role.TABLE, Atspi.Role.TABLE,
Atspi.Role.TOOL_TIP] Atspi.Role.TOOL_TIP]
@@ -1991,19 +1992,19 @@ class SpeechGenerator(generator.Generator):
if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextBlockquote'): if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextBlockquote'):
enabled.append(Atspi.Role.BLOCK_QUOTE) enabled.append(Atspi.Role.BLOCK_QUOTE)
if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextLandmark'): if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextLandmark'):
enabled.extend([Atspi.Role.LANDMARK, 'ROLE_DPUB_LANDMARK']) enabled.extend([Atspi.Role.LANDMARK, role_keys.ROLE_DPUB_LANDMARK])
if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextList'): if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextList'):
enabled.append(Atspi.Role.LIST) enabled.append(Atspi.Role.LIST)
enabled.append(Atspi.Role.DESCRIPTION_LIST) enabled.append(Atspi.Role.DESCRIPTION_LIST)
enabled.append('ROLE_FEED') enabled.append(role_keys.ROLE_FEED)
if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextPanel'): if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextPanel'):
enabled.extend([Atspi.Role.PANEL, enabled.extend([Atspi.Role.PANEL,
Atspi.Role.TOOL_TIP, Atspi.Role.TOOL_TIP,
'ROLE_CONTENT_DELETION', role_keys.ROLE_CONTENT_DELETION,
'ROLE_CONTENT_INSERTION', role_keys.ROLE_CONTENT_INSERTION,
'ROLE_CONTENT_MARK', role_keys.ROLE_CONTENT_MARK,
'ROLE_CONTENT_SUGGESTION', role_keys.ROLE_CONTENT_SUGGESTION,
'ROLE_DPUB_SECTION']) role_keys.ROLE_DPUB_SECTION])
if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextNonLandmarkForm'): if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextNonLandmarkForm'):
enabled.append(Atspi.Role.FORM) enabled.append(Atspi.Role.FORM)
if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextTable'): if cthulhu.cthulhuApp.settingsManager.getSetting('sayAllContextTable'):
@@ -2012,19 +2013,20 @@ class SpeechGenerator(generator.Generator):
if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextBlockquote'): if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextBlockquote'):
enabled.append(Atspi.Role.BLOCK_QUOTE) enabled.append(Atspi.Role.BLOCK_QUOTE)
if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextLandmark'): if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextLandmark'):
enabled.extend([Atspi.Role.LANDMARK, 'ROLE_DPUB_LANDMARK', 'ROLE_REGION']) enabled.extend([Atspi.Role.LANDMARK, role_keys.ROLE_DPUB_LANDMARK,
role_keys.ROLE_REGION])
if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextList'): if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextList'):
enabled.append(Atspi.Role.LIST) enabled.append(Atspi.Role.LIST)
enabled.append(Atspi.Role.DESCRIPTION_LIST) enabled.append(Atspi.Role.DESCRIPTION_LIST)
enabled.append('ROLE_FEED') enabled.append(role_keys.ROLE_FEED)
if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextPanel'): if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextPanel'):
enabled.extend([Atspi.Role.PANEL, enabled.extend([Atspi.Role.PANEL,
Atspi.Role.TOOL_TIP, Atspi.Role.TOOL_TIP,
'ROLE_CONTENT_DELETION', role_keys.ROLE_CONTENT_DELETION,
'ROLE_CONTENT_INSERTION', role_keys.ROLE_CONTENT_INSERTION,
'ROLE_CONTENT_MARK', role_keys.ROLE_CONTENT_MARK,
'ROLE_CONTENT_SUGGESTION', role_keys.ROLE_CONTENT_SUGGESTION,
'ROLE_DPUB_SECTION']) role_keys.ROLE_DPUB_SECTION])
if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextNonLandmarkForm'): if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextNonLandmarkForm'):
enabled.append(Atspi.Role.FORM) enabled.append(Atspi.Role.FORM)
if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextTable'): if cthulhu.cthulhuApp.settingsManager.getSetting('speakContextTable'):
@@ -2058,7 +2060,7 @@ class SpeechGenerator(generator.Generator):
result.append(messages.leavingNLists(count)) result.append(messages.leavingNLists(count))
else: else:
result.append(messages.LEAVING_LIST) result.append(messages.LEAVING_LIST)
elif role == 'ROLE_FEED': elif role == role_keys.ROLE_FEED:
result.append(messages.LEAVING_FEED) result.append(messages.LEAVING_FEED)
elif role == Atspi.Role.PANEL: elif role == Atspi.Role.PANEL:
if self._script.utilities.isFigure(obj): if self._script.utilities.isFigure(obj):
@@ -2069,7 +2071,7 @@ class SpeechGenerator(generator.Generator):
result = [''] result = ['']
elif role == Atspi.Role.TABLE and self._script.utilities.isTextDocumentTable(obj): elif role == Atspi.Role.TABLE and self._script.utilities.isTextDocumentTable(obj):
result.append(messages.LEAVING_TABLE) result.append(messages.LEAVING_TABLE)
elif role == 'ROLE_DPUB_LANDMARK': elif role == role_keys.ROLE_DPUB_LANDMARK:
if self._script.utilities.isDPubAcknowledgments(obj): if self._script.utilities.isDPubAcknowledgments(obj):
result.append(messages.LEAVING_ACKNOWLEDGMENTS) result.append(messages.LEAVING_ACKNOWLEDGMENTS)
elif self._script.utilities.isDPubAfterword(obj): elif self._script.utilities.isDPubAfterword(obj):
@@ -2108,7 +2110,7 @@ class SpeechGenerator(generator.Generator):
result.append(messages.LEAVING_PROLOGUE) result.append(messages.LEAVING_PROLOGUE)
elif self._script.utilities.isDPubToc(obj): elif self._script.utilities.isDPubToc(obj):
result.append(messages.LEAVING_TOC) result.append(messages.LEAVING_TOC)
elif role == 'ROLE_DPUB_SECTION': elif role == role_keys.ROLE_DPUB_SECTION:
if self._script.utilities.isDPubAbstract(obj): if self._script.utilities.isDPubAbstract(obj):
result.append(messages.LEAVING_ABSTRACT) result.append(messages.LEAVING_ABSTRACT)
elif self._script.utilities.isDPubColophon(obj): elif self._script.utilities.isDPubColophon(obj):
@@ -2148,13 +2150,13 @@ class SpeechGenerator(generator.Generator):
result.append(messages.LEAVING_FORM) result.append(messages.LEAVING_FORM)
elif role == Atspi.Role.TOOL_TIP: elif role == Atspi.Role.TOOL_TIP:
result.append(messages.LEAVING_TOOL_TIP) result.append(messages.LEAVING_TOOL_TIP)
elif role == 'ROLE_CONTENT_DELETION': elif role == role_keys.ROLE_CONTENT_DELETION:
result.append(messages.CONTENT_DELETION_END) result.append(messages.CONTENT_DELETION_END)
elif role == 'ROLE_CONTENT_INSERTION': elif role == role_keys.ROLE_CONTENT_INSERTION:
result.append(messages.CONTENT_INSERTION_END) result.append(messages.CONTENT_INSERTION_END)
elif role == 'ROLE_CONTENT_MARK': elif role == role_keys.ROLE_CONTENT_MARK:
result.append(messages.CONTENT_MARK_END) result.append(messages.CONTENT_MARK_END)
elif role == 'ROLE_CONTENT_SUGGESTION' \ elif role == role_keys.ROLE_CONTENT_SUGGESTION \
and not self._script.utilities.isInlineSuggestion(obj): and not self._script.utilities.isInlineSuggestion(obj):
result.append(messages.LEAVING_SUGGESTION) result.append(messages.LEAVING_SUGGESTION)
else: else:
@@ -2305,16 +2307,16 @@ class SpeechGenerator(generator.Generator):
Atspi.Role.DESCRIPTION_LIST, Atspi.Role.DESCRIPTION_LIST,
Atspi.Role.FORM, Atspi.Role.FORM,
Atspi.Role.LANDMARK, Atspi.Role.LANDMARK,
'ROLE_CONTENT_DELETION', role_keys.ROLE_CONTENT_DELETION,
'ROLE_CONTENT_INSERTION', role_keys.ROLE_CONTENT_INSERTION,
'ROLE_CONTENT_MARK', role_keys.ROLE_CONTENT_MARK,
'ROLE_CONTENT_SUGGESTION', role_keys.ROLE_CONTENT_SUGGESTION,
'ROLE_DPUB_LANDMARK', role_keys.ROLE_DPUB_LANDMARK,
'ROLE_DPUB_SECTION', role_keys.ROLE_DPUB_SECTION,
'ROLE_FEED', role_keys.ROLE_FEED,
Atspi.Role.LIST, Atspi.Role.LIST,
Atspi.Role.PANEL, Atspi.Role.PANEL,
'ROLE_REGION', role_keys.ROLE_REGION,
Atspi.Role.TABLE, Atspi.Role.TABLE,
Atspi.Role.TOOL_TIP] Atspi.Role.TOOL_TIP]