Skip to content

Commit afe27d9

Browse files
authored
Merge 964b8f8 into c4d6fb5
2 parents c4d6fb5 + 964b8f8 commit afe27d9

9 files changed

Lines changed: 102 additions & 57 deletions

File tree

source/NVDAObjects/IAccessible/MSHTML.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,11 @@ def _get_treeInterceptorClass(self):
545545

546546
def _get_isCurrent(self):
547547
isCurrent = self.HTMLAttributes["aria-current"]
548-
if isCurrent == "false":
549-
isCurrent = None
550-
return isCurrent
548+
try:
549+
return controlTypes.IsCurrent(isCurrent)
550+
except ValueError:
551+
log.debugWarning(f"Unknown aria-current value: {isCurrent}")
552+
return controlTypes.IsCurrent.NO
551553

552554
def _get_HTMLAttributes(self):
553555
return HTMLAttribCache(self.HTMLNode)

source/NVDAObjects/IAccessible/ia2Web.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ def _get_positionInfo(self):
3434
info['level']=level
3535
return info
3636

37-
def _get_isCurrent(self):
38-
current = self.IA2Attributes.get("current", None)
39-
if current == "false":
40-
current = None
41-
return current
37+
def _get_isCurrent(self) -> controlTypes.IsCurrent:
38+
ia2attrCurrent: str = self.IA2Attributes.get("current", "false")
39+
try:
40+
return controlTypes.IsCurrent(ia2attrCurrent)
41+
except ValueError:
42+
log.debugWarning(f"Unknown 'current' IA2Attribute value: {ia2attrCurrent}")
43+
return controlTypes.IsCurrent.NO
4244

4345
def _get_placeholder(self):
4446
placeholder = self.IA2Attributes.get('placeholder', None)

source/NVDAObjects/UIA/edge.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def _getControlFieldForObject(self,obj,isEmbedded=False,startOfNode=False,endOfN
156156
if obj.role==controlTypes.ROLE_COMBOBOX and obj.UIATextPattern:
157157
field['states'].add(controlTypes.STATE_EDITABLE)
158158
# report if the field is 'current'
159-
field['current']=obj.isCurrent
159+
field['current'] = obj.isCurrent
160160
if obj.placeholder and obj._isTextEmpty:
161161
field['placeholder']=obj.placeholder
162162
# For certain controls, if ARIA overrides the label, then force the field's content (value) to the label
@@ -470,15 +470,18 @@ def _get_ariaProperties(self):
470470
# "false" is ignored by the regEx and will not produce a match
471471
RE_ARIA_CURRENT_PROP_VALUE = re.compile("current=(?!false)(\w+);")
472472

473-
def _get_isCurrent(self):
473+
def _get_isCurrent(self) -> controlTypes.IsCurrent:
474474
ariaProperties=self._getUIACacheablePropertyValue(UIAHandler.UIA_AriaPropertiesPropertyId)
475475
match = self.RE_ARIA_CURRENT_PROP_VALUE.search(ariaProperties)
476-
log.debug("aria props = %s" % ariaProperties)
477476
if match:
478477
valueOfAriaCurrent = match.group(1)
479-
log.debug("aria current value = %s" % valueOfAriaCurrent)
480-
return valueOfAriaCurrent
481-
return None
478+
try:
479+
return controlTypes.IsCurrent(valueOfAriaCurrent)
480+
except ValueError:
481+
log.debugWarning(
482+
f"Unknown aria-current value: {valueOfAriaCurrent}, ariaProperties: {ariaProperties}"
483+
)
484+
return controlTypes.IsCurrent.NO
482485

483486
def _get_roleText(self):
484487
roleText = self.ariaProperties.get('roledescription', None)

source/NVDAObjects/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -975,12 +975,13 @@ def _get_statusBar(self):
975975
"""
976976
return None
977977

978-
def _get_isCurrent(self):
978+
isCurrent: controlTypes.IsCurrent #: type info for auto property _get_isCurrent
979+
980+
def _get_isCurrent(self) -> controlTypes.IsCurrent:
979981
"""Gets the value that indicates whether this object is the current element in a set of related
980-
elements. This maps to aria-current. Normally returns None. If this object is current
981-
it will return one of the following values: "true", "page", "step", "location", "date", "time"
982+
elements. This maps to aria-current.
982983
"""
983-
return None
984+
return controlTypes.IsCurrent.NO
984985

985986
def _get_shouldAcceptShowHideCaretEvent(self):
986987
"""Some objects/applications send show/hide caret events when we don't expect it, such as when the cursor is blinking.

source/braille.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -571,13 +571,9 @@ def getPropertiesBraille(**propertyValues) -> str: # noqa: C901
571571
# %s is replaced with the column number.
572572
columnStr = _("c{columnNumber}").format(columnNumber=columnNumber)
573573
textList.append(columnStr)
574-
current = propertyValues.get('current', False)
575-
if current:
576-
try:
577-
textList.append(controlTypes.isCurrentLabels[current])
578-
except KeyError:
579-
log.debugWarning("Aria-current value not handled: %s"%current)
580-
textList.append(controlTypes.isCurrentLabels[True])
574+
isCurrent = propertyValues.get('current', controlTypes.IsCurrent.NO)
575+
if isCurrent != controlTypes.IsCurrent.NO:
576+
textList.append(isCurrent.displayString)
581577
placeholder = propertyValues.get('placeholder', None)
582578
if placeholder:
583579
textList.append(placeholder)
@@ -662,7 +658,7 @@ def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):
662658

