Commit ced12ea7 authored by Ajit Narayanan's avatar Ajit Narayanan Committed by Commit Bot

Expose user-select:none to accessibility.

This CL makes user-select:none property visible to accessibility
features via a new boolean attribute, kNotUserSelectable. This is,
for example, useful for select-to-speak, which we expect to skip
non-user-selectable text.

The property is default-false in order to be memory-efficient and
backwards-compatible. Most nodes in the DOM will not have user:select
none, so this property will be omitted from the tree unless the user
explicitly marks user:select=none.

Bug: 830106
Change-Id: I7c8ea7b994514c102389a23bfc5d372ea4737da9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2353127
Commit-Queue: Ajit Narayanan <ajitnarayanan@google.com>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798398}
parent 296abcac
......@@ -2343,6 +2343,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityUl) {
RunHtmlTest(FILE_PATH_LITERAL("ul.html"));
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
AccessibilityNotUserSelectable) {
RunCSSTest(FILE_PATH_LITERAL("user-select.html"));
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityVar) {
RunHtmlTest(FILE_PATH_LITERAL("var.html"));
}
......
rootWebArea
++genericContainer ignored
++++genericContainer ignored
++++++genericContainer notUserSelectableStyle=true
++++++++staticText name='1. unselectable' notUserSelectableStyle=true
++++++++++inlineTextBox name='1. unselectable'
++++++genericContainer
++++++++staticText name='2. Selectable'
++++++++++inlineTextBox name='2. Selectable'
++++++genericContainer notUserSelectableStyle=true
++++++++staticText name='3. unselectable' notUserSelectableStyle=true
++++++++++inlineTextBox name='3. unselectable'
++++++genericContainer
++++++++staticText name='4. Selectable'
++++++++++inlineTextBox name='4. Selectable'
++++++list
++++++++listItem
++++++++++listMarker name='• '
++++++++++++staticText name='• '
++++++++++++++inlineTextBox name='• '
++++++++++staticText name='One'
++++++++++++inlineTextBox name='One'
++++++genericContainer ignored notUserSelectableStyle=true
++++++++genericContainer notUserSelectableStyle=true
++++++++++staticText name='Inner' notUserSelectableStyle=true
++++++++++++inlineTextBox name='Inner'
<!--
@BLINK-ALLOW:notUserSelectableStyle*
-->
<div style="user-select:none">1. unselectable </div>
<div style="user-select:text"> 2. Selectable </div>
<div style="user-select:none"> 3. unselectable </div>
<div style="user-select:text"> 4. Selectable </div>
<!-- List bullets are not selectable, but that is not due to user-select,
so they will not have the notUserSelectableStyle attribute -->
<ul>
<li>One</li>
</ul>
<!-- Should inherit -->
<div style="user-select:none">
<div style="user-select:inherit">Inner</div>
</div>
\ No newline at end of file
......@@ -523,6 +523,18 @@ bool AXLayoutObject::IsSelectedFromFocus() const {
is_selected);
}
// Returns true if the object is marked user-select:none
bool AXLayoutObject::IsNotUserSelectable() const {
if (!GetLayoutObject())
return false;
const ComputedStyle* style = GetLayoutObject()->Style();
if (!style)
return false;
return (style->UserSelect() == EUserSelect::kNone);
}
// Returns true if the node's aria-selected attribute should be set to true
// when the node is focused. This is true for only a subset of roles.
bool AXLayoutObject::SelectionShouldFollowFocus() const {
......
......@@ -96,6 +96,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
AccessibilityGrabbedState IsGrabbed() const override;
AccessibilitySelectedState IsSelected() const override;
bool IsSelectedFromFocus() const override;
bool IsNotUserSelectable() const override;
// Whether objects are ignored, i.e. not included in the tree.
AXObjectInclusion DefaultObjectInclusion(
......
......@@ -790,6 +790,11 @@ void AXObject::Serialize(ui::AXNodeData* node_data) {
IsSelectedFromFocus());
}
if (IsNotUserSelectable()) {
node_data->AddBoolAttribute(
ax::mojom::blink::BoolAttribute::kNotUserSelectableStyle, true);
}
if (IsRichlyEditable())
node_data->AddState(ax::mojom::blink::State::kRichlyEditable);
......
......@@ -501,6 +501,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Is the object selected because selection is following focus?
virtual bool IsSelectedFromFocus() const { return false; }
virtual bool IsSelectedOptionActive() const { return false; }
virtual bool IsNotUserSelectable() const { return false; }
virtual bool IsVisible() const;
virtual bool IsVisited() const { return false; }
......
......@@ -1882,6 +1882,8 @@ const char* ToString(ax::mojom::BoolAttribute bool_attribute) {
return "clickable";
case ax::mojom::BoolAttribute::kClipsChildren:
return "clipsChildren";
case ax::mojom::BoolAttribute::kNotUserSelectableStyle:
return "notUserSelectableStyle";
case ax::mojom::BoolAttribute::kSelected:
return "selected";
case ax::mojom::BoolAttribute::kSelectedFromFocus:
......@@ -1926,6 +1928,8 @@ ax::mojom::BoolAttribute ParseBoolAttribute(const char* bool_attribute) {
return ax::mojom::BoolAttribute::kClickable;
if (0 == strcmp(bool_attribute, "clipsChildren"))
return ax::mojom::BoolAttribute::kClipsChildren;
if (0 == strcmp(bool_attribute, "notUserSelectableStyle"))
return ax::mojom::BoolAttribute::kNotUserSelectableStyle;
if (0 == strcmp(bool_attribute, "selected"))
return ax::mojom::BoolAttribute::kSelected;
if (0 == strcmp(bool_attribute, "selectedFromFocus"))
......
......@@ -733,6 +733,12 @@ enum BoolAttribute {
// overflow: hidden or clip children by default.
kClipsChildren,
// Indicates that this node is not selectable because the style has
// user-select: none. Note that there may be other reasons why a node is
// not selectable - for example, bullets in a list. However, this attribute
// is only set on user-select: none.
kNotUserSelectableStyle,
// Indicates whether this node is selected or unselected.
kSelected,
......
......@@ -1575,6 +1575,9 @@ std::string AXNodeData::ToString() const {
case ax::mojom::BoolAttribute::kClipsChildren:
result += " clips_children=" + value;
break;
case ax::mojom::BoolAttribute::kNotUserSelectableStyle:
result += " not_user_selectable=" + value;
break;
case ax::mojom::BoolAttribute::kSelected:
result += " selected=" + value;
break;
......
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