Skip to content

Commit b9f5213

Browse files
authored
Merge 005da16 into 2e2d39a
2 parents 2e2d39a + 005da16 commit b9f5213

File tree

11 files changed

+164
-60
lines changed

11 files changed

+164
-60
lines changed

source/IAccessibleHandler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import UIAHandler
1818
from comInterfaces.Accessibility import *
1919
from comInterfaces.IAccessible2Lib import *
20+
from comInterfaces import IAccessible2Lib as IA2
2021
from logHandler import log
2122
import JABHandler
2223
import eventHandler
@@ -257,6 +258,7 @@ def flushEvents(self):
257258
IA2_ROLE_CONTENT_DELETION:controlTypes.ROLE_DELETED_CONTENT,
258259
IA2_ROLE_CONTENT_INSERTION:controlTypes.ROLE_INSERTED_CONTENT,
259260
IA2_ROLE_BLOCK_QUOTE:controlTypes.ROLE_BLOCKQUOTE,
261+
IA2.IA2_ROLE_LANDMARK: controlTypes.ROLE_LANDMARK,
260262
#some common string roles
261263
"frame":controlTypes.ROLE_FRAME,
262264
"iframe":controlTypes.ROLE_INTERNALFRAME,

source/NVDAObjects/IAccessible/MSHTML.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,13 @@ def _get_name(self):
675675
return ""
676676
return super(MSHTML,self).name
677677

678+
def _get_landmark(self):
679+
if self.HTMLNode:
680+
ariaRole = self.HTMLAttributes['role']
681+
if ariaRole and ariaRole in aria.landmarkRoles:
682+
return ariaRole
683+
return super().landmark
684+
678685
def _get_value(self):
679686
if self.HTMLNodeHasAncestorIAccessible:
680687
try:
@@ -1009,7 +1016,11 @@ def event_liveRegionChange(self):
10091016
pass
10101017

10111018
def _get_roleText(self):
1012-
return self.HTMLAttributes['aria-roledescription']
1019+
roleText = self.HTMLAttributes['aria-roledescription']
1020+
if roleText:
1021+
return roleText
1022+
return super().roleText
1023+
10131024

10141025
class V6ComboBox(IAccessible):
10151026
"""The object which receives value change events for combo boxes in MSHTML/IE 6.

source/NVDAObjects/IAccessible/ia2Web.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ def _get_isPresentableFocusAncestor(self):
4949
return super(Ia2Web,self).isPresentableFocusAncestor
5050

5151
def _get_roleText(self):
52-
roleText=self.IA2Attributes.get('roledescription')
52+
roleText = self.IA2Attributes.get('roledescription')
5353
if roleText:
5454
return roleText
55-
return super(Ia2Web,self).roleText
55+
return super().roleText
5656

5757
def _get_states(self):
5858
states=super(Ia2Web,self).states
@@ -65,6 +65,11 @@ def _get_states(self):
6565
states.discard(controlTypes.STATE_EDITABLE)
6666
return states
6767

68+
def _get_landmark(self):
69+
if self.IAccessibleRole != IAccessibleHandler.IA2_ROLE_LANDMARK:
70+
return super().landmark
71+
return self.IA2Attributes.get('xml-roles', '').split(' ')[0]
72+
6873
class Document(Ia2Web):
6974
value = None
7075

source/NVDAObjects/UIA/edge.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ def _getControlFieldForObject(self,obj,isEmbedded=False,startOfNode=False,endOfN
138138
# This can affect whether the field is presented as a container (e.g. announcing entering and exiting)
139139
if role in (controlTypes.ROLE_GROUPING,controlTypes.ROLE_SECTION,controlTypes.ROLE_PARAGRAPH):
140140
field['isBlock']=True
141-
# ARIA roledescription
141+
# ARIA roledescription and landmarks
142142
field['roleText']=obj.roleText
143-
# report landmarks
143+
# provide landmarks
144144
field['landmark']=obj.landmark
145145
# Combo boxes with a text pattern are editable
146146
if obj.role==controlTypes.ROLE_COMBOBOX and obj.UIATextPattern:
@@ -479,7 +479,10 @@ def _get_isCurrent(self):
479479
return None
480480

481481
def _get_roleText(self):
482-
return self.ariaProperties.get('roledescription', None)
482+
roleText = self.ariaProperties.get('roledescription', None)
483+
if roleText:
484+
return roleText
485+
return super().roleText
483486

484487
def _get_placeholder(self):
485488
ariaPlaceholder = self.ariaProperties.get('placeholder', None)

source/NVDAObjects/__init__.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import globalPluginHandler
3030
import brailleInput
3131
import locationHelper
32+
import aria
3233

3334
class NVDAObjectTextInfo(textInfos.offsets.OffsetsTextInfo):
3435
"""A default TextInfo which is used to enable text review of information about widgets that don't support text content.
@@ -407,8 +408,20 @@ def _get_roleText(self):
407408
No string is provided by default, meaning that NVDA will fall back to using role.
408409
Examples of where this property might be overridden are shapes in Powerpoint, or ARIA role descriptions.
409410
"""
411+
if self.landmark and self.landmark in aria.landmarkRoles:
412+
return f"{aria.landmarkRoles[self.landmark]} {controlTypes.roleLabels[controlTypes.ROLE_LANDMARK]}"
410413
return None
411414

415+
def _get_roleTextBraille(self):
416+
"""
417+
A custom role string for this object, which is used for braille presentation,
418+
which will override the standard label for this object's role property as well as the value of roleText.
419+
By default, NVDA falls back to using roleText.
420+
"""
421+
if self.landmark and self.landmark in braille.landmarkLabels:
422+
return f"{braille.roleLabels[controlTypes.ROLE_LANDMARK]} {braille.landmarkLabels[self.landmark]}"
423+
return self.roleText
424+
412425
def _get_value(self):
413426
"""The value of this object (example: the current percentage of a scrollbar, the selected option in a combo box).
414427
@rtype: str
@@ -710,14 +723,39 @@ def _get_presentationType(self):
710723
states=self.states
711724
if controlTypes.STATE_INVISIBLE in states or controlTypes.STATE_UNAVAILABLE in states:
712725
return self.presType_unavailable
713-
role=self.role
726+
role = self.role
727+
landmark = self.landmark
728+
if (
729+
role == controlTypes.ROLE_LANDMARK
730+
or landmark
731+
) and not config.conf["documentFormatting"]["reportLandmarks"]:
732+
return self.presType_layout
733+
734+
roleText = self.roleText
735+
if roleText:
736+
# If roleText is set, the object is very likely to communicate something relevant to the user.
737+
return self.presType_content
714738

715739
#Static text should be content only if it really use usable text
716740
if role==controlTypes.ROLE_STATICTEXT:
717741
text=self.makeTextInfo(textInfos.POSITION_ALL).text
718742
return self.presType_content if text and not text.isspace() else self.presType_layout
719743

720-
if role in (controlTypes.ROLE_UNKNOWN, controlTypes.ROLE_PANE, controlTypes.ROLE_TEXTFRAME, controlTypes.ROLE_ROOTPANE, controlTypes.ROLE_LAYEREDPANE, controlTypes.ROLE_SCROLLPANE, controlTypes.ROLE_SPLITPANE, controlTypes.ROLE_SECTION, controlTypes.ROLE_PARAGRAPH, controlTypes.ROLE_TITLEBAR, controlTypes.ROLE_LABEL, controlTypes.ROLE_WHITESPACE,controlTypes.ROLE_BORDER):
744+
if role in (
745+
controlTypes.ROLE_UNKNOWN,
746+
controlTypes.ROLE_PANE,
747+
controlTypes.ROLE_TEXTFRAME,
748+
controlTypes.ROLE_ROOTPANE,
749+
controlTypes.ROLE_LAYEREDPANE,
750+
controlTypes.ROLE_SCROLLPANE,
751+
controlTypes.ROLE_SPLITPANE,
752+
controlTypes.ROLE_SECTION,
753+
controlTypes.ROLE_PARAGRAPH,
754+
controlTypes.ROLE_TITLEBAR,
755+
controlTypes.ROLE_LABEL,
756+
controlTypes.ROLE_WHITESPACE,
757+
controlTypes.ROLE_BORDER
758+
):
721759
return self.presType_layout
722760
name = self.name
723761
description = self.description
@@ -1164,6 +1202,11 @@ def _get_devInfo(self):
11641202
except Exception as e:
11651203
ret = "exception: %s" % e
11661204
info.append("role: %s" % ret)
1205+
try:
1206+
ret = repr(self.roleText)
1207+
except Exception as e:
1208+
ret = f"exception: {e}"
1209+
info.append(f"roleText: {ret}")
11671210
try:
11681211
stateConsts = dict((const, name) for name, const in controlTypes.__dict__.items() if name.startswith("STATE_"))
11691212
ret = ", ".join(

source/braille.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@
169169
controlTypes.ROLE_DELETED_CONTENT: _("del"),
170170
# Translators: Displayed in braille for an object which is inserted.
171171
controlTypes.ROLE_INSERTED_CONTENT: _("ins"),
172+
# Translators: Displayed in braille for a landmark.
173+
controlTypes.ROLE_LANDMARK: _("lmk"),
172174
}
173175