663659
states = field.get("states", set())
664660
value=field.get('value',None)
665-
current=field.get('current', None)
661+
current = field.get('current', controlTypes.IsCurrent.NO)
666662
placeholder=field.get('placeholder', None)
667663
roleText = field.get('roleTextBraille', field.get('roleText'))
668664
landmark = field.get("landmark")

source/controlTypes.py

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from typing import Dict, Union, Set, Any, Optional, List
77
from enum import Enum, auto
88

9+
from logHandler import log
10+
911
ROLE_UNKNOWN=0
1012
ROLE_WINDOW=1
1113
ROLE_TITLEBAR=2
@@ -662,21 +664,50 @@ class OutputReason(Enum):
662664
REASON_CARET = OutputReason.CARET
663665
REASON_ONLYCACHE = OutputReason.ONLYCACHE
664666

665-
#: Text to use for 'current' values. These describe if an item is the current item
666-
#: within a particular kind of selection.
667-
isCurrentLabels: Dict[Union[bool, str], str] = {
667+
668+
class IsCurrent(Enum):
669+
"""Values to use within NVDA to denote 'current' values.
670+
These describe if an item is the current item within a particular kind of selection.
671+
EG aria-current
672+
"""
673+
NO = "false"
674+
YES = "true"
675+
PAGE = "page"
676+
STEP = "step"
677+
LOCATION = "location"
678+
DATE = "date"
679+
TIME = "time"
680+
681+
@property
682+
def displayString(self):
683+
"""
684+
@return: The translated UI display string that should be used for this value of the IsCurrent enum
685+
"""
686+
try:
687+
return _isCurrentLabels[self]
688+
except KeyError:
689+
log.debugWarning(f"No translation mapping for: {self}")
690+
# there is a value for 'current' but NVDA hasn't learned about it yet,
691+
# at least describe in the general sense that this item is 'current'
692+
return _isCurrentLabels[IsCurrent.YES]
693+
694+
695+
#: Text to use for 'current' values. These describe if an item is the current item
696+
#: within a particular kind of selection. EG aria-current
697+
_isCurrentLabels: Dict[Enum, str] = {
698+
IsCurrent.NO: "", # There is nothing extra to say for items that are not current.
668699
# Translators: Presented when an item is marked as current in a collection of items
669-
True:_("current"),
700+
IsCurrent.YES: _("current"),
670701
# Translators: Presented when a page item is marked as current in a collection of page items
671-
"page":_("current page"),
702+
IsCurrent.PAGE: _("current page"),
672703
# Translators: Presented when a step item is marked as current in a collection of step items
673-
"step":_("current step"),
704+
IsCurrent.STEP: _("current step"),
674705
# Translators: Presented when a location item is marked as current in a collection of location items
675-
"location":_("current location"),
706+
IsCurrent.LOCATION: _("current location"),
676707
# Translators: Presented when a date item is marked as current in a collection of date items
677-
"date":_("current date"),
708+
IsCurrent.DATE: _("current date"),
678709
# Translators: Presented when a time item is marked as current in a collection of time items
679-
"time":_("current time"),
710+
IsCurrent.TIME: _("current time"),
680711
}
681712

682713

source/speech/__init__.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def getObjectPropertiesSpeech( # noqa: C901
362362
positionInfo=obj.positionInfo
363363
elif value and name == "current":
364364
# getPropertiesSpeech names this "current", but the NVDAObject property is
365-
# named "isCurrent".
365+
# named "isCurrent", it's type should always be controltypes.IsCurrent
366366
newPropertyValues['current'] = obj.isCurrent
367367
elif value:
368368
# Certain properties such as row and column numbers have presentational versions, which should be used for speech if they are available.
@@ -1606,15 +1606,12 @@ def getPropertiesSpeech( # noqa: C901
16061606
if rowCount or columnCount:
16071607
# The caller is entering a table, so ensure that it is treated as a new table, even if the previous table was the same.
16081608
oldTableID = None
1609-
ariaCurrent = propertyValues.get('current', False)
1610-
if ariaCurrent:
1611-
try:
1612-
ariaCurrentLabel = controlTypes.isCurrentLabels[ariaCurrent]
1613-
textList.append(ariaCurrentLabel)
1614-
except KeyError:
1615-
log.debugWarning("Aria-current value not handled: %s"%ariaCurrent)
1616-
ariaCurrentLabel = controlTypes.isCurrentLabels[True]
1617-
textList.append(ariaCurrentLabel)
1609+
1610+
# speak isCurrent property EG aria-current
1611+
isCurrent = propertyValues.get('current', controlTypes.IsCurrent.NO)
1612+
if isCurrent != controlTypes.IsCurrent.NO:
1613+
textList.append(isCurrent.displayString)
1614+
16181615
placeholder: Optional[str] = propertyValues.get('placeholder', None)
16191616
if placeholder:
16201617
textList.append(placeholder)
@@ -1677,7 +1674,7 @@ def getControlFieldSpeech( # noqa: C901
16771674
name = ""
16781675
states=attrs.get('states',set())
16791676
keyboardShortcut=attrs.get('keyboardShortcut', "")
1680-
ariaCurrent=attrs.get('current', None)
1677+
isCurrent = attrs.get('current', controlTypes.IsCurrent.NO)
16811678
placeholderValue=attrs.get('placeholder', None)
16821679
value=attrs.get('value',"")
16831680
if reason==controlTypes.REASON_FOCUS or attrs.get('alwaysReportDescription',False):
@@ -1707,7 +1704,7 @@ def getControlFieldSpeech( # noqa: C901
17071704
keyboardShortcutSequence = getPropertiesSpeech(
17081705
reason=reason, keyboardShortcut=keyboardShortcut
17091706
)
1710-
ariaCurrentSequence = getPropertiesSpeech(reason=reason, current=ariaCurrent)
1707+
isCurrentSequence = getPropertiesSpeech(reason=reason, current=isCurrent)
17111708
placeholderSequence = getPropertiesSpeech(reason=reason, placeholder=placeholderValue)
17121709
nameSequence = getPropertiesSpeech(reason=reason, name=name)
17131710
valueSequence = getPropertiesSpeech(reason=reason, value=value)
@@ -1824,7 +1821,7 @@ def getControlFieldSpeech( # noqa: C901
18241821
getProps['columnHeaderText'] = attrs.get("table-columnheadertext")
18251822
tableCellSequence = getPropertiesSpeech(_tableID=tableID, **getProps)
18261823
tableCellSequence.extend(stateTextSequence)
1827-
tableCellSequence.extend(ariaCurrentSequence)
1824+
tableCellSequence.extend(isCurrentSequence)
18281825
types.logBadSequenceTypes(tableCellSequence)
18291826
return tableCellSequence
18301827

@@ -1873,7 +1870,7 @@ def getControlFieldSpeech( # noqa: C901
18731870
out.extend(stateTextSequence if speakStatesFirst else roleTextSequence)
18741871
out.extend(roleTextSequence if speakStatesFirst else stateTextSequence)
18751872
out.append(containerContainsText)
1876-
out.extend(ariaCurrentSequence)
1873+
out.extend(isCurrentSequence)
18771874
out.extend(valueSequence)
18781875
out.extend(descriptionSequence)
18791876
out.extend(levelSequence)
@@ -1908,8 +1905,8 @@ def getControlFieldSpeech( # noqa: C901
19081905
# Special cases
19091906
elif not speakEntry and fieldType in ("start_addedToControlFieldStack","start_relative"):
19101907
out = []
1911-
if ariaCurrent:
1912-
out.extend(ariaCurrentSequence)
1908+
if isCurrent != controlTypes.IsCurrent.NO:
1909+
out.extend(isCurrentSequence)
19131910
# Speak expanded / collapsed / level for treeview items (in ARIA treegrids)
19141911
if role == controlTypes.ROLE_TREEVIEWITEM:
19151912
if controlTypes.STATE_EXPANDED in states:

source/virtualBuffers/MSHTML.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,17 @@ def _normalizeFormatField(self, attrs):
4848

4949
def _normalizeControlField(self,attrs):
5050
level=None
51-
ariaCurrent = attrs.get('HTMLAttrib::aria-current', None)
52-
if ariaCurrent not in (None, "false"):
53-
attrs['current']=ariaCurrent
51+
52+
ariaCurrentValue = attrs.get('HTMLAttrib::aria-current', 'false')
53+
try:
54+
ariaCurrent = controlTypes.IsCurrent(ariaCurrentValue)
55+
except ValueError:
56+
log.debugWarning(f"Unknown aria-current value: {ariaCurrentValue}")
57+
ariaCurrent = controlTypes.IsCurrent.NO
58+
59+
if ariaCurrent != controlTypes.IsCurrent.NO:
60+
attrs['current'] = ariaCurrent
61+
5462
placeholder = self._getPlaceholderAttribute(attrs, 'HTMLAttrib::aria-placeholder')
5563
if placeholder:
5664
attrs['placeholder']=placeholder

source/virtualBuffers/gecko_ia2.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,14 @@ def _normalizeControlField(self,attrs):
5252
if attrVal is not None:
5353
attrs[attr]=int(attrVal)
5454

55-
current = attrs.get("IAccessible2::attribute_current")
56-
if current not in (None, 'false'):
57-
attrs['current']= current
55+
valForCurrent = attrs.get("IAccessible2::attribute_current", "false")
56+
try:
57+
isCurrent = controlTypes.IsCurrent(valForCurrent)
58+
except ValueError:
59+
log.debugWarning(f"Unknown isCurrent value: {valForCurrent}")
60+
isCurrent = controlTypes.IsCurrent.NO
61+
if isCurrent != controlTypes.IsCurrent.NO:
62+
attrs['current'] = isCurrent
5863
placeholder = self._getPlaceholderAttribute(attrs, "IAccessible2::attribute_placeholder")
5964
if placeholder is not None:
6065
attrs['placeholder']= placeholder

0 commit comments

Comments
 (0)