Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix misleading log message for aria-current="true" #11782

Merged
merged 15 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions source/NVDAObjects/IAccessible/MSHTML.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,11 @@ def _get_treeInterceptorClass(self):

def _get_isCurrent(self):
isCurrent = self.HTMLAttributes["aria-current"]
if isCurrent == "false":
isCurrent = None
return isCurrent
try:
return controlTypes.IS_CURRENT(isCurrent)
except ValueError:
log.debugWarning(f"Unknown aria-current value: {isCurrent}")
return controlTypes.IS_CURRENT.NO

def _get_HTMLAttributes(self):
return HTMLAttribCache(self.HTMLNode)
Expand Down
12 changes: 7 additions & 5 deletions source/NVDAObjects/IAccessible/ia2Web.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ def _get_positionInfo(self):
info['level']=level
return info

def _get_isCurrent(self):
current = self.IA2Attributes.get("current", None)
if current == "false":
current = None
return current
def _get_isCurrent(self) -> controlTypes.IS_CURRENT:
ia2attrCurrent: str = self.IA2Attributes.get("current", "false")
try:
return controlTypes.IS_CURRENT(ia2attrCurrent)
except ValueError:
log.debugWarning(f"Unknown 'current' IA2Attribute value: {ia2attrCurrent}")
return controlTypes.IS_CURRENT.NO

def _get_placeholder(self):
placeholder = self.IA2Attributes.get('placeholder', None)
Expand Down
15 changes: 9 additions & 6 deletions source/NVDAObjects/UIA/edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def _getControlFieldForObject(self,obj,isEmbedded=False,startOfNode=False,endOfN
if obj.role==controlTypes.ROLE_COMBOBOX and obj.UIATextPattern:
field['states'].add(controlTypes.STATE_EDITABLE)
# report if the field is 'current'
field['current']=obj.isCurrent
field['current'] = obj.isCurrent
if obj.placeholder and obj._isTextEmpty:
field['placeholder']=obj.placeholder
# For certain controls, if ARIA overrides the label, then force the field's content (value) to the label
Expand Down Expand Up @@ -470,15 +470,18 @@ def _get_ariaProperties(self):
# "false" is ignored by the regEx and will not produce a match
RE_ARIA_CURRENT_PROP_VALUE = re.compile("current=(?!false)(\w+);")

def _get_isCurrent(self):
def _get_isCurrent(self) -> controlTypes.IS_CURRENT:
ariaProperties=self._getUIACacheablePropertyValue(UIAHandler.UIA_AriaPropertiesPropertyId)
match = self.RE_ARIA_CURRENT_PROP_VALUE.search(ariaProperties)
log.debug("aria props = %s" % ariaProperties)
if match:
valueOfAriaCurrent = match.group(1)
log.debug("aria current value = %s" % valueOfAriaCurrent)
return valueOfAriaCurrent
return None
try:
return controlTypes.IS_CURRENT(valueOfAriaCurrent)
except ValueError:
log.debugWarning(
f"Unknown aria-current value: {valueOfAriaCurrent}, ariaProperties: {ariaProperties}"
)
return controlTypes.IS_CURRENT.NO

def _get_roleText(self):
roleText = self.ariaProperties.get('roledescription', None)
Expand Down
9 changes: 5 additions & 4 deletions source/NVDAObjects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -975,12 +975,13 @@ def _get_statusBar(self):
"""
return None

def _get_isCurrent(self):
isCurrent: controlTypes.IS_CURRENT #: type info for auto property _get_isCurrent

def _get_isCurrent(self) -> controlTypes.IS_CURRENT:
"""Gets the value that indicates whether this object is the current element in a set of related
elements. This maps to aria-current. Normally returns None. If this object is current
it will return one of the following values: "true", "page", "step", "location", "date", "time"
elements. This maps to aria-current.
"""
return None
return controlTypes.IS_CURRENT.NO

def _get_shouldAcceptShowHideCaretEvent(self):
"""Some objects/applications send show/hide caret events when we don't expect it, such as when the cursor is blinking.
Expand Down
12 changes: 4 additions & 8 deletions source/braille.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,13 +571,9 @@ def getPropertiesBraille(**propertyValues) -> str: # noqa: C901
# %s is replaced with the column number.
columnStr = _("c{columnNumber}").format(columnNumber=columnNumber)
textList.append(columnStr)
current = propertyValues.get('current', False)
if current:
try:
textList.append(controlTypes.isCurrentLabels[current])
except KeyError:
log.debugWarning("Aria-current value not handled: %s"%current)
textList.append(controlTypes.isCurrentLabels[True])
isCurrent = propertyValues.get('current', controlTypes.IS_CURRENT.NO)
if isCurrent != controlTypes.IS_CURRENT.NO:
textList.append(isCurrent.getTranslationForUI())
placeholder = propertyValues.get('placeholder', None)
if placeholder:
textList.append(placeholder)
Expand Down Expand Up @@ -662,7 +658,7 @@ def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):

