diff --git a/source/NVDAObjects/IAccessible/ia2Web.py b/source/NVDAObjects/IAccessible/ia2Web.py index 7db9f08f121..86f0f94423a 100644 --- a/source/NVDAObjects/IAccessible/ia2Web.py +++ b/source/NVDAObjects/IAccessible/ia2Web.py @@ -203,6 +203,13 @@ def _get_states(self): # Google has a custom ARIA attribute to force a node's editable state off (such as in Google Slides). if self.IA2Attributes.get('goog-editable')=="false": states.discard(controlTypes.State.EDITABLE) + if controlTypes.State.HASPOPUP in states: + popupState = aria.ariaHaspopupValuesToNVDAStates.get( + self.IA2Attributes.get("haspopup") + ) + if popupState: + states.discard(controlTypes.State.HASPOPUP) + states.add(popupState) return states def _get_landmark(self): diff --git a/source/aria.py b/source/aria.py index baf5c84af2f..4d8d7ced649 100755 --- a/source/aria.py +++ b/source/aria.py @@ -115,3 +115,13 @@ class AriaLivePoliteness(str, Enum): OFF = "off" POLITE = "polite" ASSERTIVE = "assertive" + + +ariaHaspopupValuesToNVDAStates: Dict[str, controlTypes.State] = { + "true": controlTypes.State.HASPOPUP, + "menu": controlTypes.State.HASPOPUP, + "dialog": controlTypes.State.HASPOPUP_DIALOG, + "grid": controlTypes.State.HASPOPUP_GRID, + "listbox": controlTypes.State.HASPOPUP_LIST, + "tree": controlTypes.State.HASPOPUP_TREE, +} diff --git a/source/controlTypes/state.py b/source/controlTypes/state.py index 5dcb543b091..2c5ba347ce7 100644 --- a/source/controlTypes/state.py +++ b/source/controlTypes/state.py @@ -98,6 +98,10 @@ def negativeDisplayString(self) -> str: INDETERMINATE = setBit(44) HALF_PRESSED = setBit(45) ON = setBit(46) + HASPOPUP_DIALOG = setBit(47) + HASPOPUP_GRID = setBit(48) + HASPOPUP_LIST = setBit(49) + HASPOPUP_TREE = setBit(50) STATES_SORTED = frozenset([State.SORTED, State.SORTED_ASCENDING, State.SORTED_DESCENDING]) @@ -192,6 +196,14 @@ def negativeDisplayString(self) -> str: # Translators: a state that denotes a control is currently on # E.g. a switch control. State.ON: _("on"), + # Translators: Presented when a control has a pop-up dialog. + State.HASPOPUP_DIALOG: _("opens dialog"), + # Translators: Presented when a control has a pop-up grid. + State.HASPOPUP_GRID: _("opens grid"), + # Translators: Presented when a control has a pop-up list box. + State.HASPOPUP_LIST: _("opens list"), + # Translators: Presented when a control has a pop-up tree. + State.HASPOPUP_TREE: _("opens tree"), } diff --git a/source/virtualBuffers/gecko_ia2.py b/source/virtualBuffers/gecko_ia2.py index 20d0d195ba7..3cf31bfb9bd 100755 --- a/source/virtualBuffers/gecko_ia2.py +++ b/source/virtualBuffers/gecko_ia2.py @@ -167,6 +167,12 @@ def _normalizeControlField(self, attrs): # noqa: C901 if controlTypes.State.CHECKED in states: states.discard(controlTypes.State.CHECKED) states.add(controlTypes.State.ON) + popupState = aria.ariaHaspopupValuesToNVDAStates.get( + attrs.get("IAccessible2::attribute_haspopup") + ) + if popupState: + states.discard(controlTypes.State.HASPOPUP) + states.add(popupState) attrs['role']=role attrs['states']=states if level != "" and level is not None: diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 531eca616ac..36eea22da27 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -7,6 +7,7 @@ What's New in NVDA == New Features == - Added pronunciation of Unicode braille symbols such as "⠐⠣⠃⠗⠇⠐⠜". (#14548) +- In Mozilla Firefox and Google Chrome, NVDA now reports when a control opens a dialog, grid, list or tree if the author has specified this using aria-haspopup. (#14709) -