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('BaseAutomationHandler'); | 12 goog.require('BaseAutomationHandler'); |
12 goog.require('ChromeVoxState'); | 13 goog.require('ChromeVoxState'); |
13 goog.require('CustomAutomationEvent'); | |
14 goog.require('Stubs'); | 14 goog.require('Stubs'); |
15 goog.require('editing.TextEditHandler'); | 15 goog.require('editing.TextEditHandler'); |
16 | 16 |
17 goog.scope(function() { | 17 goog.scope(function() { |
18 var AutomationEvent = chrome.automation.AutomationEvent; | 18 var AutomationEvent = chrome.automation.AutomationEvent; |
19 var AutomationNode = chrome.automation.AutomationNode; | 19 var AutomationNode = chrome.automation.AutomationNode; |
20 var Dir = constants.Dir; | 20 var Dir = constants.Dir; |
21 var EventType = chrome.automation.EventType; | 21 var EventType = chrome.automation.EventType; |
22 var RoleType = chrome.automation.RoleType; | 22 var RoleType = chrome.automation.RoleType; |
23 | 23 |
(...skipping 12 matching lines...) Expand all Loading... |
36 */ | 36 */ |
37 this.textEditHandler_ = null; | 37 this.textEditHandler_ = null; |
38 | 38 |
39 /** | 39 /** |
40 * The last time we handled a value changed event. | 40 * The last time we handled a value changed event. |
41 * @type {!Date} | 41 * @type {!Date} |
42 * @private | 42 * @private |
43 */ | 43 */ |
44 this.lastValueChanged_ = new Date(0); | 44 this.lastValueChanged_ = new Date(0); |
45 | 45 |
46 this.addListener_(EventType.ACTIVEDESCENDANTCHANGED, | 46 var e = EventType; |
47 this.onActiveDescendantChanged); | 47 this.addListener_(e.activedescendantchanged, this.onActiveDescendantChanged); |
48 this.addListener_(EventType.ALERT, | 48 this.addListener_(e.alert, this.onAlert); |
49 this.onAlert); | 49 this.addListener_(e.ariaAttributeChanged, this.onAriaAttributeChanged); |
50 this.addListener_(EventType.ARIA_ATTRIBUTE_CHANGED, | 50 this.addListener_(e.autocorrectionOccured, this.onEventIfInRange); |
51 this.onAriaAttributeChanged); | 51 this.addListener_(e.checkedStateChanged, this.onCheckedStateChanged); |
52 this.addListener_(EventType.AUTOCORRECTION_OCCURED, | 52 this.addListener_(e.childrenChanged, this.onActiveDescendantChanged); |
53 this.onEventIfInRange); | 53 this.addListener_(e.expandedChanged, this.onEventIfInRange); |
54 this.addListener_(EventType.CHECKED_STATE_CHANGED, | 54 this.addListener_(e.focus, this.onFocus); |
55 this.onCheckedStateChanged); | 55 this.addListener_(e.hover, this.onHover); |
56 this.addListener_(EventType.CHILDREN_CHANGED, | 56 this.addListener_(e.invalidStatusChanged, this.onEventIfInRange); |
57 this.onActiveDescendantChanged); | 57 this.addListener_(e.loadComplete, this.onLoadComplete); |
58 this.addListener_(EventType.EXPANDED_CHANGED, | 58 this.addListener_(e.menuEnd, this.onMenuEnd); |
59 this.onEventIfInRange); | 59 this.addListener_(e.menuListItemSelected, this.onEventIfSelected); |
60 this.addListener_(EventType.FOCUS, | 60 this.addListener_(e.menuStart, this.onMenuStart); |
61 this.onFocus); | 61 this.addListener_(e.rowCollapsed, this.onEventIfInRange); |
62 this.addListener_(EventType.HOVER, | 62 this.addListener_(e.rowExpanded, this.onEventIfInRange); |
63 this.onHover); | 63 this.addListener_(e.scrollPositionChanged, this.onScrollPositionChanged); |
64 this.addListener_(EventType.INVALID_STATUS_CHANGED, | 64 this.addListener_(e.selection, this.onSelection); |
65 this.onEventIfInRange); | 65 this.addListener_(e.textChanged, this.onTextChanged); |
66 this.addListener_(EventType.LOAD_COMPLETE, | 66 this.addListener_(e.textSelectionChanged, this.onTextSelectionChanged); |
67 this.onLoadComplete); | 67 this.addListener_(e.valueChanged, this.onValueChanged); |
68 this.addListener_(EventType.MENU_END, | |
69 this.onMenuEnd); | |
70 this.addListener_(EventType.MENU_LIST_ITEM_SELECTED, | |
71 this.onEventIfSelected); | |
72 this.addListener_(EventType.MENU_START, | |
73 this.onMenuStart); | |
74 this.addListener_(EventType.ROW_COLLAPSED, | |
75 this.onEventIfInRange); | |
76 this.addListener_(EventType.ROW_EXPANDED, | |
77 this.onEventIfInRange); | |
78 this.addListener_(EventType.SCROLL_POSITION_CHANGED, | |
79 this.onScrollPositionChanged); | |
80 this.addListener_(EventType.SELECTION, | |
81 this.onSelection); | |
82 this.addListener_(EventType.TEXT_CHANGED, | |
83 this.onTextChanged); | |
84 this.addListener_(EventType.TEXT_SELECTION_CHANGED, | |
85 this.onTextSelectionChanged); | |
86 this.addListener_(EventType.VALUE_CHANGED, | |
87 this.onValueChanged); | |
88 | 68 |
89 chrome.automation.getFocus((function(focus) { | 69 AutomationObjectConstructorInstaller.init(node, function() { |
90 if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) | 70 chrome.automation.getFocus((function(focus) { |
91 return; | 71 if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) |
| 72 return; |
92 | 73 |
93 if (focus) { | 74 if (focus) { |
94 var event = new CustomAutomationEvent(EventType.FOCUS, focus, 'page'); | 75 this.onFocus( |
95 this.onFocus(event); | 76 new chrome.automation.AutomationEvent( |
96 } | 77 EventType.focus, focus, 'page')); |
97 }).bind(this)); | 78 } |
| 79 }).bind(this)); |
| 80 }.bind(this)); |
98 }; | 81 }; |
99 | 82 |
100 /** | 83 /** |
101 * Time to wait until processing more value changed events. | 84 * Time to wait until processing more value changed events. |
102 * @const {number} | 85 * @const {number} |
103 */ | 86 */ |
104 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 500; | 87 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 500; |
105 | 88 |
106 /** | 89 /** |
107 * Controls announcement of non-user-initiated events. | 90 * Controls announcement of non-user-initiated events. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 this.onEventDefault(evt); | 198 this.onEventDefault(evt); |
216 }, | 199 }, |
217 | 200 |
218 /** | 201 /** |
219 * Makes an announcement without changing focus. | 202 * Makes an announcement without changing focus. |
220 * @param {!AutomationEvent} evt | 203 * @param {!AutomationEvent} evt |
221 */ | 204 */ |
222 onActiveDescendantChanged: function(evt) { | 205 onActiveDescendantChanged: function(evt) { |
223 if (!evt.target.activeDescendant || !evt.target.state.focused) | 206 if (!evt.target.activeDescendant || !evt.target.state.focused) |
224 return; | 207 return; |
225 var event = new CustomAutomationEvent( | 208 this.onEventDefault(new chrome.automation.AutomationEvent( |
226 EventType.FOCUS, evt.target.activeDescendant, evt.eventFrom); | 209 EventType.focus, evt.target.activeDescendant, evt.eventFrom)); |
227 this.onEventDefault(event); | |
228 }, | 210 }, |
229 | 211 |
230 /** | 212 /** |
231 * Makes an announcement without changing focus. | 213 * Makes an announcement without changing focus. |
232 * @param {!AutomationEvent} evt | 214 * @param {!AutomationEvent} evt |
233 */ | 215 */ |
234 onAlert: function(evt) { | 216 onAlert: function(evt) { |
235 var node = evt.target; | 217 var node = evt.target; |
236 if (!node || !this.shouldOutput_(evt)) | 218 if (!node || !this.shouldOutput_(evt)) |
237 return; | 219 return; |
238 | 220 |
239 var range = cursors.Range.fromNode(node); | 221 var range = cursors.Range.fromNode(node); |
240 | 222 |
241 new Output().withSpeechAndBraille(range, null, evt.type).go(); | 223 new Output().withSpeechAndBraille(range, null, evt.type).go(); |
242 }, | 224 }, |
243 | 225 |
244 /** | 226 /** |
245 * Provides all feedback once a checked state changed event fires. | 227 * Provides all feedback once a checked state changed event fires. |
246 * @param {!AutomationEvent} evt | 228 * @param {!AutomationEvent} evt |
247 */ | 229 */ |
248 onCheckedStateChanged: function(evt) { | 230 onCheckedStateChanged: function(evt) { |
249 if (!AutomationPredicate.checkable(evt.target)) | 231 if (!AutomationPredicate.checkable(evt.target)) |
250 return; | 232 return; |
251 | 233 |
252 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 234 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
253 var event = new CustomAutomationEvent( | 235 this.onEventIfInRange( |
254 EventType.CHECKED_STATE_CHANGED, evt.target, evt.eventFrom); | 236 new chrome.automation.AutomationEvent( |
255 this.onEventIfInRange(event); | 237 EventType.checkedStateChanged, evt.target, evt.eventFrom)); |
256 }, | 238 }, |
257 | 239 |
258 /** | 240 /** |
259 * Provides all feedback once a focus event fires. | 241 * Provides all feedback once a focus event fires. |
260 * @param {!AutomationEvent} evt | 242 * @param {!AutomationEvent} evt |
261 */ | 243 */ |
262 onFocus: function(evt) { | 244 onFocus: function(evt) { |
263 // Invalidate any previous editable text handler state. | 245 // Invalidate any previous editable text handler state. |
264 this.textEditHandler_ = null; | 246 this.textEditHandler_ = null; |
265 | 247 |
266 var node = evt.target; | 248 var node = evt.target; |
267 | 249 |
268 // Discard focus events on embeddedObject. | 250 // Discard focus events on embeddedObject. |
269 if (node.role == RoleType.EMBEDDED_OBJECT) | 251 if (node.role == RoleType.embeddedObject) |
270 return; | 252 return; |
271 | 253 |
272 this.createTextEditHandlerIfNeeded_(evt.target); | 254 this.createTextEditHandlerIfNeeded_(evt.target); |
273 | 255 |
274 // Category flush speech triggered by events with no source. This includes | 256 // Category flush speech triggered by events with no source. This includes |
275 // views. | 257 // views. |
276 if (evt.eventFrom == '') | 258 if (evt.eventFrom == '') |
277 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 259 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
278 if (!node.root) | 260 if (!node.root) |
279 return; | 261 return; |
280 | 262 |
281 var root = AutomationUtil.getTopLevelRoot(node.root); | 263 var root = AutomationUtil.getTopLevelRoot(node.root); |
| 264 |
282 // If we're crossing out of a root, save it in case it needs recovering. | 265 // If we're crossing out of a root, save it in case it needs recovering. |
283 var prevRange = ChromeVoxState.instance.currentRange; | 266 var prevRange = ChromeVoxState.instance.currentRange; |
284 var prevNode = prevRange ? prevRange.start.node : null; | 267 var prevNode = prevRange ? prevRange.start.node : null; |
285 if (prevNode) { | 268 if (prevNode) { |
286 var prevRoot = AutomationUtil.getTopLevelRoot(prevNode); | 269 var prevRoot = AutomationUtil.getTopLevelRoot(prevNode); |
287 if (prevRoot && prevRoot !== root) | 270 if (prevRoot && prevRoot !== root) |
288 ChromeVoxState.instance.focusRecoveryMap.set(prevRoot, prevRange); | 271 ChromeVoxState.instance.focusRecoveryMap.set(prevRoot, prevRange); |
289 } | 272 } |
| 273 |
290 // If a previous node was saved for this focus, restore it. | 274 // If a previous node was saved for this focus, restore it. |
291 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); | 275 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); |
292 ChromeVoxState.instance.focusRecoveryMap.delete(root); | 276 ChromeVoxState.instance.focusRecoveryMap.delete(root); |
293 if (savedRange) { | 277 if (savedRange) { |
294 ChromeVoxState.instance.navigateToRange(savedRange, false); | 278 ChromeVoxState.instance.navigateToRange(savedRange, false); |
295 return; | 279 return; |
296 } | 280 } |
297 var event = new CustomAutomationEvent(EventType.FOCUS, node, evt.eventFrom); | 281 |
298 this.onEventDefault(event); | 282 this.onEventDefault(new chrome.automation.AutomationEvent( |
| 283 EventType.focus, node, evt.eventFrom)); |
299 }, | 284 }, |
300 | 285 |
301 /** | 286 /** |
302 * Provides all feedback once a load complete event fires. | 287 * Provides all feedback once a load complete event fires. |
303 * @param {!AutomationEvent} evt | 288 * @param {!AutomationEvent} evt |
304 */ | 289 */ |
305 onLoadComplete: function(evt) { | 290 onLoadComplete: function(evt) { |
306 chrome.automation.getFocus(function(focus) { | 291 chrome.automation.getFocus(function(focus) { |
307 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) | 292 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) |
308 return; | 293 return; |
(...skipping 13 matching lines...) Expand all Loading... |
322 } | 307 } |
323 | 308 |
324 // If initial focus was already placed on this page (e.g. if a user starts | 309 // If initial focus was already placed on this page (e.g. if a user starts |
325 // tabbing before load complete), then don't move ChromeVox's position on | 310 // tabbing before load complete), then don't move ChromeVox's position on |
326 // the page. | 311 // the page. |
327 if (ChromeVoxState.instance.currentRange && | 312 if (ChromeVoxState.instance.currentRange && |
328 ChromeVoxState.instance.currentRange.start.node.root == focus.root) | 313 ChromeVoxState.instance.currentRange.start.node.root == focus.root) |
329 return; | 314 return; |
330 | 315 |
331 var o = new Output(); | 316 var o = new Output(); |
332 if (focus.role == RoleType.ROOT_WEB_AREA) { | 317 if (focus.role == RoleType.rootWebArea) { |
333 // Restore to previous position. | 318 // Restore to previous position. |
334 var url = focus.docUrl; | 319 var url = focus.docUrl; |
335 url = url.substring(0, url.indexOf('#')) || url; | 320 url = url.substring(0, url.indexOf('#')) || url; |
336 var pos = cvox.ChromeVox.position[url]; | 321 var pos = cvox.ChromeVox.position[url]; |
337 if (pos) { | 322 if (pos) { |
338 focus = AutomationUtil.hitTest(focus.root, pos) || focus; | 323 focus = AutomationUtil.hitTest(focus.root, pos) || focus; |
339 if (focus != focus.root) | 324 if (focus != focus.root) |
340 o.format('$name', focus.root); | 325 o.format('$name', focus.root); |
341 } | 326 } |
342 } | 327 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 if (!ChromeVoxState.instance.currentRange) { | 369 if (!ChromeVoxState.instance.currentRange) { |
385 this.onEventDefault(evt); | 370 this.onEventDefault(evt); |
386 ChromeVoxState.instance.setCurrentRange( | 371 ChromeVoxState.instance.setCurrentRange( |
387 cursors.Range.fromNode(evt.target)); | 372 cursors.Range.fromNode(evt.target)); |
388 } | 373 } |
389 | 374 |
390 this.createTextEditHandlerIfNeeded_(evt.target); | 375 this.createTextEditHandlerIfNeeded_(evt.target); |
391 | 376 |
392 // Sync the ChromeVox range to the editable, if a selection exists. | 377 // Sync the ChromeVox range to the editable, if a selection exists. |
393 var anchorObject = evt.target.root.anchorObject; | 378 var anchorObject = evt.target.root.anchorObject; |
394 var anchorOffset = evt.target.root.anchorOffset || 0; | 379 var anchorOffset = evt.target.root.anchorOffset; |
395 var focusObject = evt.target.root.focusObject; | 380 var focusObject = evt.target.root.focusObject; |
396 var focusOffset = evt.target.root.focusOffset || 0; | 381 var focusOffset = evt.target.root.focusOffset; |
397 if (anchorObject && focusObject) { | 382 if (anchorObject && focusObject) { |
398 var selectedRange = new cursors.Range( | 383 var selectedRange = new cursors.Range( |
399 new cursors.WrappingCursor(anchorObject, anchorOffset), | 384 new cursors.WrappingCursor(anchorObject, anchorOffset), |
400 new cursors.WrappingCursor(focusObject, focusOffset)); | 385 new cursors.WrappingCursor(focusObject, focusOffset)); |
401 | 386 |
402 // Sync ChromeVox range with selection. | 387 // Sync ChromeVox range with selection. |
403 ChromeVoxState.instance.setCurrentRange(selectedRange); | 388 ChromeVoxState.instance.setCurrentRange(selectedRange); |
404 } | 389 } |
405 | 390 |
406 // TODO(plundblad): This can currently be null for contenteditables. | 391 // TODO(plundblad): This can currently be null for contenteditables. |
(...skipping 11 matching lines...) Expand all Loading... |
418 if (evt.target.state.editable) { | 403 if (evt.target.state.editable) { |
419 this.onEditableChanged_(evt); | 404 this.onEditableChanged_(evt); |
420 return; | 405 return; |
421 } | 406 } |
422 | 407 |
423 if (!this.shouldOutput_(evt)) | 408 if (!this.shouldOutput_(evt)) |
424 return; | 409 return; |
425 | 410 |
426 var t = evt.target; | 411 var t = evt.target; |
427 if (t.state.focused || | 412 if (t.state.focused || |
428 t.root.role == RoleType.DESKTOP || | 413 t.root.role == RoleType.desktop || |
429 AutomationUtil.isDescendantOf( | 414 AutomationUtil.isDescendantOf( |
430 ChromeVoxState.instance.currentRange.start.node, t)) { | 415 ChromeVoxState.instance.currentRange.start.node, t)) { |
431 if (new Date() - this.lastValueChanged_ <= | 416 if (new Date() - this.lastValueChanged_ <= |
432 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS) | 417 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS) |
433 return; | 418 return; |
434 | 419 |
435 this.lastValueChanged_ = new Date(); | 420 this.lastValueChanged_ = new Date(); |
436 | 421 |
437 var output = new Output(); | 422 var output = new Output(); |
438 | 423 |
439 if (t.root.role == RoleType.DESKTOP) | 424 if (t.root.role == RoleType.desktop) |
440 output.withQueueMode(cvox.QueueMode.FLUSH); | 425 output.withQueueMode(cvox.QueueMode.FLUSH); |
441 | 426 |
442 output.format('$value', evt.target).go(); | 427 output.format('$value', evt.target).go(); |
443 } | 428 } |
444 }, | 429 }, |
445 | 430 |
446 /** | 431 /** |
447 * Handle updating the active indicator when the document scrolls. | 432 * Handle updating the active indicator when the document scrolls. |
448 * @param {!AutomationEvent} evt | 433 * @param {!AutomationEvent} evt |
449 */ | 434 */ |
450 onScrollPositionChanged: function(evt) { | 435 onScrollPositionChanged: function(evt) { |
451 var currentRange = ChromeVoxState.instance.currentRange; | 436 var currentRange = ChromeVoxState.instance.currentRange; |
452 if (currentRange && currentRange.isValid() && this.shouldOutput_(evt)) | 437 if (currentRange && currentRange.isValid() && this.shouldOutput_(evt)) |
453 new Output().withLocation(currentRange, null, evt.type).go(); | 438 new Output().withLocation(currentRange, null, evt.type).go(); |
454 }, | 439 }, |
455 | 440 |
456 /** | 441 /** |
457 * @param {!AutomationEvent} evt | 442 * @param {!AutomationEvent} evt |
458 */ | 443 */ |
459 onSelection: function(evt) { | 444 onSelection: function(evt) { |
460 // Invalidate any previous editable text handler state since some nodes, | 445 // Invalidate any previous editable text handler state since some nodes, |
461 // like menuitems, can receive selection while focus remains on an editable | 446 // like menuitems, can receive selection while focus remains on an editable |
462 // leading to braille output routing to the editable. | 447 // leading to braille output routing to the editable. |
463 this.textEditHandler_ = null; | 448 this.textEditHandler_ = null; |
464 | 449 |
465 chrome.automation.getFocus(function(focus) { | 450 chrome.automation.getFocus(function(focus) { |
466 // Desktop tabs get "selection" when there's a focused webview during tab | 451 // Desktop tabs get "selection" when there's a focused webview during tab |
467 // switching. | 452 // switching. |
468 if (focus.role == RoleType.WEB_VIEW && evt.target.role == RoleType.TAB) { | 453 if (focus.role == RoleType.webView && evt.target.role == RoleType.tab) { |
469 ChromeVoxState.instance.setCurrentRange( | 454 ChromeVoxState.instance.setCurrentRange( |
470 cursors.Range.fromNode(focus.firstChild)); | 455 cursors.Range.fromNode(focus.firstChild)); |
471 return; | 456 return; |
472 } | 457 } |
473 | 458 |
474 // Some cases (e.g. in overview mode), require overriding the assumption | 459 // Some cases (e.g. in overview mode), require overriding the assumption |
475 // that focus is an ancestor of a selection target. | 460 // that focus is an ancestor of a selection target. |
476 var override = evt.target.role == RoleType.MENU_ITEM || | 461 var override = evt.target.role == RoleType.menuItem || |
477 (evt.target.root == focus.root && | 462 (evt.target.root == focus.root && |
478 focus.root.role == RoleType.DESKTOP); | 463 focus.root.role == RoleType.desktop); |
479 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 464 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
480 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) | 465 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) |
481 this.onEventDefault(evt); | 466 this.onEventDefault(evt); |
482 }.bind(this)); | 467 }.bind(this)); |
483 }, | 468 }, |
484 | 469 |
485 /** | 470 /** |
486 * Provides all feedback once a menu start event fires. | 471 * Provides all feedback once a menu start event fires. |
487 * @param {!AutomationEvent} evt | 472 * @param {!AutomationEvent} evt |
488 */ | 473 */ |
489 onMenuStart: function(evt) { | 474 onMenuStart: function(evt) { |
490 ChromeVoxState.instance.markCurrentRange(); | 475 ChromeVoxState.instance.markCurrentRange(); |
491 this.onEventDefault(evt); | 476 this.onEventDefault(evt); |
492 }, | 477 }, |
493 | 478 |
494 /** | 479 /** |
495 * Provides all feedback once a menu end event fires. | 480 * Provides all feedback once a menu end event fires. |
496 * @param {!AutomationEvent} evt | 481 * @param {!AutomationEvent} evt |
497 */ | 482 */ |
498 onMenuEnd: function(evt) { | 483 onMenuEnd: function(evt) { |
499 this.onEventDefault(evt); | 484 this.onEventDefault(evt); |
500 | 485 |
501 // This is a work around for Chrome context menus not firing a focus event | 486 // This is a work around for Chrome context menus not firing a focus event |
502 // after you close them. | 487 // after you close them. |
503 chrome.automation.getFocus(function(focus) { | 488 chrome.automation.getFocus(function(focus) { |
504 if (focus) { | 489 if (focus) { |
505 var event = new CustomAutomationEvent(EventType.FOCUS, focus, 'page'); | 490 this.onFocus( |
506 this.onFocus(event); | 491 new chrome.automation.AutomationEvent( |
| 492 EventType.focus, focus, 'page')); |
507 } | 493 } |
508 }.bind(this)); | 494 }.bind(this)); |
509 }, | 495 }, |
510 | 496 |
511 /** | 497 /** |
512 * Create an editable text handler for the given node if needed. | 498 * Create an editable text handler for the given node if needed. |
513 * @param {!AutomationNode} node | 499 * @param {!AutomationNode} node |
514 */ | 500 */ |
515 createTextEditHandlerIfNeeded_: function(node) { | 501 createTextEditHandlerIfNeeded_: function(node) { |
516 if (!this.textEditHandler_ || | 502 if (!this.textEditHandler_ || |
517 this.textEditHandler_.node !== node) { | 503 this.textEditHandler_.node !== node) { |
518 this.textEditHandler_ = editing.TextEditHandler.createForNode(node); | 504 this.textEditHandler_ = editing.TextEditHandler.createForNode(node); |
519 } | 505 } |
520 }, | 506 }, |
521 | 507 |
522 /** | 508 /** |
523 * Once an event handler updates ChromeVox's range based on |evt| | 509 * Once an event handler updates ChromeVox's range based on |evt| |
524 * which updates mode, returns whether |evt| should be outputted. | 510 * which updates mode, returns whether |evt| should be outputted. |
525 * @return {boolean} | 511 * @return {boolean} |
526 */ | 512 */ |
527 shouldOutput_: function(evt) { | 513 shouldOutput_: function(evt) { |
528 var mode = ChromeVoxState.instance.mode; | 514 var mode = ChromeVoxState.instance.mode; |
529 // Only output desktop rooted nodes or web nodes for next engine modes. | 515 // Only output desktop rooted nodes or web nodes for next engine modes. |
530 return evt.target.root.role == RoleType.DESKTOP || | 516 return evt.target.root.role == RoleType.desktop || |
531 (mode == ChromeVoxMode.NEXT || | 517 (mode == ChromeVoxMode.NEXT || |
532 mode == ChromeVoxMode.FORCE_NEXT || | 518 mode == ChromeVoxMode.FORCE_NEXT || |
533 mode == ChromeVoxMode.CLASSIC_COMPAT); | 519 mode == ChromeVoxMode.CLASSIC_COMPAT); |
534 } | 520 } |
535 }; | 521 }; |
536 | 522 |
537 /** | 523 /** |
538 * Initializes global state for DesktopAutomationHandler. | 524 * Initializes global state for DesktopAutomationHandler. |
539 * @private | 525 * @private |
540 */ | 526 */ |
541 DesktopAutomationHandler.init_ = function() { | 527 DesktopAutomationHandler.init_ = function() { |
542 chrome.automation.getDesktop(function(desktop) { | 528 chrome.automation.getDesktop(function(desktop) { |
543 ChromeVoxState.desktopAutomationHandler = | 529 ChromeVoxState.desktopAutomationHandler = |
544 new DesktopAutomationHandler(desktop); | 530 new DesktopAutomationHandler(desktop); |
545 }); | 531 }); |
546 }; | 532 }; |
547 | 533 |
548 DesktopAutomationHandler.init_(); | 534 DesktopAutomationHandler.init_(); |
549 | 535 |
550 }); // goog.scope | 536 }); // goog.scope |
OLD | NEW |