Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Provides output services for ChromeVox. | 6 * @fileoverview Provides output services for ChromeVox. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 goog.provide('Output'); | 9 goog.provide('Output'); |
| 10 goog.provide('Output.EventType'); | 10 goog.provide('Output.EventType'); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 * The speech queue mode for the generated speech utterance. | 85 * The speech queue mode for the generated speech utterance. |
| 86 * @type {cvox.QueueMode} | 86 * @type {cvox.QueueMode} |
| 87 * @private | 87 * @private |
| 88 */ | 88 */ |
| 89 this.queueMode_ = cvox.QueueMode.QUEUE; | 89 this.queueMode_ = cvox.QueueMode.QUEUE; |
| 90 | 90 |
| 91 /** | 91 /** |
| 92 * @type {boolean} | 92 * @type {boolean} |
| 93 * @private | 93 * @private |
| 94 */ | 94 */ |
| 95 this.outputContextFirst_ = localStorage['outputContextFirst'] == 'true'; | 95 this.outputContextFirst_ = false; |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 /** | 98 /** |
| 99 * Delimiter to use between output values. | 99 * Delimiter to use between output values. |
| 100 * @type {string} | 100 * @type {string} |
| 101 */ | 101 */ |
| 102 Output.SPACE = ' '; | 102 Output.SPACE = ' '; |
| 103 | 103 |
| 104 /** | 104 /** |
| 105 * Metadata about supported automation roles. | 105 * Metadata about supported automation roles. |
| 106 * @const {Object<{msgId: string, | 106 * @const {Object<{msgId: string, |
| 107 * earconId: (string|undefined), | 107 * earconId: (string|undefined), |
| 108 * inherits: (string|undefined), | 108 * inherits: (string|undefined), |
| 109 * ignoreAncestry: (boolean|undefined)}>} | 109 * outputContextFirst: (boolean|undefined)}>} |
| 110 * msgId: the message id of the role. | 110 * msgId: the message id of the role. |
| 111 * earconId: an optional earcon to play when encountering the role. | 111 * earconId: an optional earcon to play when encountering the role. |
| 112 * inherits: inherits rules from this role. | 112 * inherits: inherits rules from this role. |
| 113 * ignoreAncestry: don't output ancestry changes when encountering this role. | 113 * outputContextFirst: where to place the context output. |
| 114 * @private | 114 * @private |
| 115 */ | 115 */ |
| 116 Output.ROLE_INFO_ = { | 116 Output.ROLE_INFO_ = { |
| 117 alert: { | 117 alert: { |
| 118 msgId: 'role_alert', | 118 msgId: 'role_alert', |
| 119 earconId: 'ALERT_NONMODAL' | 119 earconId: 'ALERT_NONMODAL' |
| 120 }, | 120 }, |
| 121 alertDialog: { | 121 alertDialog: { |
| 122 msgId: 'role_alertdialog' | 122 msgId: 'role_alertdialog' |
| 123 }, | 123 }, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 142 earconId: 'BUTTON' | 142 earconId: 'BUTTON' |
| 143 }, | 143 }, |
| 144 checkBox: { | 144 checkBox: { |
| 145 msgId: 'role_checkbox' | 145 msgId: 'role_checkbox' |
| 146 }, | 146 }, |
| 147 columnHeader: { | 147 columnHeader: { |
| 148 msgId: 'role_columnheader', | 148 msgId: 'role_columnheader', |
| 149 inherits: 'cell' | 149 inherits: 'cell' |
| 150 }, | 150 }, |
| 151 comboBox: { | 151 comboBox: { |
| 152 msgId: 'role_combobox' | 152 msgId: 'role_combobox', |
| 153 earconId: 'LISTBOX' | |
| 153 }, | 154 }, |
| 154 complementary: { | 155 complementary: { |
| 155 msgId: 'role_complementary', | 156 msgId: 'role_complementary', |
| 156 inherits: 'abstractContainer' | 157 inherits: 'abstractContainer' |
| 157 }, | 158 }, |
| 158 contentInfo: { | 159 contentInfo: { |
| 159 msgId: 'role_contentinfo', | 160 msgId: 'role_contentinfo', |
| 160 inherits: 'abstractContainer' | 161 inherits: 'abstractContainer' |
| 161 }, | 162 }, |
| 162 date: { | 163 date: { |
| 163 msgId: 'input_type_date', | 164 msgId: 'input_type_date', |
| 164 inherits: 'abstractContainer' | 165 inherits: 'abstractContainer' |
| 165 }, | 166 }, |
| 166 definition: { | 167 definition: { |
| 167 msgId: 'role_definition', | 168 msgId: 'role_definition', |
| 168 inherits: 'abstractContainer' | 169 inherits: 'abstractContainer' |
| 169 }, | 170 }, |
| 170 dialog: { | 171 dialog: { |
|
dmazzoni
2016/10/04 20:00:34
How about outputContextFirst for dialog, alertdial
| |
| 171 msgId: 'role_dialog' | 172 msgId: 'role_dialog' |
| 172 }, | 173 }, |
| 173 directory: { | 174 directory: { |
| 174 msgId: 'role_directory', | 175 msgId: 'role_directory', |
| 175 inherits: 'abstractContainer' | 176 inherits: 'abstractContainer' |
| 176 }, | 177 }, |
| 177 document: { | 178 document: { |
| 178 msgId: 'role_document', | 179 msgId: 'role_document', |
| 179 inherits: 'abstractContainer' | 180 inherits: 'abstractContainer' |
| 180 }, | 181 }, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 inherits: 'abstractContainer' | 224 inherits: 'abstractContainer' |
| 224 }, | 225 }, |
| 225 marquee: { | 226 marquee: { |
| 226 msgId: 'role_marquee', | 227 msgId: 'role_marquee', |
| 227 }, | 228 }, |
| 228 math: { | 229 math: { |
| 229 msgId: 'role_math', | 230 msgId: 'role_math', |
| 230 inherits: 'abstractContainer' | 231 inherits: 'abstractContainer' |
| 231 }, | 232 }, |
| 232 menu: { | 233 menu: { |
| 233 msgId: 'role_menu' | 234 msgId: 'role_menu', |
| 235 outputContextFirst: true | |
| 234 }, | 236 }, |
| 235 menuBar: { | 237 menuBar: { |
| 236 msgId: 'role_menubar', | 238 msgId: 'role_menubar', |
| 237 }, | 239 }, |
| 238 menuItem: { | 240 menuItem: { |
| 239 msgId: 'role_menuitem' | 241 msgId: 'role_menuitem' |
| 240 }, | 242 }, |
| 241 menuItemCheckBox: { | 243 menuItemCheckBox: { |
| 242 msgId: 'role_menuitemcheckbox' | 244 msgId: 'role_menuitemcheckbox' |
| 243 }, | 245 }, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 261 popUpButton: { | 263 popUpButton: { |
| 262 msgId: 'role_button', | 264 msgId: 'role_button', |
| 263 earconId: 'POP_UP_BUTTON' | 265 earconId: 'POP_UP_BUTTON' |
| 264 }, | 266 }, |
| 265 radioButton: { | 267 radioButton: { |
| 266 msgId: 'role_radio' | 268 msgId: 'role_radio' |
| 267 }, | 269 }, |
| 268 radioGroup: { | 270 radioGroup: { |
| 269 msgId: 'role_radiogroup', | 271 msgId: 'role_radiogroup', |
| 270 }, | 272 }, |
| 273 rootWebArea: { | |
| 274 outputContextFirst: true | |
| 275 }, | |
| 271 row: { | 276 row: { |
| 272 msgId: 'role_row', | 277 msgId: 'role_row', |
| 273 inherits: 'abstractContainer' | 278 inherits: 'abstractContainer' |
| 274 }, | 279 }, |
| 275 rowHeader: { | 280 rowHeader: { |
| 276 msgId: 'role_rowheader', | 281 msgId: 'role_rowheader', |
| 277 inherits: 'cell' | 282 inherits: 'cell' |
| 278 }, | 283 }, |
| 279 scrollBar: { | 284 scrollBar: { |
| 280 msgId: 'role_scrollbar', | 285 msgId: 'role_scrollbar', |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 inherits: 'abstractContainer' | 321 inherits: 'abstractContainer' |
| 317 }, | 322 }, |
| 318 timer: { | 323 timer: { |
| 319 msgId: 'role_timer' | 324 msgId: 'role_timer' |
| 320 }, | 325 }, |
| 321 toolbar: { | 326 toolbar: { |
| 322 msgId: 'role_toolbar' | 327 msgId: 'role_toolbar' |
| 323 }, | 328 }, |
| 324 toggleButton: { | 329 toggleButton: { |
| 325 msgId: 'role_button', | 330 msgId: 'role_button', |
| 326 inherits: 'checkBox' | 331 inherits: 'checkBox', |
| 332 earconId: 'BUTTON' | |
| 327 }, | 333 }, |
| 328 tree: { | 334 tree: { |
| 329 msgId: 'role_tree' | 335 msgId: 'role_tree' |
| 330 }, | 336 }, |
| 331 treeItem: { | 337 treeItem: { |
| 332 msgId: 'role_treeitem' | 338 msgId: 'role_treeitem' |
| 333 } | 339 } |
| 334 }; | 340 }; |
| 335 | 341 |
| 336 /** | 342 /** |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 884 callback(); | 890 callback(); |
| 885 }.bind(this); | 891 }.bind(this); |
| 886 return this; | 892 return this; |
| 887 }, | 893 }, |
| 888 | 894 |
| 889 /** | 895 /** |
| 890 * Executes all specified output. | 896 * Executes all specified output. |
| 891 */ | 897 */ |
| 892 go: function() { | 898 go: function() { |
| 893 // Speech. | 899 // Speech. |
| 894 var queueMode = this.queueMode_; | 900 var queueMode = cvox.QueueMode.FLUSH; |
| 895 this.speechBuffer_.forEach(function(buff, i, a) { | 901 if (Output.forceModeForNextSpeechUtterance_ !== undefined) |
| 896 if (Output.forceModeForNextSpeechUtterance_ !== undefined && | 902 queueMode = Output.forceModeForNextSpeechUtterance_; |
| 897 buff.length > 0) { | 903 else if (this.queueMode_ !== undefined) |
| 898 queueMode = Output.forceModeForNextSpeechUtterance_; | 904 queueMode = this.queueMode_; |
| 899 Output.forceModeForNextSpeechUtterance_ = undefined; | |
| 900 } | |
| 901 | 905 |
| 902 var speechProps = {}; | 906 if (this.speechBuffer_.length > 0) |
| 907 Output.forceModeForNextSpeechUtterance_ = undefined; | |
| 908 | |
| 909 for (var i = 0; i < this.speechBuffer_.length; i++) { | |
| 910 var buff = this.speechBuffer_[i]; | |
| 911 var speechProps = /** @type {Object} */( | |
| 912 buff.getSpanInstanceOf(Output.SpeechProperties)) || {}; | |
| 913 | |
| 914 speechProps.category = this.speechCategory_; | |
| 915 | |
| 903 (function() { | 916 (function() { |
| 904 var scopedBuff = buff; | 917 var scopedBuff = buff; |
| 905 speechProps = | |
| 906 scopedBuff.getSpanInstanceOf(Output.SpeechProperties) || {}; | |
| 907 speechProps.category = this.speechCategory_; | |
| 908 | |
| 909 speechProps['startCallback'] = function() { | 918 speechProps['startCallback'] = function() { |
| 910 var actions = scopedBuff.getSpansInstanceOf(Output.Action); | 919 var actions = scopedBuff.getSpansInstanceOf(Output.Action); |
| 911 if (actions) { | 920 if (actions) { |
| 912 actions.forEach(function(a) { | 921 actions.forEach(function(a) { |
| 913 a.run(); | 922 a.run(); |
| 914 }); | 923 }); |
| 915 } | 924 } |
| 916 }; | 925 }; |
| 917 }.bind(this)()); | 926 }()); |
| 918 | 927 |
| 919 if (this.speechEndCallback_ && i == a.length - 1) | 928 if (i == this.speechBuffer_.length - 1) |
| 920 speechProps['endCallback'] = this.speechEndCallback_; | 929 speechProps['endCallback'] = this.speechEndCallback_; |
| 921 else | 930 |
| 922 speechProps['endCallback'] = null; | |
| 923 cvox.ChromeVox.tts.speak( | 931 cvox.ChromeVox.tts.speak( |
| 924 buff.toString(), queueMode, speechProps); | 932 buff.toString(), queueMode, speechProps); |
| 925 queueMode = cvox.QueueMode.QUEUE; | 933 queueMode = cvox.QueueMode.QUEUE; |
| 926 }.bind(this)); | 934 } |
| 927 | 935 |
| 928 // Braille. | 936 // Braille. |
| 929 if (this.brailleBuffer_.length) { | 937 if (this.brailleBuffer_.length) { |
| 930 var buff = this.createBrailleOutput_(); | 938 var buff = this.createBrailleOutput_(); |
| 931 var selSpan = | 939 var selSpan = |
| 932 buff.getSpanInstanceOf(Output.SelectionSpan); | 940 buff.getSpanInstanceOf(Output.SelectionSpan); |
| 933 var startIndex = -1, endIndex = -1; | 941 var startIndex = -1, endIndex = -1; |
| 934 if (selSpan) { | 942 if (selSpan) { |
| 935 var valueStart = buff.getSpanStart(selSpan); | 943 var valueStart = buff.getSpanStart(selSpan); |
| 936 var valueEnd = buff.getSpanEnd(selSpan); | 944 var valueEnd = buff.getSpanEnd(selSpan); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 960 * @param {!cursors.Range} range | 968 * @param {!cursors.Range} range |
| 961 * @param {cursors.Range} prevRange | 969 * @param {cursors.Range} prevRange |
| 962 * @param {EventType|Output.EventType} type | 970 * @param {EventType|Output.EventType} type |
| 963 * @param {!Array<Spannable>} buff Buffer to receive rendered output. | 971 * @param {!Array<Spannable>} buff Buffer to receive rendered output. |
| 964 * @private | 972 * @private |
| 965 */ | 973 */ |
| 966 render_: function(range, prevRange, type, buff) { | 974 render_: function(range, prevRange, type, buff) { |
| 967 if (prevRange && !prevRange.isValid()) | 975 if (prevRange && !prevRange.isValid()) |
| 968 prevRange = null; | 976 prevRange = null; |
| 969 | 977 |
| 978 // Scan ancestors to get the value of |outputContextFirst|. | |
| 979 var parent = range.start.node; | |
| 980 while (parent) { | |
| 981 if (Output.ROLE_INFO_[parent.role] && | |
| 982 Output.ROLE_INFO_[parent.role].outputContextFirst) { | |
| 983 this.outputContextFirst_ = true; | |
| 984 break; | |
| 985 } | |
| 986 parent = parent.parent; | |
| 987 } | |
| 988 | |
| 970 if (range.isSubNode()) | 989 if (range.isSubNode()) |
| 971 this.subNode_(range, prevRange, type, buff); | 990 this.subNode_(range, prevRange, type, buff); |
| 972 else | 991 else |
| 973 this.range_(range, prevRange, type, buff); | 992 this.range_(range, prevRange, type, buff); |
| 974 }, | 993 }, |
| 975 | 994 |
| 976 /** | 995 /** |
| 977 * Format the node given the format specifier. | 996 * Format the node given the format specifier. |
| 978 * @param {AutomationNode} node | 997 * @param {AutomationNode} node |
| 979 * @param {string|!Object} format The output format either specified as an | 998 * @param {string|!Object} format The output format either specified as an |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1357 }, | 1376 }, |
| 1358 | 1377 |
| 1359 /** | 1378 /** |
| 1360 * @param {!AutomationNode} node | 1379 * @param {!AutomationNode} node |
| 1361 * @param {!AutomationNode} prevNode | 1380 * @param {!AutomationNode} prevNode |
| 1362 * @param {EventType|Output.EventType} type | 1381 * @param {EventType|Output.EventType} type |
| 1363 * @param {!Array<Spannable>} buff | 1382 * @param {!Array<Spannable>} buff |
| 1364 * @private | 1383 * @private |
| 1365 */ | 1384 */ |
| 1366 ancestry_: function(node, prevNode, type, buff) { | 1385 ancestry_: function(node, prevNode, type, buff) { |
| 1367 // Check to see if ancestry output is ignored. | |
| 1368 if (Output.ROLE_INFO_[node.role] && | |
| 1369 Output.ROLE_INFO_[node.role].ignoreAncestry) | |
| 1370 return; | |
| 1371 | |
| 1372 var prevUniqueAncestors = | 1386 var prevUniqueAncestors = |
| 1373 AutomationUtil.getUniqueAncestors(node, prevNode); | 1387 AutomationUtil.getUniqueAncestors(node, prevNode); |
| 1374 var uniqueAncestors = AutomationUtil.getUniqueAncestors(prevNode, node); | 1388 var uniqueAncestors = AutomationUtil.getUniqueAncestors(prevNode, node); |
| 1375 | 1389 |
| 1376 // First, look up the event type's format block. | 1390 // First, look up the event type's format block. |
| 1377 // Navigate is the default event. | 1391 // Navigate is the default event. |
| 1378 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; | 1392 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; |
| 1379 | 1393 |
| 1380 var getMergedRoleBlock = function(role) { | 1394 var getMergedRoleBlock = function(role) { |
| 1381 var parentRole = (Output.ROLE_INFO_[role] || {}).inherits; | 1395 var parentRole = (Output.ROLE_INFO_[role] || {}).inherits; |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1708 /** | 1722 /** |
| 1709 * Gets the output buffer for braille. | 1723 * Gets the output buffer for braille. |
| 1710 * @return {!Spannable} | 1724 * @return {!Spannable} |
| 1711 */ | 1725 */ |
| 1712 get brailleOutputForTest() { | 1726 get brailleOutputForTest() { |
| 1713 return this.createBrailleOutput_(); | 1727 return this.createBrailleOutput_(); |
| 1714 } | 1728 } |
| 1715 }; | 1729 }; |
| 1716 | 1730 |
| 1717 }); // goog.scope | 1731 }); // goog.scope |
| OLD | NEW |