| Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
|
| diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
|
| index 101e896d2d767232cb3e4f80d33e3cf07bb21949..0e3c5205f96a90d023fd0caa9b7008c56d561952 100644
|
| --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
|
| +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
|
| @@ -51,17 +51,23 @@ Output = function() {
|
| /** @type {!Array.<Object>} */
|
| this.locations_ = [];
|
| /** @type {function()} */
|
| - this.speechStartCallback_ = function() {};
|
| + this.speechStartCallback_;
|
| /** @type {function()} */
|
| - this.speechEndCallback_ = function() {};
|
| + this.speechEndCallback_;
|
| /** @type {function()} */
|
| - this.speechInterruptedCallback_ = function() {};
|
| + this.speechInterruptedCallback_;
|
|
|
| /**
|
| * Current global options.
|
| * @type {{speech: boolean, braille: boolean, location: boolean}}
|
| */
|
| this.formatOptions_ = {speech: true, braille: false, location: true};
|
| +
|
| + /**
|
| + * Speech properties to apply to the entire output.
|
| + * @type {!Object.<string, *>}
|
| + */
|
| + this.speechProperties_ = {};
|
| };
|
|
|
| /**
|
| @@ -81,7 +87,8 @@ Output.RULES = {
|
| braille: ''
|
| },
|
| alert: {
|
| - speak: '@aria_role_alert $name $earcon(ALERT_NONMODAL)'
|
| + speak: '!doNotInterrupt ' +
|
| + '@aria_role_alert $name $earcon(ALERT_NONMODAL) $descendants'
|
| },
|
| button: {
|
| speak: '$name $earcon(BUTTON, @tag_button)'
|
| @@ -307,15 +314,26 @@ Output.prototype = {
|
|
|
| var onEvent = function(evt) {
|
| switch (evt.type) {
|
| - case 'start': this.speechStartCallback_(); break;
|
| - case 'end': this.speechEndCallback_(); break;
|
| - case 'interrupted': this.speechInterruptedCallback_(); break;
|
| + case 'start':
|
| + this.speechStartCallback_();
|
| + break;
|
| + case 'end':
|
| + this.speechEndCallback_();
|
| + break;
|
| + case 'interrupted':
|
| + this.speechInterruptedCallback_ && this.speechInterruptedCallback_();
|
| + break;
|
| }
|
| }.bind(this);
|
|
|
| if (buff.toString()) {
|
| + if (this.speechStartCallback_ ||
|
| + this.speechEndCallback_ ||
|
| + this.speechInterruptedCallback_)
|
| + this.speechProperties_['onEvent'] = onEvent;
|
| +
|
| cvox.ChromeVox.tts.speak(
|
| - buff.toString(), cvox.QueueMode.FLUSH, {onEvent: onEvent});
|
| + buff.toString(), cvox.QueueMode.FLUSH, this.speechProperties_);
|
| }
|
|
|
| var actions = buff.getSpansInstanceOf(Output.Action);
|
| @@ -431,11 +449,17 @@ Output.prototype = {
|
| this.addToSpannable_(buff, node.role, options);
|
| } else if (token == 'value') {
|
| var text = node.attributes.value;
|
| - var offset = buff.getLength();
|
| - if (node.attributes.textSelStart !== undefined) {
|
| - options.annotation = new Output.SelectionSpan(
|
| - node.attributes.textSelStart,
|
| - node.attributes.textSelEnd);
|
| + if (text) {
|
| + var offset = buff.getLength();
|
| + if (node.attributes.textSelStart !== undefined) {
|
| + options.annotation = new Output.SelectionSpan(
|
| + node.attributes.textSelStart,
|
| + node.attributes.textSelEnd);
|
| + }
|
| + } else if (node.role == chrome.automation.RoleType.staticText) {
|
| + // TODO(dtseng): Remove once Blink treats staticText values as
|
| + // names.
|
| + text = node.attributes.name;
|
| }
|
| this.addToSpannable_(buff, text, options);
|
| } else if (token == 'indexInParent') {
|
| @@ -457,6 +481,22 @@ Output.prototype = {
|
| if (node)
|
| this.format_(node, formatString, buff);
|
| }
|
| + } else if (token == 'descendants') {
|
| + if (AutomationPredicate.leaf(node))
|
| + return;
|
| +
|
| + // Construct a range to the leftmost and rightmost leaves.
|
| + var leftmost = AutomationUtil.findNodePre(
|
| + node, Dir.FORWARD, AutomationPredicate.leaf);
|
| + var rightmost = AutomationUtil.findNodePre(
|
| + node, Dir.BACKWARD, AutomationPredicate.leaf);
|
| + if (!leftmost || !rightmost)
|
| + return;
|
| +
|
| + var subrange = new cursors.Range(
|
| + new cursors.Cursor(leftmost, 0),
|
| + new cursors.Cursor(rightmost, 0));
|
| + this.range_(subrange, null, 'navigate', buff);
|
| } else if (node.attributes[token]) {
|
| this.addToSpannable_(buff, node.attributes[token], options);
|
| } else if (node.state[token]) {
|
| @@ -506,6 +546,8 @@ Output.prototype = {
|
| if (msg) {
|
| this.addToSpannable_(buff, msg, options);
|
| }
|
| + } else if (prefix == '!') {
|
| + this.speechProperties_[token] = true;
|
| }
|
| }.bind(this));
|
| },
|
|
|