Commit 6390b8bf authored by Aaron Leventhal's avatar Aaron Leventhal Committed by Commit Bot

Android a11y: do not mark as scrollable unless user scrollable

When objects are only programmatically scrollable, e.g. overflow:hidden,
as opposed to overflow:auto|scroll, do not mark them as scrollable.

Bug: 1055344
Change-Id: Ib5ade11a7a92720d6571acf6d65112696f2a2535
Cq-Do-Not-Cancel-Tryjobs: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2070232Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Auto-Submit: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745498}
parent 82ede06e
......@@ -327,7 +327,7 @@ bool BrowserAccessibilityAndroid::IsRangeType() const {
}
bool BrowserAccessibilityAndroid::IsScrollable() const {
return HasIntAttribute(ax::mojom::IntAttribute::kScrollXMax);
return GetBoolAttribute(ax::mojom::BoolAttribute::kScrollable);
}
bool BrowserAccessibilityAndroid::IsSelected() const {
......
......@@ -1161,7 +1161,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
}
if (src.IsScrollableContainer()) {
dst->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, true);
// Only mark as scrollable if user has actual scrollbars to use.
dst->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable,
src.IsUserScrollable());
// Provide x,y scroll info if scrollable in any way (programmatically or via
// user).
const gfx::Point& scroll_offset = src.GetScrollOffset();
dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, scroll_offset.x());
dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, scroll_offset.y());
......
android.webkit.WebView focusable focused scrollable
android.webkit.WebView focusable focused
++android.view.View
++++android.widget.Button role_description='button' clickable focusable name='Button'
++android.view.View
......
android.webkit.WebView focusable focused scrollable
++android.view.View name='no overflow'
++android.view.View
++++android.view.View name='clipped'
++android.widget.EditText clickable editable_text focusable has_non_empty_value multiline scrollable name='ab cd' text_change_added_count=5
++android.view.View
++++android.view.View name='tiny'
++android.view.View scrollable
++++android.view.View name='x=hidden'
++android.view.View scrollable name='x=auto'
++++android.view.View name='x=auto'
++android.view.View scrollable name='x=scroll'
++++android.view.View name='x=scroll'
++android.view.View name='x=visible'
++android.view.View scrollable
++++android.view.View name='y=hidden'
++android.view.View scrollable name='y=auto'
++++android.view.View name='y=auto'
++android.view.View scrollable name='y=scroll'
++++android.view.View name='y=scroll'
++android.view.View name='y=visible'
\ No newline at end of file
[document web]
++[paragraph]
++++[static] name='no overflow'
++[section]
++++[paragraph]
++++++[static] name='clipped'
++[entry] selectable-text
++[section]
++++[paragraph]
++++++[static] name='tiny'
++[section]
++++[paragraph]
++++++[static] name='x=hidden'
++[section] name='x=auto'
++++[paragraph]
++++++[static] name='x=auto'
++[section] name='x=scroll'
++++[paragraph]
++++++[static] name='x=scroll'
++[paragraph]
++++[static] name='x=visible'
++[section]
++++[paragraph]
++++++[static] name='y=hidden'
++[section] name='y=auto'
++++[paragraph]
++++++[static] name='y=auto'
++[section] name='y=scroll'
++++[paragraph]
++++++[static] name='y=scroll'
++[paragraph]
++++[static] name='y=visible'
\ No newline at end of file
rootWebArea scrollXMin=0
rootWebArea scrollXMin=0 scrollable=true
++genericContainer ignored
++++genericContainer ignored
++++++paragraph
++++++++staticText name='no overflow'
++++++++++inlineTextBox name='no overflow'
++++genericContainer scrollXMin=0
++++++paragraph
++++++++staticText name='clipped'
++++++++++inlineTextBox name='clipped'
++++textField multiline value='ab cd' scrollXMin=0 scrollable=true
++++++genericContainer
++++++++staticText name='ab cd'
++++++++++inlineTextBox name='ab'
++++++++++inlineTextBox name=' '
++++++++++inlineTextBox name='cd'
++++genericContainer ignored
++++++genericContainer
++++++++paragraph
++++++++++staticText name='tiny'
++++++++++++inlineTextBox name='tiny'
++++genericContainer ignored
++++++genericContainer scrollXMin=0
++++++genericContainer scrollXMin=0 scrollable=true
++++++++paragraph
++++++++++staticText name='x=hidden'
++++++++++++inlineTextBox name='x=hidden'
++++++genericContainer name='x=auto' scrollXMin=0
++++++genericContainer name='x=auto' scrollXMin=0 scrollable=true
++++++++paragraph
++++++++++staticText name='x=auto'
++++++++++++inlineTextBox name='x=auto'
++++++genericContainer name='x=scroll' scrollXMin=0
++++++genericContainer name='x=scroll' scrollXMin=0 scrollable=true
++++++++paragraph
++++++++++staticText name='x=scroll'
++++++++++++inlineTextBox name='x=scroll'
......@@ -27,15 +37,15 @@ rootWebArea scrollXMin=0
++++++++++staticText name='x=visible'
++++++++++++inlineTextBox name='x=visible'
++++genericContainer ignored
++++++genericContainer scrollXMin=0
++++++genericContainer scrollXMin=0 scrollable=true
++++++++paragraph
++++++++++staticText name='y=hidden'
++++++++++++inlineTextBox name='y=hidden'
++++++genericContainer name='y=auto' scrollXMin=0
++++++genericContainer name='y=auto' scrollXMin=0 scrollable=true
++++++++paragraph
++++++++++staticText name='y=auto'
++++++++++++inlineTextBox name='y=auto'
++++++genericContainer name='y=scroll' scrollXMin=0
++++++genericContainer name='y=scroll' scrollXMin=0 scrollable=true
++++++++paragraph
++++++++++staticText name='y=scroll'
++++++++++++inlineTextBox name='y=scroll'
......
Document IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=true Scroll.VerticallyScrollable=false
++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++Text Name='no overflow' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group IsControlElement=false IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=true Scroll.VerticallyScrollable=true
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='clipped' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Edit IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=false Scroll.VerticallyScrollable=true Value.Value='ab cd'
++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='tiny' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group IsControlElement=false IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=true Scroll.VerticallyScrollable=false
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='x=hidden' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group Name='x=auto' IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=true Scroll.VerticallyScrollable=false
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='x=auto' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group Name='x=scroll' IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=true Scroll.VerticallyScrollable=false
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='x=scroll' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++Text Name='x=visible' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group IsControlElement=false IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=false Scroll.VerticallyScrollable=true
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='y=hidden' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group Name='y=auto' IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=false Scroll.VerticallyScrollable=true
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='y=auto' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group Name='y=scroll' IsScrollPatternAvailable=true IsScrollItemPatternAvailable=true Scroll.HorizontallyScrollable=false Scroll.VerticallyScrollable=true
++++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++++Text Name='y=scroll' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++Group IsControlElement=false IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
++++Text Name='y=visible' IsScrollPatternAvailable=false IsScrollItemPatternAvailable=true
<!--
* Test scrollXMin -- the presence of this indicates something is scrollable.
@BLINK-ALLOW:scrollXMin=*
@BLINK-ALLOW:scrollable=true
@UIA-WIN-ALLOW:*ScrollItemPatternAvailable*
@UIA-WIN-ALLOW:*ScrollPatternAvailable*
@UIA-WIN-ALLOW:*Scrollable*
-->
<html>
<style>
body { font-style: monospace; width: 999px;}
.clipped { width: 25px; height: 25px; overflow: hidden; }
.x-overflow > div { width: 25px; height: 50px;}
.x-overflow > div > p { margin: 0; }
.y-overflow > div { height: 25px; }
......@@ -12,9 +17,15 @@
</style>
<body>
<div class="no-overflow"> <!-- Not scrollable -->
<p>no overflow
<p>no overflow <!-- Default is overflow: visible -->
</div>
<div class="clipped"> <!-- Not scrollable -->
<p>clipped <!-- Default is overflow: visible -->
</div>
<textarea rows="1" cols="2">ab cd</textarea> <!-- User scrollable -->
<div class="not-enough-content-to-scroll"> <!-- Not scrollable -->
<div style="overflow: scroll; width: 100px; height: 100px">
<p>tiny
......@@ -22,13 +33,13 @@
</div>
<div class="x-overflow">
<div style="overflow-x: hidden;"> <!-- Scrollable -->
<div style="overflow-x: hidden;"> <!-- Actually user scrollable, because overflow-x=hidden changes overflow-y to auto -->
<p>x=hidden
</div>
<div style="overflow-x: auto;"> <!-- Scrollable -->
<div style="overflow-x: auto;"> <!-- User scrollable if overflow -->
<p>x=auto
</div>
<div style="overflow-x: scroll;"> <!-- Scrollable -->
<div style="overflow-x: scroll;"> <!-- User scrollable if overflow -->
<p>x=scroll
</div>
<div style="overflow-x: visible;"> <!-- Not scrollable -->
......@@ -37,13 +48,13 @@
</div>
<div class="y-overflow">
<div style="overflow-y: hidden;"> <!-- Scrollable -->
<div style="overflow-y: hidden;"> <!-- Actually user scrollable, because overflow-y=hidden changes overflow-x to auto -->
<p>y=hidden
</div>
<div style="overflow-y: auto;"> <!-- Scrollable -->
<div style="overflow-y: auto;"> <!-- Use scrollable if overflow -->
<p>y=auto
</div>
<div style="overflow-y: scroll;"> <!-- Scrollable -->
<div style="overflow-y: scroll;"> <!-- Use scrollable if overflow -->
<p>y=scroll
</div>
<div style="overflow-y: visible;"> <!-- Not scrollable -->
......
......@@ -355,7 +355,10 @@ class WebAXObject {
WebVector<int>& ends) const;
// Scrollable containers.
// Programmatically scrollable.
BLINK_EXPORT bool IsScrollableContainer() const;
// Also scrollable by user.
BLINK_EXPORT bool IsUserScrollable() const;
BLINK_EXPORT gfx::Point GetScrollOffset() const;
BLINK_EXPORT gfx::Point MinimumScrollOffset() const;
BLINK_EXPORT gfx::Point MaximumScrollOffset() const;
......
......@@ -2749,6 +2749,17 @@ bool AXObject::IsScrollableContainer() const {
return !!GetScrollableAreaIfScrollable();
}
bool AXObject::IsUserScrollable() const {
if (!GetScrollableAreaIfScrollable() || !GetLayoutObject())
return false;
const ComputedStyle* style = GetLayoutObject()->Style();
if (!style)
return false;
return style->ScrollsOverflowY() || style->ScrollsOverflowX();
}
IntPoint AXObject::GetScrollOffset() const {
ScrollableArea* area = GetScrollableAreaIfScrollable();
if (!area)
......
......@@ -913,6 +913,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Scrollable containers.
bool IsScrollableContainer() const;
bool IsUserScrollable() const; // Only true if actual scrollbars are present.
IntPoint GetScrollOffset() const;
IntPoint MinimumScrollOffset() const;
IntPoint MaximumScrollOffset() const;
......
......@@ -1528,6 +1528,12 @@ bool WebAXObject::IsScrollableContainer() const {
return private_->IsScrollableContainer();
}
bool WebAXObject::IsUserScrollable() const {
if (IsDetached())
return false;
return private_->IsUserScrollable();
}
gfx::Point WebAXObject::GetScrollOffset() const {
if (IsDetached())
return gfx::Point();
......
......@@ -719,7 +719,9 @@ enum BoolAttribute {
// Set on a canvas element if it has fallback content.
kCanvasHasFallback,
// Indicates this node is scrollable (Android only).
// Indicates this node is user-scrollable, e.g. overflow:scroll|auto, as
// opposed to only programmatically scrollable, like overflow:hidden, or
// not scrollable at all, e.g. overflow:visible.
kScrollable,
// A hint to clients that the node is clickable.
......
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