Commit a135032a authored by dtseng's avatar dtseng Committed by Commit bot

Cleanup AutomationUtil.findNodeUntil, fix wrapping when moving by line

1. AutomationUtil.findNodeUntil isn't entirely clear due to the use of a callback that wants to keep track of the previous node being visited. This has since become wrong because of the changes made to AutomationTreeWalker. Instead, let's just call AutomationUtil.findNextNode which should gibve us the proper linearization. Take pairs in order and apply the predicate.

2. wrapping by line didn't quite work as expected because of the asymmetric nature of the linearization. We need to get to the end when wrapping from the beginning to the end and start applying our predicate. Note that this is subject to some weird corner cases depending on how we write the predicates (e.g. ones that check for children).

3. Ensure we consider invisible nodes to be leaves. They should also be ignored when encountered (this is already done).

TEST=navigate around using ChromeVox Next on the shelf. Observe desirable behaviors.

Review URL: https://codereview.chromium.org/1622803002

Cr-Commit-Position: refs/heads/master@{#371620}
parent b4ff54bb
...@@ -143,6 +143,7 @@ AutomationPredicate.leaf = function(node) { ...@@ -143,6 +143,7 @@ AutomationPredicate.leaf = function(node) {
node.role == RoleType.popUpButton || node.role == RoleType.popUpButton ||
node.role == RoleType.slider || node.role == RoleType.slider ||
node.role == RoleType.textField || node.role == RoleType.textField ||
node.state.invisible ||
node.children.every(function(n) { node.children.every(function(n) {
return n.state.invisible; return n.state.invisible;
}); });
......
...@@ -115,44 +115,22 @@ AutomationUtil.findNextNode = function(cur, dir, pred, opt_restrictions) { ...@@ -115,44 +115,22 @@ AutomationUtil.findNextNode = function(cur, dir, pred, opt_restrictions) {
/** /**
* Given nodes a_1, ..., a_n starting at |cur| in pre order traversal, apply * Given nodes a_1, ..., a_n starting at |cur| in pre order traversal, apply
* |pred| to a_i and a_(i - 1) until |pred| is satisfied. Returns a_(i - 1) or * |pred| to a_i and a_(i - 1) until |pred| is satisfied. Returns a_(i - 1) or
* a_i (depending on opt_options.before) or null if no match was found. * a_i (depending on opt_before) or null if no match was found.
* @param {!AutomationNode} cur * @param {!AutomationNode} cur
* @param {Dir} dir * @param {Dir} dir
* @param {AutomationPredicate.Binary} pred * @param {AutomationPredicate.Binary} pred
* @param {{filter: (AutomationPredicate.Unary|undefined), * @param {boolean=} opt_before True to return a_(i - 1); a_i otherwise.
* before: boolean?}=} opt_options * Defaults to false.
* filter - Filters which candidate nodes to consider. Defaults to leaf
* only.
* before - True to return a_(i - 1); a_i otherwise. Defaults to false.
* @return {AutomationNode} * @return {AutomationNode}
*/ */
AutomationUtil.findNodeUntil = function(cur, dir, pred, opt_options) { AutomationUtil.findNodeUntil = function(cur, dir, pred, opt_before) {
opt_options = var before = cur;
opt_options || {filter: AutomationPredicate.leaf, before: false}; var after = before;
if (!opt_options.filter) do {
opt_options.filter = AutomationPredicate.leaf; before = after;
after = AutomationUtil.findNextNode(before, dir, AutomationPredicate.leaf);
var before = null; } while (after && !pred(before, after));
var after = null; return opt_before ? before : after;
var prev = cur;
AutomationUtil.findNextNode(cur,
dir,
function(candidate) {
if (!opt_options.filter(candidate))
return false;
var satisfied = pred(prev, candidate);
prev = candidate;
if (!satisfied)
before = candidate;
else
after = candidate;
return satisfied;
},
{leaf: AutomationPredicate.leaf, skipInitialSubtree: true});
return opt_options.before ? before : after;
}; };
/** /**
......
...@@ -238,7 +238,7 @@ cursors.Cursor.prototype = { ...@@ -238,7 +238,7 @@ cursors.Cursor.prototype = {
switch (movement) { switch (movement) {
case Movement.BOUND: case Movement.BOUND:
newNode = AutomationUtil.findNodeUntil(newNode, dir, newNode = AutomationUtil.findNodeUntil(newNode, dir,
AutomationPredicate.linebreak, {before: true}); AutomationPredicate.linebreak, true);
newNode = newNode || this.node_; newNode = newNode || this.node_;
newIndex = newIndex =
dir == Dir.FORWARD ? this.getText(newNode).length : 0; dir == Dir.FORWARD ? this.getText(newNode).length : 0;
...@@ -290,10 +290,17 @@ cursors.WrappingCursor.prototype = { ...@@ -290,10 +290,17 @@ cursors.WrappingCursor.prototype = {
if (movement == Movement.DIRECTIONAL && result.equals(this)) { if (movement == Movement.DIRECTIONAL && result.equals(this)) {
var pred = unit == Unit.DOM_NODE ? var pred = unit == Unit.DOM_NODE ?
AutomationPredicate.leafDomNode : AutomationPredicate.leaf; AutomationPredicate.leafDomNode : AutomationPredicate.leaf;
var root = this.node; var endpoint = this.node;
while (!AutomationUtil.isTraversalRoot(root) && root.parent) while (!AutomationUtil.isTraversalRoot(endpoint) && endpoint.parent)
root = root.parent; endpoint = endpoint.parent;
var wrappedNode = AutomationUtil.findNodePre(root, dir, pred); if (dir == Dir.BACKWARD) {
while (endpoint.lastChild)
endpoint = endpoint.lastChild;
}
var wrappedNode = endpoint;
if (!pred(wrappedNode))
wrappedNode = AutomationUtil.findNextNode(endpoint, dir, pred);
if (wrappedNode) { if (wrappedNode) {
cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP);
return new cursors.WrappingCursor(wrappedNode, cursors.NODE_INDEX); return new cursors.WrappingCursor(wrappedNode, cursors.NODE_INDEX);
......
...@@ -298,7 +298,7 @@ TEST_F('CursorsTest', 'WrappingCursors', function() { ...@@ -298,7 +298,7 @@ TEST_F('CursorsTest', 'WrappingCursors', function() {
var para = root.firstChild; var para = root.firstChild;
var cursor = new cursors.WrappingCursor(para, -1); var cursor = new cursors.WrappingCursor(para, -1);
cursor = cursor.move(DOM_NODE, DIRECTIONAL, BACKWARD); cursor = cursor.move(DOM_NODE, DIRECTIONAL, BACKWARD);
assertEquals(root.lastChild.firstChild, cursor.node); assertEquals(root.lastChild.firstChild.firstChild, cursor.node);
cursor = cursor.move(DOM_NODE, DIRECTIONAL, FORWARD); cursor = cursor.move(DOM_NODE, DIRECTIONAL, FORWARD);
assertEquals(root.firstChild.firstChild, cursor.node); assertEquals(root.firstChild.firstChild, cursor.node);
}); });
......
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