Commit 4107aca1 authored by Martin Robinson's avatar Martin Robinson Committed by Commit Bot

Reland: Make 'click' the default action of unfocusable ARIA buttons

Trusty comes with a version of ATK that does not support the checkable
attribute, so we must specifically deny this in the test. A followup
change will make this global in order to avoid having to add it to many
tests.

Original commit message:
> Users of ATs on AuraLinux use the default action to know whether or not
> to activate nodes via the keyboard or a simulated mouse event. When a
> node with a button role cannot receive keyboard focus, have the default
> action be click. This heuristic helps ensure that when there is an ARIA
> button that cannot be activated via the keyboard, users know to simulate
> a mouse click.

Bug: 1025264
Change-Id: Ib8e66b369e30c771ce8533de24050f99e32ab579
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1953709Reviewed-by: default avatarJoanmarie Diggs <jdiggs@igalia.com>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Martin Robinson <mrobinson@igalia.com>
Cr-Commit-Position: refs/heads/master@{#722496}
parent 577edb91
......@@ -55,6 +55,7 @@ class AccessibilityTreeFormatterAuraLinux
AtspiAccessible* node);
void AddTextProperties(AtkText* atk_text, base::DictionaryValue* dict);
void AddActionProperties(AtkObject* atk_object, base::DictionaryValue* dict);
void AddValueProperties(AtkObject* atk_object, base::DictionaryValue* dict);
void AddTableProperties(AtkObject* atk_object, base::DictionaryValue* dict);
void AddTableCellProperties(const ui::AXPlatformNodeAuraLinux* node,
......@@ -242,6 +243,23 @@ void AccessibilityTreeFormatterAuraLinux::AddTextProperties(
dict->Set("text", std::move(text_values));
}
void AccessibilityTreeFormatterAuraLinux::AddActionProperties(
AtkObject* atk_object,
base::DictionaryValue* dict) {
if (!ATK_IS_ACTION(atk_object))
return;
AtkAction* action = ATK_ACTION(atk_object);
int action_count = atk_action_get_n_actions(action);
if (!action_count)
return;
auto actions = std::make_unique<base::ListValue>();
for (int i = 0; i < action_count; i++)
actions->AppendString(atk_action_get_name(action, i));
dict->Set("actions", std::move(actions));
}
void AccessibilityTreeFormatterAuraLinux::AddValueProperties(
AtkObject* atk_object,
base::DictionaryValue* dict) {
......@@ -448,6 +466,7 @@ void AccessibilityTreeFormatterAuraLinux::AddProperties(
if (ATK_IS_TEXT(atk_object))
AddTextProperties(ATK_TEXT(atk_object), dict);
AddActionProperties(atk_object, dict);
AddValueProperties(atk_object, dict);
AddTableProperties(atk_object, dict);
AddTableCellProperties(ax_platform_node, atk_object, dict);
......@@ -583,6 +602,23 @@ base::string16 AccessibilityTreeFormatterAuraLinux::ProcessTreeForOutput(
}
}
const base::ListValue* action_names_list;
std::vector<std::string> action_names;
if (node.GetList("actions", &action_names_list)) {
for (auto it = action_names_list->begin(); it != action_names_list->end();
++it) {
std::string action_name;
if (it->GetAsString(&action_name))
action_names.push_back(action_name);
}
std::string actions_str = base::JoinString(action_names, ", ");
if (actions_str.size()) {
WriteAttribute(false,
base::StringPrintf("actions=(%s)", actions_str.c_str()),
&line);
}
}
const base::ListValue* relations_value;
if (node.GetList("relations", &relations_value)) {
for (auto it = relations_value->begin(); it != relations_value->end();
......
[document web] name='Action verbs'
++[section]
++++[static] name='Generic div'
++[heading] name='Heading'
++++[static] name='Heading'
++[push button] name='Button' actions=(press)
++[link] name='Link' actions=(jump)
++++[static] name='Link' actions=(click-ancestor)
++[entry] selectable-text actions=(activate)
++[entry] selectable-text actions=(activate)
++[entry] selectable-text actions=(activate)
++[entry] selectable-text actions=(activate)
++[check box] actions=(check) checkable:true
++[check box] checked actions=(uncheck) checkable:true
++[radio button] actions=(check) checkable:true
++[toggle button] name='ARIA Switch' actions=(check) checkable:true
++[panel]
++++[toggle button] name='Summary' actions=(press)
++++++[static] name='Summary'
++[combo box] actions=(open)
++++[menu]
++++++[menu item] name='Pop-up button' selectable selected actions=(select)
++[section] actions=(click)
++++[static] name='Div with click handler' actions=(click-ancestor)
++[panel] actions=(click)
++++[paragraph] actions=(click-ancestor)
++++++[static] name='Paragraph with click handler on parent' actions=(click-ancestor)
++[menu]
++++[menu item] name='Menu item 1' actions=(select)
++++[check menu item] name='Menu item 2' checked actions=(uncheck) checkable:true
++++[radio menu item] name='Menu item 3' actions=(check) checkable:true
++[push button] name='ARIA Button' actions=(click)
++[push button] name='ARIA button with tab index' actions=(press)
++[push button] name='ARIA button with negative tab index' actions=(press)
++[section]
++++[push button] name='ARIA button that is an active descendant' actions=(press)
......@@ -41,3 +41,16 @@ rootWebArea name='Action verbs'
++++++menuItem name='Menu item 1' defaultActionVerb=select
++++++menuItemCheckBox name='Menu item 2' defaultActionVerb=uncheck checkedState=true
++++++menuItemRadio name='Menu item 3' defaultActionVerb=check checkedState=false
++++button name='ARIA Button' defaultActionVerb=click
++++++staticText name='ARIA Button'
++++++++inlineTextBox name='ARIA Button'
++++button name='ARIA button with tab index' defaultActionVerb=press
++++++staticText name='ARIA button with tab index'
++++++++inlineTextBox name='ARIA button with tab index'
++++button name='ARIA button with negative tab index' defaultActionVerb=press
++++++staticText name='ARIA button with negative tab index'
++++++++inlineTextBox name='ARIA button with negative tab index'
++++genericContainer activedescendantId=button
++++++button name='ARIA button that is an active descendant' defaultActionVerb=press
++++++++staticText name='ARIA button that is an active descendant'
++++++++++inlineTextBox name='ARIA button that is an active descendant'
......@@ -29,3 +29,8 @@ document Name='Action verbs'
++++menuitem Name='Menu item 1'
++++menuitemcheckbox Name='Menu item 2' Toggle.ToggleState='On'
++++menuitemradio Name='Menu item 3' SelectionItem.IsSelected=false
++button Name='ARIA Button'
++button Name='ARIA button with tab index'
++button Name='ARIA button with negative tab index'
++group
++++button Name='ARIA button that is an active descendant'
......@@ -29,3 +29,8 @@ ROLE_SYSTEM_DOCUMENT name='Action verbs' READONLY FOCUSABLE
++++ROLE_SYSTEM_MENUITEM name='Menu item 1' default_action='select' action_name='select'
++++IA2_ROLE_CHECK_MENU_ITEM name='Menu item 2' CHECKED IA2_STATE_CHECKABLE checkable:true default_action='uncheck' action_name='uncheck'
++++IA2_ROLE_RADIO_MENU_ITEM name='Menu item 3' IA2_STATE_CHECKABLE checkable:true default_action='check' action_name='check'
++ROLE_SYSTEM_PUSHBUTTON name='ARIA Button' default_action='click' action_name='click'
++ROLE_SYSTEM_PUSHBUTTON name='ARIA button with tab index' FOCUSABLE default_action='press' action_name='press'
++ROLE_SYSTEM_PUSHBUTTON name='ARIA button with negative tab index' FOCUSABLE default_action='press' action_name='press'
++IA2_ROLE_SECTION
++++ROLE_SYSTEM_PUSHBUTTON name='ARIA button that is an active descendant' FOCUSABLE default_action='press' action_name='press'
......@@ -4,6 +4,8 @@
@WIN-ALLOW:action_name*
@WIN-ALLOW:default_action*
@WIN-ALLOW:haspopup*
@AURALINUX-ALLOW:actions*
@AURALINUX-DENY:checkable
-->
<!doctype html>
<html>
......@@ -34,5 +36,11 @@
<div role="menuitemcheckbox" aria-checked="true">Menu item 2</div>
<div role="menuitemradio">Menu item 3</div>
</div>
<div role="button">ARIA Button</div>
<div role="button" tabindex="1">ARIA button with tab index</div>
<div role="button" tabindex="-1">ARIA button with negative tab index</div>
<div aria-activedescendant="active-descendant-button">
<div role="button" id="active-descendant-button">ARIA button that is an active descendant</div>
</div>
</body>
</html>
......@@ -1866,6 +1866,17 @@ ax::mojom::DefaultActionVerb AXObject::Action() const {
: ax::mojom::DefaultActionVerb::kUncheck;
}
// If this object cannot receive focus and has a button role, use click as
// the default action. On the AuraLinux platform, the press action is a
// signal to users that they can trigger the action using the keyboard, while
// a click action means the user should trigger the action via a simulated
// click. If this object cannot receive focus, it's impossible to trigger it
// with a key press.
if (RoleValue() == ax::mojom::Role::kButton &&
!CanReceiveAccessibilityFocus()) {
return ax::mojom::DefaultActionVerb::kClick;
}
switch (RoleValue()) {
case ax::mojom::Role::kButton:
case ax::mojom::Role::kDisclosureTriangle:
......
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