Commit ffc377fd authored by Adam Ettenberger's avatar Adam Ettenberger Committed by Commit Bot

Fire UIA SelectionItem events on aria-checked changes for radio buttons

According to the following spec radio and menuitemradio should expose
UIA SelectedItem.IsSelected when aria-checked is set :
https://www.w3.org/TR/core-aam-1.1/#mapping_state-property_table

This CL ensures that radio / menuitemradio fire appropriate
SelectionItem events, and whenever a SelectionItem changes its
selection state that we also fire a Property Changed event for
SelectionItem.IsSelected.

AX-Relnotes: Fire missing events for ARIA radio/menuitemradio when aria-checked changes. Narrator will now announce selected state changes for this scenario.
Bug: 1102580
Change-Id: I72f479e25f61b0ddffc28f73d4a9c34e8dc4ecb8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2212982Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarKevin Babbitt <kbabbitt@microsoft.com>
Commit-Queue: Adam Ettenberger <Adam.Ettenberger@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#791802}
parent 44f37823
......@@ -77,7 +77,40 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
const std::vector<ui::AXTreeObserver::Change>& changes) override;
private:
void HandleSelectedStateChanged(BrowserAccessibility* node);
struct SelectionEvents {
std::vector<BrowserAccessibility*> added;
std::vector<BrowserAccessibility*> removed;
SelectionEvents();
~SelectionEvents();
};
using SelectionEventsMap = std::map<BrowserAccessibility*, SelectionEvents>;
using IsSelectedPredicate =
base::RepeatingCallback<bool(BrowserAccessibility*)>;
using FirePlatformSelectionEventsCallback =
base::RepeatingCallback<void(BrowserAccessibility*,
BrowserAccessibility*,
const SelectionEvents&)>;
static bool IsIA2NodeSelected(BrowserAccessibility* node);
static bool IsUIANodeSelected(BrowserAccessibility* node);
void FireIA2SelectionEvents(BrowserAccessibility* container,
BrowserAccessibility* only_selected_child,
const SelectionEvents& changes);
void FireUIASelectionEvents(BrowserAccessibility* container,
BrowserAccessibility* only_selected_child,
const SelectionEvents& changes);
static void HandleSelectedStateChanged(
SelectionEventsMap& selection_events_map,
BrowserAccessibility* node,
bool is_selected);
static void FinalizeSelectionEvents(
SelectionEventsMap& selection_events_map,
IsSelectedPredicate is_selected_predicate,
FirePlatformSelectionEventsCallback fire_platform_events_callback);
// Give BrowserAccessibilityManager::Create access to our constructor.
friend class BrowserAccessibilityManager;
......@@ -109,13 +142,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// Keep track of selection changes so we can optimize UIA event firing.
// Pointers are only stored for the duration of |OnAccessibilityEvents|, and
// the map is cleared in |FinalizeAccessibilityEvents|.
struct SelectionEvents {
std::vector<BrowserAccessibility*> added;
std::vector<BrowserAccessibility*> removed;
SelectionEvents();
~SelectionEvents();
};
std::map<BrowserAccessibility*, SelectionEvents> selection_events_;
SelectionEventsMap ia2_selection_events_;
SelectionEventsMap uia_selection_events_;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin);
};
......
......@@ -2,6 +2,10 @@ AriaProperties changed on role=checkbox, name=checkbox1
AriaProperties changed on role=checkbox, name=checkbox2
AriaProperties changed on role=radio, name=radio1
AriaProperties changed on role=radio, name=radio2
SelectionItemIsSelected changed on role=radio, name=radio1
SelectionItemIsSelected changed on role=radio, name=radio2
SelectionItem_ElementRemovedFromSelection on role=radio, name=radio2
SelectionItem_ElementSelected on role=radio, name=radio1
ToggleToggleState changed on role=checkbox, name=checkbox1
ToggleToggleState changed on role=checkbox, name=checkbox2
ToggleToggleState changed on role=radio, name=radio1
......
......@@ -3,4 +3,5 @@ AriaProperties changed on role=option, name=Apple
AutomationFocusChanged on role=option, name=Apple
AutomationFocusChanged on role=option, name=Apple
ExpandCollapseExpandCollapseState changed on role=combobox
SelectionItemIsSelected changed on role=option, name=Apple
SelectionItem_ElementSelected on role=option, name=Apple
......@@ -4,4 +4,5 @@ AutomationFocusChanged on role=combobox
AutomationFocusChanged on role=option, name=Apple
AutomationFocusChanged on role=option, name=Apple
ExpandCollapseExpandCollapseState changed on role=combobox
SelectionItemIsSelected changed on role=option, name=Apple
SelectionItem_ElementSelected on role=option, name=Apple
......@@ -2,10 +2,14 @@ AriaProperties changed on role=option, name=Apple
AriaProperties changed on role=option, name=Orange
AutomationFocusChanged on role=option, name=Orange
AutomationFocusChanged on role=option, name=Orange
SelectionItemIsSelected changed on role=option, name=Apple
SelectionItemIsSelected changed on role=option, name=Orange
SelectionItem_ElementSelected on role=option, name=Orange
=== Start Continuation ===
AriaProperties changed on role=option, name=Banana
AriaProperties changed on role=option, name=Orange
AutomationFocusChanged on role=option, name=Banana
AutomationFocusChanged on role=option, name=Banana
SelectionItemIsSelected changed on role=option, name=Banana
SelectionItemIsSelected changed on role=option, name=Orange
SelectionItem_ElementSelected on role=option, name=Banana
......@@ -3,6 +3,7 @@ AriaProperties changed on role=option, name=Orange
AutomationFocusChanged on role=option, name=Apple
AutomationFocusChanged on role=option, name=Orange
AutomationFocusChanged on role=option, name=Orange
SelectionItemIsSelected changed on role=option, name=Orange
SelectionItem_ElementSelected on role=option, name=Orange
=== Start Continuation ===
AriaProperties changed on role=option, name=Banana
......@@ -10,4 +11,5 @@ AriaProperties changed on role=option, name=Orange
AutomationFocusChanged on role=option, name=Banana
AutomationFocusChanged on role=option, name=Banana
AutomationFocusChanged on role=option, name=Orange
SelectionItemIsSelected changed on role=option, name=Banana
SelectionItem_ElementSelected on role=option, name=Banana
AriaProperties changed on role=gridcell, name=Grid1, GridCell1
SelectionItemIsSelected changed on role=gridcell, name=Grid1, GridCell1
SelectionItem_ElementRemovedFromSelection on role=gridcell, name=Grid1, GridCell1
=== Start Continuation ===
AriaProperties changed on role=gridcell, name=Grid2, GridCell2
SelectionItemIsSelected changed on role=gridcell, name=Grid2, GridCell2
SelectionItem_ElementAddedToSelection on role=gridcell, name=Grid2, GridCell2
=== Start Continuation ===
AriaProperties changed on role=gridcell, name=Grid3, GridCell1
SelectionItemIsSelected changed on role=gridcell, name=Grid3, GridCell1
SelectionItem_ElementRemovedFromSelection on role=gridcell, name=Grid3, GridCell1
=== Start Continuation ===
AriaProperties changed on role=gridcell, name=Grid4, GridCell1
AriaProperties changed on role=gridcell, name=Grid4, GridCell2
SelectionItemIsSelected changed on role=gridcell, name=Grid4, GridCell1
SelectionItemIsSelected changed on role=gridcell, name=Grid4, GridCell2
SelectionItem_ElementRemovedFromSelection on role=gridcell, name=Grid4, GridCell1
SelectionItem_ElementSelected on role=gridcell, name=Grid4, GridCell2
=== Start Continuation ===
=== Start Continuation ===
AriaProperties changed on role=combobox
AriaProperties changed on role=listitem, name=Select2, Option2
SelectionItemIsSelected changed on role=combobox
SelectionItemIsSelected changed on role=listitem, name=Select2, Option2
SelectionItem_ElementSelected on role=listitem, name=Select2, Option2
ValueValue changed on role=combobox
=== Start Continuation ===
AriaProperties changed on role=option, name=DivSelect, Option1
AriaProperties changed on role=option, name=DivSelect, Option2
SelectionItemIsSelected changed on role=option, name=DivSelect, Option1
SelectionItemIsSelected changed on role=option, name=DivSelect, Option2
SelectionItem_ElementSelected on role=option, name=DivSelect, Option2
......@@ -2,4 +2,6 @@ AriaProperties changed on role=option, name=b
AriaProperties changed on role=option, name=c
AutomationFocusChanged on role=option, name=c
AutomationFocusChanged on role=option, name=c
SelectionItemIsSelected changed on role=option, name=b
SelectionItemIsSelected changed on role=option, name=c
SelectionItem_ElementSelected on role=option, name=c
......@@ -2,4 +2,6 @@ AriaProperties changed on role=option, name=Apple
AriaProperties changed on role=option, name=Orange
AutomationFocusChanged on role=option, name=Orange
AutomationFocusChanged on role=option, name=Orange
SelectionItemIsSelected changed on role=option, name=Apple
SelectionItemIsSelected changed on role=option, name=Orange
SelectionItem_ElementSelected on role=option, name=Orange
......@@ -3,4 +3,5 @@ AriaProperties changed on role=option, name=Orange
AutomationFocusChanged on role=option, name=Apple
AutomationFocusChanged on role=option, name=Orange
AutomationFocusChanged on role=option, name=Orange
SelectionItemIsSelected changed on role=option, name=Orange
SelectionItem_ElementSelected on role=option, name=Orange
......@@ -2,5 +2,6 @@ AutomationFocusChanged on role=combobox
AutomationFocusChanged on role=combobox
=== Start Continuation ===
AriaProperties changed on role=combobox
SelectionItemIsSelected changed on role=combobox
SelectionItem_ElementRemovedFromSelection on role=combobox
ValueValue changed on role=combobox
......@@ -3,5 +3,6 @@ AutomationFocusChanged on role=combobox
AutomationFocusChanged on role=combobox
=== Start Continuation ===
AriaProperties changed on role=combobox
SelectionItemIsSelected changed on role=combobox
SelectionItem_ElementRemovedFromSelection on role=combobox
ValueValue changed on role=combobox
......@@ -3,5 +3,7 @@ AutomationFocusChanged on role=combobox
=== Start Continuation ===
AriaProperties changed on role=combobox
AriaProperties changed on role=listitem, name=Orange
SelectionItemIsSelected changed on role=combobox
SelectionItemIsSelected changed on role=listitem, name=Orange
SelectionItem_ElementSelected on role=listitem, name=Orange
ValueValue changed on role=combobox
......@@ -5,5 +5,6 @@ AutomationFocusChanged on role=combobox
AriaProperties changed on role=combobox
AriaProperties changed on role=listitem, name=Orange
AutomationFocusChanged on role=combobox
SelectionItemIsSelected changed on role=listitem, name=Orange
SelectionItem_ElementSelected on role=listitem, name=Orange
ValueValue changed on role=combobox
SelectionItemIsSelected changed on role=option, name=Option2
SelectionItem_ElementSelected on role=option, name=Option2
=== Start Continuation ===
SelectionItemIsSelected changed on role=option, name=Option3
SelectionItem_ElementAddedToSelection on role=option, name=Option3
=== Start Continuation ===
SelectionItemIsSelected changed on role=option, name=Option4
SelectionItem_ElementRemovedFromSelection on role=option, name=Option4
=== Start Continuation ===
SelectionItemIsSelected changed on role=option, name=Option5
SelectionItemIsSelected changed on role=option, name=Option6
SelectionItem_ElementSelected on role=option, name=Option6
=== Start Continuation ===
SelectionItemIsSelected changed on role=combobox, name=Combo3
SelectionItemIsSelected changed on role=listitem, name=Option8
SelectionItem_ElementSelected on role=listitem, name=Option8
=== Start Continuation ===
Selection_Invalidated on role=listbox, name=Combo4
<!--
@UIA-WIN-DENY:*
@UIA-WIN-ALLOW:SelectionItem_Element*
@UIA-WIN-ALLOW:SelectionItemIsSelected*
@UIA-WIN-ALLOW:Selection_Invalidated*
-->
<!DOCTYPE html>
......
......@@ -403,6 +403,16 @@ bool IsPresentational(const ax::mojom::Role role) {
}
}
bool IsRadio(const ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kRadioButton:
case ax::mojom::Role::kMenuItemRadio:
return true;
default:
return false;
}
}
bool IsRangeValueSupported(const ax::mojom::Role role) {
// https://www.w3.org/TR/wai-aria-1.1/#aria-valuenow
// https://www.w3.org/TR/wai-aria-1.1/#aria-valuetext
......
......@@ -113,6 +113,9 @@ AX_BASE_EXPORT bool IsMenuRelated(const ax::mojom::Role role);
// API.
AX_BASE_EXPORT bool IsPresentational(const ax::mojom::Role role);
// Returns true if the provided role belongs to a radio.
AX_BASE_EXPORT bool IsRadio(const ax::mojom::Role role);
// Returns true if the provided role supports a range-based value, such as a
// slider.
AX_BASE_EXPORT bool IsRangeValueSupported(const ax::mojom::Role role);
......
......@@ -7588,6 +7588,10 @@ base::Optional<PROPERTYID> AXPlatformNodeWin::MojoEventToUIAProperty(
case ax::mojom::Event::kRowCollapsed:
case ax::mojom::Event::kRowExpanded:
return UIA_ExpandCollapseExpandCollapseStatePropertyId;
case ax::mojom::Event::kSelection:
case ax::mojom::Event::kSelectionAdd:
case ax::mojom::Event::kSelectionRemove:
return UIA_SelectionItemIsSelectedPropertyId;
default:
return base::nullopt;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment