Commit 25c64254 authored by Joanmarie Diggs's avatar Joanmarie Diggs

Explicitly announce the popup type when aria-haspopup is used

Notes:
* This will not be presented if the verbosity is set to brief.
* At the present time, no filtering of obvious or default types is
  taking place. (Example: The default popup of an ARIA combo box is
  "listbox". Rather than filtering it out, Orca will present it.
* The information is being tacked on to the very end of presentation
  so it can be interrupted by users who don't find it meaningful.
* What gets spoken when is subject to change based on user feedback.
parent 5eba5318
......@@ -116,9 +116,9 @@ formatting = {
},
'suffix': {
'focused': '[]',
'unfocused': 'newNodeLevel + unselectedCell + clickable + hasLongDesc + ' + TUTORIAL + ' + description',
'basicWhereAmI': TUTORIAL + ' + clickable + hasLongDesc + description',
'detailedWhereAmI': TUTORIAL + ' + clickable + hasLongDesc + description'
'unfocused': 'newNodeLevel + unselectedCell + clickable + hasLongDesc + ' + TUTORIAL + ' + description + pause + hasPopup',
'basicWhereAmI': TUTORIAL + ' + clickable + hasLongDesc + description + pause + hasPopup',
'detailedWhereAmI': TUTORIAL + ' + clickable + hasLongDesc + description + pause + hasPopup'
},
'default': {
'focused': '[]',
......
......@@ -486,6 +486,9 @@ class Generator:
def _generateHasLongDesc(self, obj, **args):
return []
def _generateHasPopup(self, obj, **args):
return []
def _generateAvailability(self, obj, **args):
"""Returns an array of strings for use by speech and braille that
represent the grayed/sensitivity/availability state of the
......
......@@ -563,6 +563,28 @@ FLAT_REVIEW_STOP = _("Leaving flat review.")
# (e.g., "=sum(a1:d1)")
HAS_FORMULA = _("has formula")
# Translators: this message will be presented to indicate the focused object
# will cause a dialog to appear if activated.
HAS_POPUP_DIALOG = _("opens dialog")
# Translators: this message will be presented to indicate the focused object
# will cause a grid to appear if activated. A grid is an interactive table.
HAS_POPUP_GRID = _("opens grid")
# Translators: this message will be presented to indicate the focused object
# will cause a listbox to appear if activated.
HAS_POPUP_LISTBOX = _("opens listbox")
# Translators: this message will be presented to indicate the focused object
# will cause a menu to appear if activated.
HAS_POPUP_MENU = _("opens menu")
# Translators: this message will be presented to indicate the focused object
# will cause a tree to appear if activated. A tree is a list with sub-levels
# which can be expanded or collapsed, similar to the list of folders in an
# email client.
HAS_POPUP_TREE = _("opens tree")
# Translators: The following string is spoken to let the user know that he/she
# is on a link within an image map. An image map is an image/graphic which has
# been divided into regions. Each region can be clicked on and has an associated
......
......@@ -3901,6 +3901,9 @@ class Utilities:
def hasLongDesc(self, obj):
return False
def popupType(self, obj):
return ''
def headingLevel(self, obj):
if not (obj and obj.getRole() == pyatspi.ROLE_HEADING):
return 0
......
......@@ -76,6 +76,7 @@ class Utilities(script_utilities.Utilities):
self._hasExplicitName = {}
self._hasNoSize = {}
self._hasLongDesc = {}
self._popupType = {}
self._hasUselessCanvasDescendant = {}
self._id = {}
self._displayStyle = {}
......@@ -155,6 +156,7 @@ class Utilities(script_utilities.Utilities):
self._hasExplicitName = {}
self._hasNoSize = {}
self._hasLongDesc = {}
self._popupType = {}
self._hasUselessCanvasDescendant = {}
self._id = {}
self._displayStyle = {}
......@@ -3530,6 +3532,23 @@ class Utilities(script_utilities.Utilities):
self._hasLongDesc[hash(obj)] = rv
return rv
def popupType(self, obj):
if not (obj and self.inDocumentContent(obj)):
return False
rv = self._popupType.get(hash(obj))
if rv is not None:
return rv
try:
attrs = dict([attr.split(':', 1) for attr in obj.getAttributes()])
except:
attrs = {}
rv = attrs.get('haspopup', 'false').lower()
self._popupType[hash(obj)] = rv
return rv
def inferLabelFor(self, obj):
if not self.shouldInferLabelFor(obj):
return None, []
......
......@@ -104,6 +104,28 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
# call utility methods rather than generate it.
return super()._generateAnyTextSelection(obj, **args)
def _generateHasPopup(self, obj, **args):
if not self._script.utilities.inDocumentContent(obj):
return []
result = []
popupType = self._script.utilities.popupType(obj)
if popupType == 'dialog':
result = [messages.HAS_POPUP_DIALOG]
elif popupType == 'grid':
result = [messages.HAS_POPUP_GRID]
elif popupType == 'listbox':
result = [messages.HAS_POPUP_LISTBOX]
elif popupType in ('menu', 'true'):
result = [messages.HAS_POPUP_MENU]
elif popupType == 'tree':
result = [messages.HAS_POPUP_TREE]
if result:
result.extend(self.voice(speech_generator.SYSTEM))
return result
def _generateClickable(self, obj, **args):
if not self._script.utilities.inDocumentContent(obj):
return []
......
......@@ -252,6 +252,18 @@ class SpeechGenerator(generator.Generator):
result.extend(acss)
return result
def _generateHasPopup(self, obj, **args):
if _settingsManager.getSetting('onlySpeakDisplayedText') \
or _settingsManager.getSetting('speechVerbosityLevel') \
== settings.VERBOSITY_LEVEL_BRIEF:
return []
acss = self.voice(SYSTEM)
result = generator.Generator._generateHasPopup(self, obj, **args)
if result:
result.extend(acss)
return result
def _generateClickable(self, obj, **args):
if _settingsManager.getSetting('onlySpeakDisplayedText') \
or _settingsManager.getSetting('speechVerbosityLevel') \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment