diff options
author | dmazzoni <dmazzoni@chromium.org> | 2015-04-24 01:22:17 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-24 08:22:27 +0000 |
commit | 9dbb3741802d2a5a3f6370fef9d712b077fa4b86 (patch) | |
tree | ac1147c3e471e87d7106fe4b80baee5c84e1bcf4 /content/browser/accessibility/browser_accessibility_win.cc | |
parent | 3396ad31e40ceef8d08cef11a91da9ee15ff6159 (diff) | |
download | chromium_src-9dbb3741802d2a5a3f6370fef9d712b077fa4b86.zip chromium_src-9dbb3741802d2a5a3f6370fef9d712b077fa4b86.tar.gz chromium_src-9dbb3741802d2a5a3f6370fef9d712b077fa4b86.tar.bz2 |
Fix menu list and list box screen reader accessibility.
The most important change here is getting rid of code in
renderer_accessibility.cc that recreated the subtree whenever
AXSelectedChildrenChanged was fired. This is no longer
necessary because Blink now fires the right events on each
individual option in a menu list or list box.
The rest of the changes just make sure the exact attributes
and events match the spec and match what Firefox and
Safari do when interacting with these elements, including
adding some good tests for those.
BUG=323462
Review URL: https://codereview.chromium.org/1057083002
Cr-Commit-Position: refs/heads/master@{#326755}
Diffstat (limited to 'content/browser/accessibility/browser_accessibility_win.cc')
-rw-r--r-- | content/browser/accessibility/browser_accessibility_win.cc | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index b61f2f9..c6c7788 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc @@ -3179,9 +3179,9 @@ void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() { // WebKit stores the main accessible text in the "value" - swap it so // that it's the "name". if (name.empty() && - (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION || - GetRole() == ui::AX_ROLE_STATIC_TEXT || - GetRole() == ui::AX_ROLE_LIST_MARKER)) { + (GetRole() == ui::AX_ROLE_STATIC_TEXT || + GetRole() == ui::AX_ROLE_LIST_MARKER || + IsListBoxOptionOrMenuListOption())) { base::string16 tmp = value; value = name; name = tmp; @@ -3298,10 +3298,22 @@ void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) { bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; bool was_selected_before = (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; - if (is_selected_now && !was_selected_before) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); - } else if (!is_selected_now && was_selected_before) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); + if (is_selected_now || was_selected_before) { + bool multiselect = false; + if (GetParent() && GetParent()->HasState(ui::AX_STATE_MULTISELECTABLE)) + multiselect = true; + + if (multiselect) { + // In a multi-select box, fire SELECTIONADD and SELECTIONREMOVE events. + if (is_selected_now && !was_selected_before) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); + } else if (!is_selected_now && was_selected_before) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); + } + } else if (is_selected_now && !was_selected_before) { + // In a single-select box, only fire SELECTION events. + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTION, this); + } } // Fire an event if this container object has scrolled. @@ -3461,7 +3473,7 @@ base::string16 BrowserAccessibilityWin::GetValueText() { } base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { - if (IsEditableText()) + if (IsEditableText() || GetRole() == ui::AX_ROLE_MENU_LIST_OPTION) return value(); return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext(); } @@ -3587,6 +3599,26 @@ BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32 id) { return manager()->GetFromID(id)->ToBrowserAccessibilityWin(); } +bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() { + if (!GetParent()) + return false; + + int32 role = GetRole(); + int32 parent_role = GetParent()->GetRole(); + + if (role == ui::AX_ROLE_LIST_BOX_OPTION && + parent_role == ui::AX_ROLE_LIST_BOX) { + return true; + } + + if (role == ui::AX_ROLE_MENU_LIST_OPTION && + parent_role == ui::AX_ROLE_MENU_LIST_POPUP) { + return true; + } + + return false; +} + void BrowserAccessibilityWin::InitRoleAndState() { int32 ia_role = 0; int32 ia_state = 0; @@ -3909,10 +3941,12 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia2_role = IA2_ROLE_RADIO_MENU_ITEM; break; case ui::AX_ROLE_MENU_LIST_POPUP: - ia_role = ROLE_SYSTEM_CLIENT; + ia_role = ROLE_SYSTEM_LIST; + ia2_state &= ~(IA2_STATE_EDITABLE); break; case ui::AX_ROLE_MENU_LIST_OPTION: ia_role = ROLE_SYSTEM_LISTITEM; + ia2_state &= ~(IA2_STATE_EDITABLE); if (ia_state & STATE_SYSTEM_SELECTABLE) { ia_state |= STATE_SYSTEM_FOCUSABLE; if (HasState(ui::AX_STATE_FOCUSED)) |