states = field.get("states", set())
value=field.get('value',None)
current=field.get('current', None)
current = field.get('current', controlTypes.IS_CURRENT.NO)
placeholder=field.get('placeholder', None)
roleText = field.get('roleTextBraille', field.get('roleText'))
landmark = field.get("landmark")
Expand Down
45 changes: 36 additions & 9 deletions source/controlTypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from typing import Dict, Union, Set, Any, Optional, List
from enum import Enum, auto

from logHandler import log

ROLE_UNKNOWN=0
ROLE_WINDOW=1
ROLE_TITLEBAR=2
Expand Down Expand Up @@ -662,21 +664,46 @@ class OutputReason(Enum):
REASON_CARET = OutputReason.CARET
REASON_ONLYCACHE = OutputReason.ONLYCACHE

#: Text to use for 'current' values. These describe if an item is the current item
#: within a particular kind of selection.
isCurrentLabels: Dict[Union[bool, str], str] = {

class IS_CURRENT(Enum):
"""Values to use within NVDA to denote 'current' values.
These describe if an item is the current item within a particular kind of selection.
EG aria-current
"""
NO = "false"
Yes = "true"
PAGE = "page"
STEP = "step"
LOCATION = "location"
DATE = "date"
TIME = "time"

def getTranslationForUI(self):
try:
return _isCurrentLabels[self]
except KeyError:
log.debugWarning(f"No translation mapping for: {self}")
# there is a value for 'current' but NVDA hasn't learned about it yet,
# at least describe in the general sense that this item is 'current'
return _isCurrentLabels[IS_CURRENT.Yes]


#: Text to use for 'current' values. These describe if an item is the current item
#: within a particular kind of selection. EG aria-current
_isCurrentLabels: Dict[Enum, str] = {
IS_CURRENT.NO: "", # There is nothing extra to say for items that are not current.
# Translators: Presented when an item is marked as current in a collection of items
True:_("current"),
IS_CURRENT.Yes: _("current"),
# Translators: Presented when a page item is marked as current in a collection of page items
"page":_("current page"),
IS_CURRENT.PAGE: _("current page"),
# Translators: Presented when a step item is marked as current in a collection of step items
"step":_("current step"),
IS_CURRENT.STEP: _("current step"),
# Translators: Presented when a location item is marked as current in a collection of location items
"location":_("current location"),
IS_CURRENT.LOCATION: _("current location"),
# Translators: Presented when a date item is marked as current in a collection of date items
"date":_("current date"),
IS_CURRENT.DATE: _("current date"),
# Translators: Presented when a time item is marked as current in a collection of time items
"time":_("current time"),
IS_CURRENT.TIME: _("current time"),
}


Expand Down
29 changes: 13 additions & 16 deletions source/speech/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def getObjectPropertiesSpeech( # noqa: C901
positionInfo=obj.positionInfo
elif value and name == "current":
# getPropertiesSpeech names this "current", but the NVDAObject property is
# named "isCurrent".
# named "isCurrent", it's type should always be controltypes.IS_CURRENT
newPropertyValues['current'] = obj.isCurrent
elif value:
# Certain properties such as row and column numbers have presentational versions, which should be used for speech if they are available.
Expand Down Expand Up @@ -1606,15 +1606,12 @@ def getPropertiesSpeech( # noqa: C901
if rowCount or columnCount:
# The caller is entering a table, so ensure that it is treated as a new table, even if the previous table was the same.
oldTableID = None
ariaCurrent = propertyValues.get('current', False)
if ariaCurrent:
try:
ariaCurrentLabel = controlTypes.isCurrentLabels[ariaCurrent]
textList.append(ariaCurrentLabel)
except KeyError:
log.debugWarning("Aria-current value not handled: %s"%ariaCurrent)
ariaCurrentLabel = controlTypes.isCurrentLabels[True]
textList.append(ariaCurrentLabel)

# speak isCurrent property EG aria-current
isCurrent = propertyValues.get('current', controlTypes.IS_CURRENT.NO)
if isCurrent != controlTypes.IS_CURRENT.NO:
textList.append(isCurrent.getTranslationForUI())

placeholder: Optional[str] = propertyValues.get('placeholder', None)
if placeholder:
textList.append(placeholder)
Expand Down Expand Up @@ -1677,7 +1674,7 @@ def getControlFieldSpeech( # noqa: C901
name = ""
states=attrs.get('states',set())
keyboardShortcut=attrs.get('keyboardShortcut', "")
ariaCurrent=attrs.get('current', None)
isCurrent = attrs.get('current', controlTypes.IS_CURRENT.NO)
placeholderValue=attrs.get('placeholder', None)
value=attrs.get('value',"")
if reason==controlTypes.REASON_FOCUS or attrs.get('alwaysReportDescription',False):
Expand Down Expand Up @@ -1707,7 +1704,7 @@ def getControlFieldSpeech( # noqa: C901
keyboardShortcutSequence = getPropertiesSpeech(
reason=reason, keyboardShortcut=keyboardShortcut
)
ariaCurrentSequence = getPropertiesSpeech(reason=reason, current=ariaCurrent)
isCurrentSequence = getPropertiesSpeech(reason=reason, current=isCurrent)
placeholderSequence = getPropertiesSpeech(reason=reason, placeholder=placeholderValue)
nameSequence = getPropertiesSpeech(reason=reason, name=name)
valueSequence = getPropertiesSpeech(reason=reason, value=value)
Expand Down Expand Up @@ -1824,7 +1821,7 @@ def getControlFieldSpeech( # noqa: C901
getProps['columnHeaderText'] = attrs.get("table-columnheadertext")
tableCellSequence = getPropertiesSpeech(_tableID=tableID, **getProps)
tableCellSequence.extend(stateTextSequence)
tableCellSequence.extend(ariaCurrentSequence)
tableCellSequence.extend(isCurrentSequence)
types.logBadSequenceTypes(tableCellSequence)
return tableCellSequence

Expand Down Expand Up @@ -1873,7 +1870,7 @@ def getControlFieldSpeech( # noqa: C901
out.extend(stateTextSequence if speakStatesFirst else roleTextSequence)
out.extend(roleTextSequence if speakStatesFirst else stateTextSequence)
out.append(containerContainsText)
out.extend(ariaCurrentSequence)
out.extend(isCurrentSequence)
out.extend(valueSequence)
out.extend(descriptionSequence)
out.extend(levelSequence)
Expand Down Expand Up @@ -1908,8 +1905,8 @@ def getControlFieldSpeech( # noqa: C901
# Special cases
elif not speakEntry and fieldType in ("start_addedToControlFieldStack","start_relative"):
out = []
if ariaCurrent:
out.extend(ariaCurrentSequence)
if isCurrent != controlTypes.IS_CURRENT.NO:
out.extend(isCurrentSequence)
# Speak expanded / collapsed / level for treeview items (in ARIA treegrids)
if role == controlTypes.ROLE_TREEVIEWITEM:
if controlTypes.STATE_EXPANDED in states:
Expand Down
14 changes: 11 additions & 3 deletions source/virtualBuffers/MSHTML.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,17 @@ def _normalizeFormatField(self, attrs):

def _normalizeControlField(self,attrs):
level=None
ariaCurrent = attrs.get('HTMLAttrib::aria-current', None)
if ariaCurrent not in (None, "false"):
attrs['current']=ariaCurrent

ariaCurrentValue = attrs.get('HTMLAttrib::aria-current', 'false')
try:
ariaCurrent = controlTypes.IS_CURRENT(ariaCurrentValue)
except ValueError:
log.debugWarning(f"Unknown aria-current value: {ariaCurrentValue}")
ariaCurrent = controlTypes.IS_CURRENT.NO

if ariaCurrent != controlTypes.IS_CURRENT.NO:
attrs['current'] = ariaCurrent

placeholder = self._getPlaceholderAttribute(attrs, 'HTMLAttrib::aria-placeholder')
if placeholder:
attrs['placeholder']=placeholder
Expand Down
11 changes: 8 additions & 3 deletions source/virtualBuffers/gecko_ia2.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ def _normalizeControlField(self,attrs):
if attrVal is not None:
attrs[attr]=int(attrVal)

current = attrs.get("IAccessible2::attribute_current")
if current not in (None, 'false'):
attrs['current']= current
valForCurrent = attrs.get("IAccessible2::attribute_current", "false")
try:
isCurrent = controlTypes.IS_CURRENT(valForCurrent)
except ValueError:
log.debugWarning(f"Unknown isCurrent value: {valForCurrent}")
isCurrent = controlTypes.IS_CURRENT.NO
if isCurrent != controlTypes.IS_CURRENT.NO:
attrs['current'] = isCurrent
placeholder = self._getPlaceholderAttribute(attrs, "IAccessible2::attribute_placeholder")
if placeholder is not None:
attrs['placeholder']= placeholder
Expand Down