174176
positiveStateLabels = {
@@ -473,7 +475,7 @@ def getBrailleTextForProperties(**propertyValues):
473475
if name:
474476
textList.append(name)
475477
role = propertyValues.get("role")
476-
roleText = propertyValues.get("roleText")
478+
roleText = propertyValues.get('roleText')
477479
states = propertyValues.get("states")
478480
positionInfo = propertyValues.get("positionInfo")
479481
level = positionInfo.get("level") if positionInfo else None
@@ -596,7 +598,7 @@ def update(self):
596598
text = getBrailleTextForProperties(
597599
name=obj.name,
598600
role=role,
599-
roleText=obj.roleText,
601+
roleText=obj.roleTextBraille,
600602
current=obj.isCurrent,
601603
placeholder=placeholderValue,
602604
value=obj.value if not NVDAObjectHasUsefulText(obj) else None ,
@@ -643,8 +645,7 @@ def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):
643645
value=field.get('value',None)
644646
current=field.get('current', None)
645647
placeholder=field.get('placeholder', None)
646-
roleText=field.get('roleText')
647-
648+
roleText = field.get('roleTextBraille', field.get('roleText'))
648649
if presCat == field.PRESCAT_LAYOUT:
649650
text = []
650651
if current:
@@ -674,6 +675,11 @@ def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):
674675
# However, we still need to pass it (hence "_role").
675676
"_role" if role == controlTypes.ROLE_MATH else "role": role,
676677
"states": states,"value":value, "current":current, "placeholder":placeholder,"roleText":roleText}
678+
if formatConfig["reportLandmarks"] and field.get("landmark") and field.get("_startOfNode"):
679+
# Ensure that the name of the field gets presented even if normally it wouldn't.
680+
name = field.get("name")
681+
if name:
682+
props["name"] = name
677683
if config.conf["presentation"]["reportKeyboardShortcuts"]:
678684
kbShortcut = field.get("keyboardShortcut")
679685
if kbShortcut:

source/browseMode.py

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,41 +1106,6 @@ def move():
11061106

11071107
class BrowseModeDocumentTextInfo(textInfos.TextInfo):
11081108

1109-
def getControlFieldSpeech(self, attrs, ancestorAttrs, fieldType, formatConfig=None, extraDetail=False, reason=None):
1110-
textList = []
1111-
landmark = attrs.get("landmark")
1112-
if formatConfig["reportLandmarks"] and fieldType == "start_addedToControlFieldStack" and landmark:
1113-
# Ensure that the name of the field gets presented even if normally it wouldn't.
1114-
name=attrs.get('name')
1115-
if name and attrs.getPresentationCategory(ancestorAttrs,formatConfig,reason) is None:
1116-
textList.append(name)
1117-
if landmark == "region":
1118-
# The word landmark is superfluous for regions.
1119-
textList.append(aria.landmarkRoles[landmark])
1120-
if landmark != "region":
1121-
textList.append(_("%s landmark") % aria.landmarkRoles[landmark])
1122-
textList.append(super(BrowseModeDocumentTextInfo, self).getControlFieldSpeech(attrs, ancestorAttrs, fieldType, formatConfig, extraDetail, reason))
1123-
return " ".join(textList)
1124-
1125-
def getControlFieldBraille(self, field, ancestors, reportStart, formatConfig):
1126-
textList = []
1127-
landmark = field.get("landmark")
1128-
if formatConfig["reportLandmarks"] and reportStart and landmark and field.get("_startOfNode"):
1129-
# Ensure that the name of the field gets presented even if normally it wouldn't.
1130-
name=field.get('name')
1131-
if name and field.getPresentationCategory(ancestors,formatConfig) is None:
1132-
textList.append(name)
1133-
if landmark == "region":
1134-
# The word landmark is superfluous for regions.
1135-
textList.append(braille.landmarkLabels[landmark])
1136-
if landmark != "region":
1137-
# Translators: This is brailled to indicate a landmark (example output: lmk main).
1138-
textList.append(_("lmk %s") % braille.landmarkLabels[landmark])
1139-
text = super(BrowseModeDocumentTextInfo, self).getControlFieldBraille(field, ancestors, reportStart, formatConfig)
1140-
if text:
1141-
textList.append(text)
1142-
return " ".join(textList)
1143-
11441109
def _get_focusableNVDAObjectAtStart(self):
11451110
try:
11461111
item = next(self.obj._iterNodesByType("focusable", "up", self))

source/controlTypes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
ROLE_CHARTELEMENT=146
153153
ROLE_DELETED_CONTENT=147
154154
ROLE_INSERTED_CONTENT=148
155+
ROLE_LANDMARK = 149
155156

156157
STATE_UNAVAILABLE=0X1
157158
STATE_FOCUSED=0X2
@@ -492,6 +493,8 @@
492493
ROLE_DELETED_CONTENT:_("deleted"),
493494
# Translators: Identifies inserted content.
494495
ROLE_INSERTED_CONTENT:_("inserted"),
496+
# Translators: Identifies a landmark.
497+
ROLE_LANDMARK: _("landmark"),
495498
}
496499

497500
stateLabels={

0 commit comments

Comments
 (0)