Index: chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
diff --git a/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
index 98aa57ddb5a251bb78c1c27cab04ecc29c90b2c3..3d1569bfc1867a5f8b5c7ab2a0479187a387e243 100644 |
--- a/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
+++ b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
@@ -25,6 +25,9 @@ cvox2.Background = function() { |
*/ |
this.whitelist_ = ['http://www.chromevox.com/', 'chromevox_next_test']; |
+ /** @type {AutomationElement} @private */ |
+ this.currentElement_ = null; |
+ |
// Only needed with unmerged ChromeVox classic loaded before. |
// TODO(dtseng): Refactor all tabs handlers out of |
// accessibility_api_handler.js. |
@@ -86,9 +89,10 @@ cvox2.Background.prototype = { |
* @param {AutomationEvent} evt The event. |
*/ |
onAutomationEvent: function(evt) { |
- var output = evt.target.attributes.name + ' ' + evt.target.role; |
- cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH); |
- cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output)); |
+ switch (evt.type) { |
+ case 'focus': |
+ this.onFocus(evt.target); |
+ } |
}, |
/** |
@@ -96,6 +100,98 @@ cvox2.Background.prototype = { |
* @param {string} command |
*/ |
onGotCommand: function(command) { |
+ if (!this.current_) |
+ return; |
+ |
+ function find(cur, r, pred) { |
+ if (pred(cur)) |
+ return cur; |
+ var child = r ? cur.lastChild() : cur.firstChild(); |
+ while (child) { |
+ var ret = find(child, r, pred); |
+ if (ret) |
+ return ret; |
dmazzoni
2014/09/22 06:44:26
nit: indent
David Tseng
2014/09/22 23:45:34
Done.
|
+ child = r ? child.previousSibling() : child.nextSibling(); |
+ } |
+ } |
+ |
+ function findNextSubtree(cur, r) { |
+ while (cur) { |
+ var next = r ? cur.previousSibling() : cur.nextSibling(); |
+ if (next) |
+ return next; |
+ |
+ cur = cur.parent(); |
+ } |
+ } |
+ |
+ function moveNext(cur, r, pred) { |
+ var next = cur; |
+ do { |
+ if (!(next = findNextSubtree(cur, r))) |
+ return null; |
+ cur = next; |
+ next = find(next, r, pred); |
+ } while (!next); |
+ return next; |
+ } |
+ |
+ var previous = this.current_; |
+ var current = this.current_; |
+ switch (command) { |
+ case 'nextHeading': |
+ current = moveNext(current, false, function(e) { |
+ return e.role == 'heading'; |
+ }); |
+ break; |
+ case 'previousHeading': |
+ current = moveNext(current, true, function(e) { |
Peter Lundblad
2014/09/22 09:30:59
I think using predicates like this is nice. I sug
David Tseng
2014/09/22 23:45:34
Done.
|
+ return e.role == 'heading'; |
+ }); |
+ break; |
+ case 'nextLine': |
+ current = moveNext(current, false, function(e) { |
+ return e.role == 'inlineTextBox'; |
dmazzoni
2014/09/22 06:44:26
FWIW, since inline text boxes aren't actually node
David Tseng
2014/09/22 23:41:29
I actually think leaving them in the tree will sim
|
+ }); |
+ break; |
+ case 'previousLine': |
+ current = moveNext(current, true, function(e) { |
+ return e.role == 'inlineTextBox'; |
+ }); |
+ break; |
+ case 'nextLink': |
+ current = moveNext(current, false, function(e) { |
+ return e.role == 'link'; |
+ }); |
+ break; |
+ case 'previousLink': |
+ current = moveNext(current, true, function(e) { |
+ return e.role == 'link'; |
+ }); |
+ break; |
+ } |
+ if (current) |
+ current.focus(); |
+ this.onFocus(current || previous); |
+ }, |
+ |
+ /** |
+ * Provides all feedback once ChromeVox's focus changes. |
+ * @param {AutomationElement} element The newly focused element. |
+ */ |
+ onFocus: function(element) { |
+ var container = element; |
+ while (container && (container.role == 'inlineTextBox' || |
+ container.role == 'staticText')) |
+ container = container.parent(); |
+ |
+ var role = container ? container.role : element.role; |
+ |
+ var output = |
+ [element.attributes.name, element.attributes.value, role].join(','); |
+ cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH); |
+ cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output)); |
+ this.current_ = element; |
}, |
/** |