OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 Handles automation from a desktop automation node. | 6 * @fileoverview Handles automation from a desktop automation node. |
7 */ | 7 */ |
8 | 8 |
9 goog.provide('DesktopAutomationHandler'); | 9 goog.provide('DesktopAutomationHandler'); |
10 | 10 |
11 goog.require('AutomationObjectConstructorInstaller'); | 11 goog.require('AutomationObjectConstructorInstaller'); |
12 goog.require('BaseAutomationHandler'); | 12 goog.require('BaseAutomationHandler'); |
| 13 goog.require('ChromeVoxAutomationEvent'); |
13 goog.require('ChromeVoxState'); | 14 goog.require('ChromeVoxState'); |
14 goog.require('Stubs'); | 15 goog.require('Stubs'); |
15 goog.require('editing.TextEditHandler'); | 16 goog.require('editing.TextEditHandler'); |
16 | 17 |
17 goog.scope(function() { | 18 goog.scope(function() { |
18 var AutomationEvent = chrome.automation.AutomationEvent; | 19 var AutomationEvent = chrome.automation.AutomationEvent; |
19 var AutomationNode = chrome.automation.AutomationNode; | 20 var AutomationNode = chrome.automation.AutomationNode; |
20 var Dir = constants.Dir; | 21 var Dir = constants.Dir; |
21 var EventType = chrome.automation.EventType; | 22 var EventType = chrome.automation.EventType; |
22 var RoleType = chrome.automation.RoleType; | 23 var RoleType = chrome.automation.RoleType; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 this.addListener_(e.textChanged, this.onTextChanged); | 66 this.addListener_(e.textChanged, this.onTextChanged); |
66 this.addListener_(e.textSelectionChanged, this.onTextSelectionChanged); | 67 this.addListener_(e.textSelectionChanged, this.onTextSelectionChanged); |
67 this.addListener_(e.valueChanged, this.onValueChanged); | 68 this.addListener_(e.valueChanged, this.onValueChanged); |
68 | 69 |
69 AutomationObjectConstructorInstaller.init(node, function() { | 70 AutomationObjectConstructorInstaller.init(node, function() { |
70 chrome.automation.getFocus((function(focus) { | 71 chrome.automation.getFocus((function(focus) { |
71 if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) | 72 if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) |
72 return; | 73 return; |
73 | 74 |
74 if (focus) { | 75 if (focus) { |
75 this.onFocus( | 76 this.onFocus(new ChromeVoxAutomationEvent( |
76 new chrome.automation.AutomationEvent( | 77 EventType.focus, focus, 'page')); |
77 EventType.focus, focus, 'page')); | |
78 } | 78 } |
79 }).bind(this)); | 79 }).bind(this)); |
80 }.bind(this)); | 80 }.bind(this)); |
81 }; | 81 }; |
82 | 82 |
83 /** | 83 /** |
84 * Time to wait until processing more value changed events. | 84 * Time to wait until processing more value changed events. |
85 * @const {number} | 85 * @const {number} |
86 */ | 86 */ |
87 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 500; | 87 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 500; |
88 | 88 |
89 /** | 89 /** |
90 * Controls announcement of non-user-initiated events. | 90 * Controls announcement of non-user-initiated events. |
91 * @type {boolean} | 91 * @type {boolean} |
92 */ | 92 */ |
93 DesktopAutomationHandler.announceActions = false; | 93 DesktopAutomationHandler.announceActions = false; |
94 | 94 |
95 DesktopAutomationHandler.prototype = { | 95 DesktopAutomationHandler.prototype = { |
96 __proto__: BaseAutomationHandler.prototype, | 96 __proto__: BaseAutomationHandler.prototype, |
97 | 97 |
98 /** @override */ | 98 /** @override */ |
99 willHandleEvent_: function(evt) { | 99 willHandleEvent_: function(evt) { |
100 return !cvox.ChromeVox.isActive; | 100 return !cvox.ChromeVox.isActive; |
101 }, | 101 }, |
102 | 102 |
103 /** | 103 /** |
104 * Provides all feedback once ChromeVox's focus changes. | 104 * Provides all feedback once ChromeVox's focus changes. |
105 * @param {!AutomationEvent} evt | 105 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
106 */ | 106 */ |
107 onEventDefault: function(evt) { | 107 onEventDefault: function(evt) { |
108 var node = evt.target; | 108 var node = evt.target; |
109 if (!node) | 109 if (!node) |
110 return; | 110 return; |
111 | 111 |
112 // Decide whether to announce and sync this event. | 112 // Decide whether to announce and sync this event. |
113 if (!DesktopAutomationHandler.announceActions && evt.eventFrom == 'action') | 113 if (!DesktopAutomationHandler.announceActions && evt.eventFrom == 'action') |
114 return; | 114 return; |
115 | 115 |
(...skipping 17 matching lines...) Expand all Loading... |
133 output.withBraille( | 133 output.withBraille( |
134 ChromeVoxState.instance.currentRange, prevRange, evt.type); | 134 ChromeVoxState.instance.currentRange, prevRange, evt.type); |
135 } else { | 135 } else { |
136 // Delegate event handling to the text edit handler for braille. | 136 // Delegate event handling to the text edit handler for braille. |
137 this.textEditHandler_.onEvent(evt); | 137 this.textEditHandler_.onEvent(evt); |
138 } | 138 } |
139 output.go(); | 139 output.go(); |
140 }, | 140 }, |
141 | 141 |
142 /** | 142 /** |
143 * @param {!AutomationEvent} evt | 143 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
144 */ | 144 */ |
145 onEventIfInRange: function(evt) { | 145 onEventIfInRange: function(evt) { |
146 if (!this.shouldOutput_(evt)) | 146 if (!this.shouldOutput_(evt)) |
147 return; | 147 return; |
148 | 148 |
149 var prev = ChromeVoxState.instance.currentRange; | 149 var prev = ChromeVoxState.instance.currentRange; |
150 if (prev.contentEquals(cursors.Range.fromNode(evt.target)) || | 150 if (prev.contentEquals(cursors.Range.fromNode(evt.target)) || |
151 evt.target.state.focused) { | 151 evt.target.state.focused) { |
152 // Category flush here since previous focus events via navigation can | 152 // Category flush here since previous focus events via navigation can |
153 // cause double speak. | 153 // cause double speak. |
154 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 154 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
155 | 155 |
156 // Intentionally skip setting range. | 156 // Intentionally skip setting range. |
157 new Output() | 157 new Output() |
158 .withRichSpeechAndBraille(cursors.Range.fromNode(evt.target), | 158 .withRichSpeechAndBraille(cursors.Range.fromNode(evt.target), |
159 prev, | 159 prev, |
160 Output.EventType.NAVIGATE) | 160 Output.EventType.NAVIGATE) |
161 .go(); | 161 .go(); |
162 } | 162 } |
163 }, | 163 }, |
164 | 164 |
165 /** | 165 /** |
166 * @param {!AutomationEvent} evt | 166 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
167 */ | 167 */ |
168 onEventIfSelected: function(evt) { | 168 onEventIfSelected: function(evt) { |
169 if (evt.target.state.selected) | 169 if (evt.target.state.selected) |
170 this.onEventDefault(evt); | 170 this.onEventDefault(evt); |
171 }, | 171 }, |
172 | 172 |
173 /** | 173 /** |
174 * @param {!AutomationEvent} evt | 174 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
175 */ | 175 */ |
176 onEventWithFlushedOutput: function(evt) { | 176 onEventWithFlushedOutput: function(evt) { |
177 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 177 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
178 this.onEventDefault(evt); | 178 this.onEventDefault(evt); |
179 }, | 179 }, |
180 | 180 |
181 /** | 181 /** |
182 * @param {!AutomationEvent} evt | 182 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
183 */ | 183 */ |
184 onAriaAttributeChanged: function(evt) { | 184 onAriaAttributeChanged: function(evt) { |
185 if (evt.target.state.editable) | 185 if (evt.target.state.editable) |
186 return; | 186 return; |
187 this.onEventIfInRange(evt); | 187 this.onEventIfInRange(evt); |
188 }, | 188 }, |
189 | 189 |
190 /** | 190 /** |
191 * @param {!AutomationEvent} evt | 191 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
192 */ | 192 */ |
193 onHover: function(evt) { | 193 onHover: function(evt) { |
194 if (ChromeVoxState.instance.currentRange && | 194 if (ChromeVoxState.instance.currentRange && |
195 evt.target == ChromeVoxState.instance.currentRange.start.node) | 195 evt.target == ChromeVoxState.instance.currentRange.start.node) |
196 return; | 196 return; |
197 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 197 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
198 this.onEventDefault(evt); | 198 this.onEventDefault(evt); |
199 }, | 199 }, |
200 | 200 |
201 /** | 201 /** |
202 * Makes an announcement without changing focus. | 202 * Makes an announcement without changing focus. |
203 * @param {!AutomationEvent} evt | 203 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
204 */ | 204 */ |
205 onActiveDescendantChanged: function(evt) { | 205 onActiveDescendantChanged: function(evt) { |
206 if (!evt.target.activeDescendant || !evt.target.state.focused) | 206 if (!evt.target.activeDescendant || !evt.target.state.focused) |
207 return; | 207 return; |
208 this.onEventDefault(new chrome.automation.AutomationEvent( | 208 this.onEventDefault(new ChromeVoxAutomationEvent( |
209 EventType.focus, evt.target.activeDescendant, evt.eventFrom)); | 209 EventType.focus, evt.target.activeDescendant, evt.eventFrom)); |
210 }, | 210 }, |
211 | 211 |
212 /** | 212 /** |
213 * Makes an announcement without changing focus. | 213 * Makes an announcement without changing focus. |
214 * @param {!AutomationEvent} evt | 214 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
215 */ | 215 */ |
216 onAlert: function(evt) { | 216 onAlert: function(evt) { |
217 var node = evt.target; | 217 var node = evt.target; |
218 if (!node || !this.shouldOutput_(evt)) | 218 if (!node || !this.shouldOutput_(evt)) |
219 return; | 219 return; |
220 | 220 |
221 var range = cursors.Range.fromNode(node); | 221 var range = cursors.Range.fromNode(node); |
222 | 222 |
223 new Output().withSpeechAndBraille(range, null, evt.type).go(); | 223 new Output().withSpeechAndBraille(range, null, evt.type).go(); |
224 }, | 224 }, |
225 | 225 |
226 /** | 226 /** |
227 * Provides all feedback once a checked state changed event fires. | 227 * Provides all feedback once a checked state changed event fires. |
228 * @param {!AutomationEvent} evt | 228 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
229 */ | 229 */ |
230 onCheckedStateChanged: function(evt) { | 230 onCheckedStateChanged: function(evt) { |
231 if (!AutomationPredicate.checkable(evt.target)) | 231 if (!AutomationPredicate.checkable(evt.target)) |
232 return; | 232 return; |
233 | 233 |
234 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 234 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
235 this.onEventIfInRange( | 235 this.onEventIfInRange( |
236 new chrome.automation.AutomationEvent( | 236 new ChromeVoxAutomationEvent( |
237 EventType.checkedStateChanged, evt.target, evt.eventFrom)); | 237 EventType.checkedStateChanged, evt.target, evt.eventFrom)); |
238 }, | 238 }, |
239 | 239 |
240 /** | 240 /** |
241 * Provides all feedback once a focus event fires. | 241 * Provides all feedback once a focus event fires. |
242 * @param {!AutomationEvent} evt | 242 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
243 */ | 243 */ |
244 onFocus: function(evt) { | 244 onFocus: function(evt) { |
245 // Invalidate any previous editable text handler state. | 245 // Invalidate any previous editable text handler state. |
246 this.textEditHandler_ = null; | 246 this.textEditHandler_ = null; |
247 | 247 |
248 var node = evt.target; | 248 var node = evt.target; |
249 | 249 |
250 // Discard focus events on embeddedObject. | 250 // Discard focus events on embeddedObject. |
251 if (node.role == RoleType.embeddedObject) | 251 if (node.role == RoleType.embeddedObject) |
252 return; | 252 return; |
(...skipping 19 matching lines...) Expand all Loading... |
272 } | 272 } |
273 | 273 |
274 // If a previous node was saved for this focus, restore it. | 274 // If a previous node was saved for this focus, restore it. |
275 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); | 275 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); |
276 ChromeVoxState.instance.focusRecoveryMap.delete(root); | 276 ChromeVoxState.instance.focusRecoveryMap.delete(root); |
277 if (savedRange) { | 277 if (savedRange) { |
278 ChromeVoxState.instance.navigateToRange(savedRange, false); | 278 ChromeVoxState.instance.navigateToRange(savedRange, false); |
279 return; | 279 return; |
280 } | 280 } |
281 | 281 |
282 this.onEventDefault(new chrome.automation.AutomationEvent( | 282 this.onEventDefault(new ChromeVoxAutomationEvent( |
283 EventType.focus, node, evt.eventFrom)); | 283 EventType.focus, node, evt.eventFrom)); |
284 }, | 284 }, |
285 | 285 |
286 /** | 286 /** |
287 * Provides all feedback once a load complete event fires. | 287 * Provides all feedback once a load complete event fires. |
288 * @param {!AutomationEvent} evt | 288 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
289 */ | 289 */ |
290 onLoadComplete: function(evt) { | 290 onLoadComplete: function(evt) { |
291 chrome.automation.getFocus(function(focus) { | 291 chrome.automation.getFocus(function(focus) { |
292 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) | 292 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) |
293 return; | 293 return; |
294 | 294 |
295 // Create text edit handler, if needed, now in order not to miss initial | 295 // Create text edit handler, if needed, now in order not to miss initial |
296 // value change if text field has already been focused when initializing | 296 // value change if text field has already been focused when initializing |
297 // ChromeVox. | 297 // ChromeVox. |
298 this.createTextEditHandlerIfNeeded_(focus); | 298 this.createTextEditHandlerIfNeeded_(focus); |
(...skipping 22 matching lines...) Expand all Loading... |
321 return; | 321 return; |
322 | 322 |
323 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 323 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
324 o.withRichSpeechAndBraille( | 324 o.withRichSpeechAndBraille( |
325 ChromeVoxState.instance.currentRange, null, evt.type).go(); | 325 ChromeVoxState.instance.currentRange, null, evt.type).go(); |
326 }.bind(this)); | 326 }.bind(this)); |
327 }, | 327 }, |
328 | 328 |
329 /** | 329 /** |
330 * Provides all feedback once a text changed event fires. | 330 * Provides all feedback once a text changed event fires. |
331 * @param {!AutomationEvent} evt | 331 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
332 */ | 332 */ |
333 onTextChanged: function(evt) { | 333 onTextChanged: function(evt) { |
334 if (evt.target.state.editable) | 334 if (evt.target.state.editable) |
335 this.onEditableChanged_(evt); | 335 this.onEditableChanged_(evt); |
336 }, | 336 }, |
337 | 337 |
338 /** | 338 /** |
339 * Provides all feedback once a text selection changed event fires. | 339 * Provides all feedback once a text selection changed event fires. |
340 * @param {!AutomationEvent} evt | 340 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
341 */ | 341 */ |
342 onTextSelectionChanged: function(evt) { | 342 onTextSelectionChanged: function(evt) { |
343 if (evt.target.state.editable) | 343 if (evt.target.state.editable) |
344 this.onEditableChanged_(evt); | 344 this.onEditableChanged_(evt); |
345 }, | 345 }, |
346 | 346 |
347 /** | 347 /** |
348 * Provides all feedback once a change event in a text field fires. | 348 * Provides all feedback once a change event in a text field fires. |
349 * @param {!AutomationEvent} evt | 349 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
350 * @private | 350 * @private |
351 */ | 351 */ |
352 onEditableChanged_: function(evt) { | 352 onEditableChanged_: function(evt) { |
353 var topRoot = AutomationUtil.getTopLevelRoot(evt.target); | 353 var topRoot = AutomationUtil.getTopLevelRoot(evt.target); |
354 if (!evt.target.state.focused || | 354 if (!evt.target.state.focused || |
355 (topRoot && | 355 (topRoot && |
356 topRoot.parent && | 356 topRoot.parent && |
357 !topRoot.parent.state.focused)) | 357 !topRoot.parent.state.focused)) |
358 return; | 358 return; |
359 | 359 |
(...skipping 20 matching lines...) Expand all Loading... |
380 } | 380 } |
381 | 381 |
382 // TODO(plundblad): This can currently be null for contenteditables. | 382 // TODO(plundblad): This can currently be null for contenteditables. |
383 // Clean up when it can't. | 383 // Clean up when it can't. |
384 if (this.textEditHandler_) | 384 if (this.textEditHandler_) |
385 this.textEditHandler_.onEvent(evt); | 385 this.textEditHandler_.onEvent(evt); |
386 }, | 386 }, |
387 | 387 |
388 /** | 388 /** |
389 * Provides all feedback once a value changed event fires. | 389 * Provides all feedback once a value changed event fires. |
390 * @param {!AutomationEvent} evt | 390 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
391 */ | 391 */ |
392 onValueChanged: function(evt) { | 392 onValueChanged: function(evt) { |
393 // Delegate to the edit text handler if this is an editable. | 393 // Delegate to the edit text handler if this is an editable. |
394 if (evt.target.state.editable) { | 394 if (evt.target.state.editable) { |
395 this.onEditableChanged_(evt); | 395 this.onEditableChanged_(evt); |
396 return; | 396 return; |
397 } | 397 } |
398 | 398 |
399 if (!this.shouldOutput_(evt)) | 399 if (!this.shouldOutput_(evt)) |
400 return; | 400 return; |
(...skipping 13 matching lines...) Expand all Loading... |
414 | 414 |
415 if (t.root.role == RoleType.desktop) | 415 if (t.root.role == RoleType.desktop) |
416 output.withQueueMode(cvox.QueueMode.FLUSH); | 416 output.withQueueMode(cvox.QueueMode.FLUSH); |
417 | 417 |
418 output.format('$value', evt.target).go(); | 418 output.format('$value', evt.target).go(); |
419 } | 419 } |
420 }, | 420 }, |
421 | 421 |
422 /** | 422 /** |
423 * Handle updating the active indicator when the document scrolls. | 423 * Handle updating the active indicator when the document scrolls. |
424 * @param {!AutomationEvent} evt | 424 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
425 */ | 425 */ |
426 onScrollPositionChanged: function(evt) { | 426 onScrollPositionChanged: function(evt) { |
427 var currentRange = ChromeVoxState.instance.currentRange; | 427 var currentRange = ChromeVoxState.instance.currentRange; |
428 if (currentRange && currentRange.isValid() && this.shouldOutput_(evt)) | 428 if (currentRange && currentRange.isValid() && this.shouldOutput_(evt)) |
429 new Output().withLocation(currentRange, null, evt.type).go(); | 429 new Output().withLocation(currentRange, null, evt.type).go(); |
430 }, | 430 }, |
431 | 431 |
432 /** | 432 /** |
433 * @param {!AutomationEvent} evt | 433 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
434 */ | 434 */ |
435 onSelection: function(evt) { | 435 onSelection: function(evt) { |
436 // Invalidate any previous editable text handler state since some nodes, | 436 // Invalidate any previous editable text handler state since some nodes, |
437 // like menuitems, can receive selection while focus remains on an editable | 437 // like menuitems, can receive selection while focus remains on an editable |
438 // leading to braille output routing to the editable. | 438 // leading to braille output routing to the editable. |
439 this.textEditHandler_ = null; | 439 this.textEditHandler_ = null; |
440 | 440 |
441 chrome.automation.getFocus(function(focus) { | 441 chrome.automation.getFocus(function(focus) { |
442 // Desktop tabs get "selection" when there's a focused webview during tab | 442 // Desktop tabs get "selection" when there's a focused webview during tab |
443 // switching. | 443 // switching. |
444 if (focus.role == RoleType.webView && evt.target.role == RoleType.tab) { | 444 if (focus.role == RoleType.webView && evt.target.role == RoleType.tab) { |
445 ChromeVoxState.instance.setCurrentRange( | 445 ChromeVoxState.instance.setCurrentRange( |
446 cursors.Range.fromNode(focus.firstChild)); | 446 cursors.Range.fromNode(focus.firstChild)); |
447 return; | 447 return; |
448 } | 448 } |
449 | 449 |
450 // Some cases (e.g. in overview mode), require overriding the assumption | 450 // Some cases (e.g. in overview mode), require overriding the assumption |
451 // that focus is an ancestor of a selection target. | 451 // that focus is an ancestor of a selection target. |
452 var override = evt.target.role == RoleType.menuItem || | 452 var override = evt.target.role == RoleType.menuItem || |
453 (evt.target.root == focus.root && | 453 (evt.target.root == focus.root && |
454 focus.root.role == RoleType.desktop); | 454 focus.root.role == RoleType.desktop); |
455 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 455 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
456 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) | 456 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) |
457 this.onEventDefault(evt); | 457 this.onEventDefault(evt); |
458 }.bind(this)); | 458 }.bind(this)); |
459 }, | 459 }, |
460 | 460 |
461 /** | 461 /** |
462 * Provides all feedback once a menu start event fires. | 462 * Provides all feedback once a menu start event fires. |
463 * @param {!AutomationEvent} evt | 463 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
464 */ | 464 */ |
465 onMenuStart: function(evt) { | 465 onMenuStart: function(evt) { |
466 ChromeVoxState.instance.markCurrentRange(); | 466 ChromeVoxState.instance.markCurrentRange(); |
467 this.onEventDefault(evt); | 467 this.onEventDefault(evt); |
468 }, | 468 }, |
469 | 469 |
470 /** | 470 /** |
471 * Provides all feedback once a menu end event fires. | 471 * Provides all feedback once a menu end event fires. |
472 * @param {!AutomationEvent} evt | 472 * @param {!AutomationEvent|!ChromeVoxAutomationEvent} evt |
473 */ | 473 */ |
474 onMenuEnd: function(evt) { | 474 onMenuEnd: function(evt) { |
475 this.onEventDefault(evt); | 475 this.onEventDefault(evt); |
476 | 476 |
477 // This is a work around for Chrome context menus not firing a focus event | 477 // This is a work around for Chrome context menus not firing a focus event |
478 // after you close them. | 478 // after you close them. |
479 chrome.automation.getFocus(function(focus) { | 479 chrome.automation.getFocus(function(focus) { |
480 if (focus) { | 480 if (focus) { |
481 this.onFocus( | 481 this.onFocus( |
482 new chrome.automation.AutomationEvent( | 482 new ChromeVoxAutomationEvent( |
483 EventType.focus, focus, 'page')); | 483 EventType.focus, focus, 'page')); |
484 } | 484 } |
485 }.bind(this)); | 485 }.bind(this)); |
486 }, | 486 }, |
487 | 487 |
488 /** | 488 /** |
489 * Create an editable text handler for the given node if needed. | 489 * Create an editable text handler for the given node if needed. |
490 * @param {!AutomationNode} node | 490 * @param {!AutomationNode} node |
491 */ | 491 */ |
492 createTextEditHandlerIfNeeded_: function(node) { | 492 createTextEditHandlerIfNeeded_: function(node) { |
(...skipping 25 matching lines...) Expand all Loading... |
518 DesktopAutomationHandler.init_ = function() { | 518 DesktopAutomationHandler.init_ = function() { |
519 chrome.automation.getDesktop(function(desktop) { | 519 chrome.automation.getDesktop(function(desktop) { |
520 ChromeVoxState.desktopAutomationHandler = | 520 ChromeVoxState.desktopAutomationHandler = |
521 new DesktopAutomationHandler(desktop); | 521 new DesktopAutomationHandler(desktop); |
522 }); | 522 }); |
523 }; | 523 }; |
524 | 524 |
525 DesktopAutomationHandler.init_(); | 525 DesktopAutomationHandler.init_(); |
526 | 526 |
527 }); // goog.scope | 527 }); // goog.scope |
OLD | NEW |