Commit 1c15aee7 authored by Aaron Leventhal's avatar Aaron Leventhal Committed by Commit Bot

Refresh selected state on active descendants

Items in single selection containers that have accessibility focus
should get the selected state. Code to mirror focus to selection exists,
but the selected state must be refreshed.

Bug: 846089
Change-Id: I90eb6aaec3be196b78126241ebf7e3d38ccda7c2
Reviewed-on: https://chromium-review.googlesource.com/1070520
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561353}
parent 73b21d67
AXExpandedChanged on AXComboBox AXExpandedChanged on AXComboBox
AXSelectedChildrenChanged on AXComboBox AXSelectedChildrenChanged on AXComboBox
AXSelectedChildrenChanged on AXList
EVENT_OBJECT_FOCUS on <li#option1> role=ROLE_SYSTEM_LISTITEM name="Apple" FOCUSED,FOCUSABLE,SELECTABLE EVENT_OBJECT_FOCUS on <li#option1> role=ROLE_SYSTEM_LISTITEM name="Apple" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
EVENT_OBJECT_SELECTION on <li#option1> role=ROLE_SYSTEM_LISTITEM name="Apple" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
EVENT_OBJECT_SELECTIONWITHIN on <ul#list> role=ROLE_SYSTEM_LIST IA2_STATE_VERTICAL
EVENT_OBJECT_STATECHANGE on <input> role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION EVENT_OBJECT_STATECHANGE on <input> role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION
EVENT_OBJECT_STATECHANGE on <li#option1> role=ROLE_SYSTEM_LISTITEM name="Apple" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on <input> role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on <input> role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION
EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Apple" FOCUSED,FOCUSABLE,SELECTABLE EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Apple" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
EVENT_OBJECT_SELECTION on <li#option3> role=ROLE_SYSTEM_LISTITEM name="Banana" SELECTED,FOCUSABLE,SELECTABLE
EVENT_OBJECT_SELECTIONWITHIN on <ul#list> role=ROLE_SYSTEM_LIST IA2_STATE_VERTICAL
EVENT_OBJECT_STATECHANGE on <li#option3> role=ROLE_SYSTEM_LISTITEM name="Banana" SELECTED,FOCUSABLE,SELECTABLE
IA2_EVENT_TEXT_CARET_MOVED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION IA2_EVENT_TEXT_CARET_MOVED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION
AXSelectedChildrenChanged on AXComboBox AXSelectedChildrenChanged on AXComboBox
AXSelectedChildrenChanged on AXList
EVENT_OBJECT_FOCUS on <li#option3> role=ROLE_SYSTEM_LISTITEM name="Banana" FOCUSED,FOCUSABLE,SELECTABLE EVENT_OBJECT_FOCUS on <li#option3> role=ROLE_SYSTEM_LISTITEM name="Banana" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
EVENT_OBJECT_SELECTION on <li#option3> role=ROLE_SYSTEM_LISTITEM name="Banana" SELECTED,FOCUSABLE,SELECTABLE
EVENT_OBJECT_SELECTIONWITHIN on <ul#list> role=ROLE_SYSTEM_LIST IA2_STATE_VERTICAL
EVENT_OBJECT_STATECHANGE on <li#option3> role=ROLE_SYSTEM_LISTITEM name="Banana" SELECTED,FOCUSABLE,SELECTABLE
IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on <input> role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on <input> role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE,IA2_STATE_SUPPORTS_AUTOCOMPLETION
AXFocusedUIElementChanged on AXRow AXTitle="Minor Ninth" AXFocusedUIElementChanged on AXRow AXTitle="Minor Ninth"
AXSelectedChildrenChanged on AXOutline
AXSelectedRowsChanged on AXOutline AXSelectedRowsChanged on AXOutline
...@@ -458,16 +458,29 @@ AccessibilitySelectedState AXLayoutObject::IsSelected() const { ...@@ -458,16 +458,29 @@ AccessibilitySelectedState AXLayoutObject::IsSelected() const {
// Selection follows focus, but ONLY in single selection containers, // Selection follows focus, but ONLY in single selection containers,
// and only if aria-selected was not present to override // and only if aria-selected was not present to override
return IsSelectedFromFocus() ? kSelectedStateTrue : kSelectedStateFalse;
}
// In single selection containers, selection follows focus unless aria_selected
// is set to false.
bool AXLayoutObject::IsSelectedFromFocus() const {
// If not a single selection container, selection does not follow focus.
AXObject* container = ContainerWidget(); AXObject* container = ContainerWidget();
if (!container || container->IsMultiSelectable()) if (!container || container->IsMultiSelectable())
return kSelectedStateFalse; return false;
// If this object is not accessibility focused, then it is not selected from
// focus.
AXObject* focused_object = AXObjectCache().FocusedObject(); AXObject* focused_object = AXObjectCache().FocusedObject();
return (focused_object == this || if (focused_object != this &&
(focused_object && focused_object->ActiveDescendant() == this)) (!focused_object || focused_object->ActiveDescendant() != this))
? kSelectedStateTrue return false;
: kSelectedStateFalse;
// In single selection container and accessibility focused => true if
// aria-selected wasn't used as an override.
bool is_selected;
return !HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kSelected,
is_selected);
} }
// //
...@@ -2214,8 +2227,21 @@ void AXLayoutObject::HandleActiveDescendantChanged() { ...@@ -2214,8 +2227,21 @@ void AXLayoutObject::HandleActiveDescendantChanged() {
if (!GetLayoutObject()) if (!GetLayoutObject())
return; return;
Vector<String> ids;
TokenVectorFromAttribute(ids, aria_activedescendantAttr);
if (!ids.IsEmpty())
AXObjectCache().UpdateReverseRelations(this, ids);
AXObject* focused_object = AXObjectCache().FocusedObject(); AXObject* focused_object = AXObjectCache().FocusedObject();
if (focused_object == this && SupportsARIAActiveDescendant()) { if (focused_object == this && SupportsARIAActiveDescendant()) {
AXObject* active_descendant = ActiveDescendant();
if (active_descendant && active_descendant->IsSelectedFromFocus()) {
// In single selection containers, selection follows focus, so a selection
// changed event must be fired. This ensures the AT is notified that the
// selected state has changed, so that it does not read "unselected" as
// the user navigates through the items.
AXObjectCache().HandleAriaSelectedChanged(active_descendant->GetNode());
}
AXObjectCache().PostNotification( AXObjectCache().PostNotification(
GetLayoutObject(), AXObjectCacheImpl::kAXActiveDescendantChanged); GetLayoutObject(), AXObjectCacheImpl::kAXActiveDescendantChanged);
} }
...@@ -2418,7 +2444,6 @@ void AXLayoutObject::LineBreaks(Vector<int>& line_breaks) const { ...@@ -2418,7 +2444,6 @@ void AXLayoutObject::LineBreaks(Vector<int>& line_breaks) const {
// Private. // Private.
// //
bool AXLayoutObject::IsTabItemSelected() const { bool AXLayoutObject::IsTabItemSelected() const {
if (!IsTabItem() || !GetLayoutObject()) if (!IsTabItem() || !GetLayoutObject())
return false; return false;
......
...@@ -86,6 +86,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject { ...@@ -86,6 +86,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
// Check object state. // Check object state.
bool IsFocused() const override; bool IsFocused() const override;
AccessibilitySelectedState IsSelected() const override; AccessibilitySelectedState IsSelected() const override;
bool IsSelectedFromFocus() const override;
// Whether objects are ignored, i.e. not included in the tree. // Whether objects are ignored, i.e. not included in the tree.
AXObjectInclusion DefaultObjectInclusion( AXObjectInclusion DefaultObjectInclusion(
......
...@@ -379,6 +379,8 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> { ...@@ -379,6 +379,8 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
virtual AccessibilitySelectedState IsSelected() const { virtual AccessibilitySelectedState IsSelected() const {
return kSelectedStateUndefined; return kSelectedStateUndefined;
} }
// Is the object selected because selection is following focus?
virtual bool IsSelectedFromFocus() const { return false; }
virtual bool IsSelectedOptionActive() const { return false; } virtual bool IsSelectedOptionActive() const { return false; }
virtual bool IsVisible() const { return true; } virtual bool IsVisible() const { return true; }
virtual bool IsVisited() const { return false; } virtual bool IsVisited() const { return false; }
......
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