Commit 42dc0c78 authored by Sara Kato's avatar Sara Kato Committed by Commit Bot

Adjust container computation logic.

Mainly in ARC++ we often see that focus going into containers with
clickable parents. This is evident in lists (as described in bugs), where the containing children will also receive focus.

This CL adds a condition, which considers focusable nodes that have
children with the same name should be considered as a leaf (thus
preventing further focus propagation).

    announced twice.

AX-Relnotes: Ensure that nodes with static text with same name don't get
Bug: b:156426961
Bug: b:154875936
Test: ChromeVoxBackgroundTest.FocusableNamedDivIsNotContainer
Test: manual (open FamilylinkApp, Hangouts app), navigate using search+arrow and note that items are read once.
Change-Id: I569b9059c2a8eb458f9e8684bd4d645b0260b93c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2198047
Commit-Queue: Sara Kato <sarakato@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#770960}
parent d71d0fb7
......@@ -214,7 +214,7 @@ TEST_F('ChromeVoxBackgroundTest', 'ForwardBackwardNavigation', function() {
});
TEST_F('ChromeVoxBackgroundTest', 'CaretNavigation', function() {
// TODO(plundblad): Add braille expectaions when crbug.com/523285 is fixed.
// TODO(plundblad): Add braille expectations when crbug.com/523285 is fixed.
const mockFeedback = this.createMockFeedback();
this.runWithLoadedTree(this.linksAndHeadingsDoc, function() {
mockFeedback.expectSpeech('start');
......@@ -2565,3 +2565,15 @@ TEST_F('ChromeVoxBackgroundTest', 'MenuItemRadio', function() {
.replay();
});
});
TEST_F(
'ChromeVoxBackgroundTest', 'FocusableNamedDivIsNotContainer', function() {
this.runWithLoadedTree(
`<div aria-label="hello world" tabindex="0">hello world</div>`,
function(root) {
const genericContainer =
root.find({role: RoleType.GENERIC_CONTAINER});
assertTrue(AutomationPredicate.object(genericContainer));
assertFalse(AutomationPredicate.container(genericContainer));
});
});
......@@ -38,6 +38,41 @@ const hasActionableDescendant = function(node) {
return result;
};
/**
* A helper to determine whether the children of a node are all
* STATIC_TEXT, and whether the joined names of such children nodes are equal to
* the current nodes name.
* @param {!AutomationNode} node
* @return {boolean}
* @private
*/
const nodeNameContainedInStaticTextChildren = function(node) {
const name = node.name;
let child = node.firstChild;
if (!child) {
return false;
}
let nameIndex = 0;
do {
if (child.role != Role.STATIC_TEXT) {
return false;
}
if (name.substring(nameIndex, nameIndex + child.name.length) !=
child.name) {
return false;
}
nameIndex += child.name.length;
// Either space or empty (i.e. end of string).
const char = name.substring(nameIndex, nameIndex + 1);
child = child.nextSibling;
if ((child && char != ' ') || char != '') {
return false;
}
nameIndex++;
} while (child);
return true;
};
AutomationPredicate = class {
constructor() {}
......@@ -281,6 +316,13 @@ AutomationPredicate = class {
return false;
}
// Sometimes a focusable node will have a static text child with the same
// name. During object navigation, the child will receive focus, resulting
// in the name being read out twice.
if (node.state.focusable && nodeNameContainedInStaticTextChildren(node)) {
return false;
}
return AutomationPredicate.match({
anyRole: [
Role.GENERIC_CONTAINER, Role.DOCUMENT, Role.GROUP, Role.LIST,
......
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