Skip to content

Commit a6844f4

Browse files
authored
Merge b662a0b into 4b339e2
2 parents 4b339e2 + b662a0b commit a6844f4

3 files changed

Lines changed: 95 additions & 4 deletions

File tree

source/browseMode.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,22 @@ def shouldPassThrough(self, obj, reason: Optional[OutputReason] = None):
353353
if not obj.isFocusable and controlTypes.State.FOCUSED not in states and role != controlTypes.Role.POPUPMENU:
354354
return False
355355
# many controls that are read-only should not switch to passThrough.
356-
# However, certain controls such as combo boxes and readonly edits are read-only but still interactive.
357-
# #5118: read-only ARIA grids should also be allowed (focusable table cells, rows and headers).
358-
if controlTypes.State.READONLY in states and role not in (controlTypes.Role.EDITABLETEXT, controlTypes.Role.COMBOBOX, controlTypes.Role.TABLEROW, controlTypes.Role.TABLECELL, controlTypes.Role.TABLEROWHEADER, controlTypes.Role.TABLECOLUMNHEADER):
359-
return False
356+
# However, there are exceptions.
357+
if controlTypes.State.READONLY in states:
358+
# #13221: For Slack message lists, and the MS Edge downloads window, switch to passthrough
359+
# even though the list item and list are read-only, but focusable.
360+
if (
361+
role == controlTypes.Role.LISTITEM and controlTypes.State.FOCUSED in states
362+
and obj.parent.role == controlTypes.Role.LIST and controlTypes.State.FOCUSABLE in obj.parent.states
363+
):
364+
return True
365+
# Certain controls such as combo boxes and readonly edits are read-only but still interactive.
366+
# #5118: read-only ARIA grids should also be allowed (focusable table cells, rows and headers).
367+
if role not in (
368+
controlTypes.Role.EDITABLETEXT, controlTypes.Role.COMBOBOX, controlTypes.Role.TABLEROW,
369+
controlTypes.Role.TABLECELL, controlTypes.Role.TABLEROWHEADER, controlTypes.Role.TABLECOLUMNHEADER
370+
):
371+
return False
360372
# Any roles or states for which we always switch to passThrough
361373
if role in self.ALWAYS_SWITCH_TO_PASS_THROUGH_ROLES or controlTypes.State.EDITABLE in states:
362374
return True

tests/system/robot/chromeTests.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,3 +1652,79 @@ def test_focusTargetReporting():
16521652
]),
16531653
message="focus mode - focus with Report Articles enabled"
16541654
)
1655+
1656+
1657+
def test_focus_mode_on_focusable_read_only_lists():
1658+
"""
1659+
If a list is read-only, but is focusable, and a list element receives focus, switch to focus mode.
1660+
"""
1661+
_chrome.prepareChrome(
1662+
"""
1663+
<a href="#">before Target</a>
1664+
<div role="list" aria-label="Messages" tabindex="-1">
1665+
<div role="listitem" tabindex="0" aria-label="Todd Kloots Hello all. At 1:30 PM">
1666+
<div role="document" aria-roledescription="message">
1667+
<a href="/kloots" class="sender">Todd Kloots</a> <a href="/time" class="time">1:30 PM</a>
1668+
<p>Hello all.</p>
1669+
</div>
1670+
</div>
1671+
</div>
1672+
"""
1673+
)
1674+
# Set focus
1675+
actualSpeech = _chrome.getSpeechAfterKey("tab")
1676+
_asserts.strings_match(
1677+
actualSpeech,
1678+
SPEECH_SEP.join([
1679+
"before Target",
1680+
"link",
1681+
])
1682+
)
1683+
1684+
# focus the list item
1685+
actualSpeech = _chrome.getSpeechAfterKey("tab")
1686+
_asserts.strings_match(
1687+
actualSpeech,
1688+
SPEECH_CALL_SEP.join([
1689+
SPEECH_SEP.join([
1690+
"messages", # name for list container
1691+
"list", # role for list container
1692+
]),
1693+
SPEECH_SEP.join([
1694+
"level 1", # Inserted by Chromium even though not explicitly set
1695+
"Todd Kloots Hello all.At 1:30 PM", # list element name, should read first
1696+
"1 of 1", # item count, no role expected here
1697+
]),
1698+
"Focus mode", # Focus mode should be enabled automatically and be indicated
1699+
]),
1700+
message="focus mode - focus list item and turn on focus mode"
1701+
)
1702+
1703+
# Tab into the document, which should turn on browse mode
1704+
actualSpeech = _chrome.getSpeechAfterKey("tab")
1705+
_asserts.strings_match(
1706+
actualSpeech,
1707+
SPEECH_CALL_SEP.join([
1708+
"message", # role description for document container
1709+
SPEECH_SEP.join([
1710+
"Todd Kloots", # name for link
1711+
"link", # role for link
1712+
]),
1713+
"Browse mode", # Focus mode should be disabled automatically and be indicated
1714+
]),
1715+
message="focus mode - focus link in document and turn off focus mode"
1716+
)
1717+
1718+
# shift+tab back to the focusable list item
1719+
actualSpeech = _chrome.getSpeechAfterKey("shift+tab")
1720+
_asserts.strings_match(
1721+
actualSpeech,
1722+
SPEECH_CALL_SEP.join([
1723+
SPEECH_SEP.join([
1724+
"Todd Kloots Hello all. At 1:30 PM", # list element name, should read first
1725+
"1 of 1", # item count, no role expected here
1726+
]),
1727+
"Focus mode", # Focus mode should be enabled automatically and be indicated
1728+
]),
1729+
message="focus mode - focus list item and turn on focus mode"
1730+
)

tests/system/robot/chromeTests.robot

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,6 @@ Quick Nav reports target first
120120
Focus reports target first
121121
[Documentation] Focus target should always be reported before ancestors. Ancestors should be reported from inner to outer.
122122
test_focusTargetReporting
123+
focus mode is turned on on focused read-only list item
124+
[Documentation] Focused list items with a focusable list container should cause focus mode to be turned on automatically.
125+
test_focus_mode_on_focusable_read_only_lists

0 commit comments

Comments
 (0)