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 |
(...skipping 25 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 this.addListener_( |
47 this.onActiveDescendantChanged); | 47 EventType.ACTIVEDESCENDANTCHANGED, this.onActiveDescendantChanged); |
48 this.addListener_(EventType.ALERT, | 48 this.addListener_(EventType.ALERT, this.onAlert); |
49 this.onAlert); | 49 this.addListener_( |
50 this.addListener_(EventType.ARIA_ATTRIBUTE_CHANGED, | 50 EventType.ARIA_ATTRIBUTE_CHANGED, this.onAriaAttributeChanged); |
51 this.onAriaAttributeChanged); | 51 this.addListener_(EventType.AUTOCORRECTION_OCCURED, this.onEventIfInRange); |
52 this.addListener_(EventType.AUTOCORRECTION_OCCURED, | 52 this.addListener_(EventType.BLUR, this.onBlur); |
53 this.onEventIfInRange); | 53 this.addListener_( |
54 this.addListener_(EventType.BLUR, | 54 EventType.CHECKED_STATE_CHANGED, this.onCheckedStateChanged); |
55 this.onBlur); | 55 this.addListener_(EventType.CHILDREN_CHANGED, this.onChildrenChanged); |
56 this.addListener_(EventType.CHECKED_STATE_CHANGED, | 56 this.addListener_(EventType.EXPANDED_CHANGED, this.onEventIfInRange); |
57 this.onCheckedStateChanged); | 57 this.addListener_(EventType.FOCUS, this.onFocus); |
58 this.addListener_(EventType.CHILDREN_CHANGED, | 58 this.addListener_(EventType.HOVER, this.onHover); |
59 this.onChildrenChanged); | 59 this.addListener_(EventType.INVALID_STATUS_CHANGED, this.onEventIfInRange); |
60 this.addListener_(EventType.EXPANDED_CHANGED, | 60 this.addListener_(EventType.LOAD_COMPLETE, this.onLoadComplete); |
61 this.onEventIfInRange); | 61 this.addListener_(EventType.MENU_END, this.onMenuEnd); |
62 this.addListener_(EventType.FOCUS, | 62 this.addListener_(EventType.MENU_LIST_ITEM_SELECTED, this.onEventIfSelected); |
63 this.onFocus); | 63 this.addListener_(EventType.MENU_START, this.onMenuStart); |
64 this.addListener_(EventType.HOVER, | 64 this.addListener_(EventType.ROW_COLLAPSED, this.onEventIfInRange); |
65 this.onHover); | 65 this.addListener_(EventType.ROW_EXPANDED, this.onEventIfInRange); |
66 this.addListener_(EventType.INVALID_STATUS_CHANGED, | 66 this.addListener_( |
67 this.onEventIfInRange); | 67 EventType.SCROLL_POSITION_CHANGED, this.onScrollPositionChanged); |
68 this.addListener_(EventType.LOAD_COMPLETE, | 68 this.addListener_(EventType.SELECTION, this.onSelection); |
69 this.onLoadComplete); | 69 this.addListener_(EventType.TEXT_CHANGED, this.onTextChanged); |
70 this.addListener_(EventType.MENU_END, | 70 this.addListener_( |
71 this.onMenuEnd); | 71 EventType.TEXT_SELECTION_CHANGED, this.onTextSelectionChanged); |
72 this.addListener_(EventType.MENU_LIST_ITEM_SELECTED, | 72 this.addListener_(EventType.VALUE_CHANGED, this.onValueChanged); |
73 this.onEventIfSelected); | |
74 this.addListener_(EventType.MENU_START, | |
75 this.onMenuStart); | |
76 this.addListener_(EventType.ROW_COLLAPSED, | |
77 this.onEventIfInRange); | |
78 this.addListener_(EventType.ROW_EXPANDED, | |
79 this.onEventIfInRange); | |
80 this.addListener_(EventType.SCROLL_POSITION_CHANGED, | |
81 this.onScrollPositionChanged); | |
82 this.addListener_(EventType.SELECTION, | |
83 this.onSelection); | |
84 this.addListener_(EventType.TEXT_CHANGED, | |
85 this.onTextChanged); | |
86 this.addListener_(EventType.TEXT_SELECTION_CHANGED, | |
87 this.onTextSelectionChanged); | |
88 this.addListener_(EventType.VALUE_CHANGED, | |
89 this.onValueChanged); | |
90 | 73 |
91 AutomationObjectConstructorInstaller.init(node, function() { | 74 AutomationObjectConstructorInstaller.init(node, function() { |
92 chrome.automation.getFocus((function(focus) { | 75 chrome.automation.getFocus( |
93 if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) | 76 (function(focus) { |
94 return; | 77 if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) |
| 78 return; |
95 | 79 |
96 if (focus) { | 80 if (focus) { |
97 var event = new CustomAutomationEvent(EventType.FOCUS, focus, 'page'); | 81 var event = |
98 this.onFocus(event); | 82 new CustomAutomationEvent(EventType.FOCUS, focus, 'page'); |
99 } | 83 this.onFocus(event); |
100 }).bind(this)); | 84 } |
| 85 }).bind(this)); |
101 }.bind(this)); | 86 }.bind(this)); |
102 }; | 87 }; |
103 | 88 |
104 /** | 89 /** |
105 * Time to wait until processing more value changed events. | 90 * Time to wait until processing more value changed events. |
106 * @const {number} | 91 * @const {number} |
107 */ | 92 */ |
108 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 500; | 93 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 500; |
109 | 94 |
110 /** | 95 /** |
(...skipping 24 matching lines...) Expand all Loading... |
135 return; | 120 return; |
136 | 121 |
137 var prevRange = ChromeVoxState.instance.currentRange; | 122 var prevRange = ChromeVoxState.instance.currentRange; |
138 | 123 |
139 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(node)); | 124 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(node)); |
140 | 125 |
141 if (!this.shouldOutput_(evt)) | 126 if (!this.shouldOutput_(evt)) |
142 return; | 127 return; |
143 | 128 |
144 // Don't output if focused node hasn't changed. | 129 // Don't output if focused node hasn't changed. |
145 if (prevRange && | 130 if (prevRange && evt.type == 'focus' && |
146 evt.type == 'focus' && | |
147 ChromeVoxState.instance.currentRange.equals(prevRange)) | 131 ChromeVoxState.instance.currentRange.equals(prevRange)) |
148 return; | 132 return; |
149 | 133 |
150 var output = new Output(); | 134 var output = new Output(); |
151 output.withRichSpeech( | 135 output.withRichSpeech( |
152 ChromeVoxState.instance.currentRange, prevRange, evt.type); | 136 ChromeVoxState.instance.currentRange, prevRange, evt.type); |
153 if (!this.textEditHandler_) { | 137 if (!this.textEditHandler_) { |
154 output.withBraille( | 138 output.withBraille( |
155 ChromeVoxState.instance.currentRange, prevRange, evt.type); | 139 ChromeVoxState.instance.currentRange, prevRange, evt.type); |
156 } else { | 140 } else { |
(...skipping 12 matching lines...) Expand all Loading... |
169 | 153 |
170 var prev = ChromeVoxState.instance.currentRange; | 154 var prev = ChromeVoxState.instance.currentRange; |
171 if (prev.contentEquals(cursors.Range.fromNode(evt.target)) || | 155 if (prev.contentEquals(cursors.Range.fromNode(evt.target)) || |
172 evt.target.state.focused) { | 156 evt.target.state.focused) { |
173 // Category flush here since previous focus events via navigation can | 157 // Category flush here since previous focus events via navigation can |
174 // cause double speak. | 158 // cause double speak. |
175 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 159 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
176 | 160 |
177 // Intentionally skip setting range. | 161 // Intentionally skip setting range. |
178 new Output() | 162 new Output() |
179 .withRichSpeechAndBraille(cursors.Range.fromNode(evt.target), | 163 .withRichSpeechAndBraille( |
180 prev, | 164 cursors.Range.fromNode(evt.target), prev, |
181 Output.EventType.NAVIGATE) | 165 Output.EventType.NAVIGATE) |
182 .go(); | 166 .go(); |
183 } | 167 } |
184 }, | 168 }, |
185 | 169 |
186 /** | 170 /** |
187 * @param {!AutomationEvent} evt | 171 * @param {!AutomationEvent} evt |
188 */ | 172 */ |
189 onEventIfSelected: function(evt) { | 173 onEventIfSelected: function(evt) { |
190 if (evt.target.state.selected) | 174 if (evt.target.state.selected) |
191 this.onEventDefault(evt); | 175 this.onEventDefault(evt); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 return; | 267 return; |
284 } | 268 } |
285 | 269 |
286 if (!this.shouldOutput_(evt)) | 270 if (!this.shouldOutput_(evt)) |
287 return; | 271 return; |
288 | 272 |
289 var curRange = ChromeVoxState.instance.currentRange; | 273 var curRange = ChromeVoxState.instance.currentRange; |
290 | 274 |
291 // Always refresh the braille contents. | 275 // Always refresh the braille contents. |
292 if (curRange && curRange.equals(cursors.Range.fromNode(evt.target))) { | 276 if (curRange && curRange.equals(cursors.Range.fromNode(evt.target))) { |
293 new Output().withBraille(curRange, curRange, Output.EventType.NAVIGATE) | 277 new Output() |
| 278 .withBraille(curRange, curRange, Output.EventType.NAVIGATE) |
294 .go(); | 279 .go(); |
295 } | 280 } |
296 | 281 |
297 this.onActiveDescendantChanged(evt); | 282 this.onActiveDescendantChanged(evt); |
298 }, | 283 }, |
299 | 284 |
300 /** | 285 /** |
301 * Provides all feedback once a focus event fires. | 286 * Provides all feedback once a focus event fires. |
302 * @param {!AutomationEvent} evt | 287 * @param {!AutomationEvent} evt |
303 */ | 288 */ |
(...skipping 14 matching lines...) Expand all Loading... |
318 if (evt.eventFrom == '') | 303 if (evt.eventFrom == '') |
319 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 304 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
320 if (!node.root) | 305 if (!node.root) |
321 return; | 306 return; |
322 | 307 |
323 var root = AutomationUtil.getTopLevelRoot(node.root); | 308 var root = AutomationUtil.getTopLevelRoot(node.root); |
324 // If we're crossing out of a root, save it in case it needs recovering. | 309 // If we're crossing out of a root, save it in case it needs recovering. |
325 var prevRange = ChromeVoxState.instance.currentRange; | 310 var prevRange = ChromeVoxState.instance.currentRange; |
326 var prevNode = prevRange ? prevRange.start.node : null; | 311 var prevNode = prevRange ? prevRange.start.node : null; |
327 if (prevNode) { | 312 if (prevNode) { |
328 var prevRoot = AutomationUtil.getTopLevelRoot(prevNode); | 313 var prevRoot = AutomationUtil.getTopLevelRoot(prevNode); |
329 if (prevRoot && prevRoot !== root) | 314 if (prevRoot && prevRoot !== root) |
330 ChromeVoxState.instance.focusRecoveryMap.set(prevRoot, prevRange); | 315 ChromeVoxState.instance.focusRecoveryMap.set(prevRoot, prevRange); |
331 } | 316 } |
332 // If a previous node was saved for this focus, restore it. | 317 // If a previous node was saved for this focus, restore it. |
333 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); | 318 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); |
334 ChromeVoxState.instance.focusRecoveryMap.delete(root); | 319 ChromeVoxState.instance.focusRecoveryMap.delete(root); |
335 if (savedRange) { | 320 if (savedRange) { |
336 ChromeVoxState.instance.navigateToRange(savedRange, false); | 321 ChromeVoxState.instance.navigateToRange(savedRange, false); |
337 return; | 322 return; |
338 } | 323 } |
339 var event = new CustomAutomationEvent(EventType.FOCUS, node, evt.eventFrom); | 324 var event = new CustomAutomationEvent(EventType.FOCUS, node, evt.eventFrom); |
340 this.onEventDefault(event); | 325 this.onEventDefault(event); |
341 }, | 326 }, |
342 | 327 |
343 /** | 328 /** |
344 * Provides all feedback once a load complete event fires. | 329 * Provides all feedback once a load complete event fires. |
345 * @param {!AutomationEvent} evt | 330 * @param {!AutomationEvent} evt |
346 */ | 331 */ |
347 onLoadComplete: function(evt) { | 332 onLoadComplete: function(evt) { |
348 chrome.automation.getFocus(function(focus) { | 333 chrome.automation.getFocus(function(focus) { |
349 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) | 334 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) |
350 return; | 335 return; |
351 | 336 |
352 // Create text edit handler, if needed, now in order not to miss initial | 337 // Create text edit handler, if needed, now in order not to miss initial |
353 // value change if text field has already been focused when initializing | 338 // value change if text field has already been focused when initializing |
354 // ChromeVox. | 339 // ChromeVox. |
355 this.createTextEditHandlerIfNeeded_(focus); | 340 this.createTextEditHandlerIfNeeded_(focus); |
356 | 341 |
357 // If auto read is set, skip focus recovery and start reading from the top
. | 342 // If auto read is set, skip focus recovery and start reading from the |
| 343 // top. |
358 if (localStorage['autoRead'] == 'true' && | 344 if (localStorage['autoRead'] == 'true' && |
359 AutomationUtil.getTopLevelRoot(evt.target) == evt.target) { | 345 AutomationUtil.getTopLevelRoot(evt.target) == evt.target) { |
360 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(evt.targe
t)); | 346 ChromeVoxState.instance.setCurrentRange( |
| 347 cursors.Range.fromNode(evt.target)); |
361 cvox.ChromeVox.tts.stop(); | 348 cvox.ChromeVox.tts.stop(); |
362 CommandHandler.onCommand('readFromHere'); | 349 CommandHandler.onCommand('readFromHere'); |
363 return; | 350 return; |
364 } | 351 } |
365 | 352 |
366 // If initial focus was already placed on this page (e.g. if a user starts | 353 // If initial focus was already placed on this page (e.g. if a user starts |
367 // tabbing before load complete), then don't move ChromeVox's position on | 354 // tabbing before load complete), then don't move ChromeVox's position on |
368 // the page. | 355 // the page. |
369 if (ChromeVoxState.instance.currentRange && | 356 if (ChromeVoxState.instance.currentRange && |
370 ChromeVoxState.instance.currentRange.start.node.root == focus.root) | 357 ChromeVoxState.instance.currentRange.start.node.root == focus.root) |
(...skipping 10 matching lines...) Expand all Loading... |
381 if (focus != focus.root) | 368 if (focus != focus.root) |
382 o.format('$name', focus.root); | 369 o.format('$name', focus.root); |
383 } | 370 } |
384 } | 371 } |
385 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus)); | 372 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus)); |
386 if (!this.shouldOutput_(evt)) | 373 if (!this.shouldOutput_(evt)) |
387 return; | 374 return; |
388 | 375 |
389 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 376 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
390 o.withRichSpeechAndBraille( | 377 o.withRichSpeechAndBraille( |
391 ChromeVoxState.instance.currentRange, null, evt.type).go(); | 378 ChromeVoxState.instance.currentRange, null, evt.type) |
| 379 .go(); |
392 }.bind(this)); | 380 }.bind(this)); |
393 }, | 381 }, |
394 | 382 |
395 /** | 383 /** |
396 * Provides all feedback once a text changed event fires. | 384 * Provides all feedback once a text changed event fires. |
397 * @param {!AutomationEvent} evt | 385 * @param {!AutomationEvent} evt |
398 */ | 386 */ |
399 onTextChanged: function(evt) { | 387 onTextChanged: function(evt) { |
400 if (evt.target.state.editable) | 388 if (evt.target.state.editable) |
401 this.onEditableChanged_(evt); | 389 this.onEditableChanged_(evt); |
402 }, | 390 }, |
403 | 391 |
404 /** | 392 /** |
405 * Provides all feedback once a text selection changed event fires. | 393 * Provides all feedback once a text selection changed event fires. |
406 * @param {!AutomationEvent} evt | 394 * @param {!AutomationEvent} evt |
407 */ | 395 */ |
408 onTextSelectionChanged: function(evt) { | 396 onTextSelectionChanged: function(evt) { |
409 if (evt.target.state.editable) | 397 if (evt.target.state.editable) |
410 this.onEditableChanged_(evt); | 398 this.onEditableChanged_(evt); |
411 }, | 399 }, |
412 | 400 |
413 /** | 401 /** |
414 * Provides all feedback once a change event in a text field fires. | 402 * Provides all feedback once a change event in a text field fires. |
415 * @param {!AutomationEvent} evt | 403 * @param {!AutomationEvent} evt |
416 * @private | 404 * @private |
417 */ | 405 */ |
418 onEditableChanged_: function(evt) { | 406 onEditableChanged_: function(evt) { |
419 var topRoot = AutomationUtil.getTopLevelRoot(evt.target); | 407 var topRoot = AutomationUtil.getTopLevelRoot(evt.target); |
420 if (!evt.target.state.focused || | 408 if (!evt.target.state.focused || |
421 (topRoot && | 409 (topRoot && topRoot.parent && !topRoot.parent.state.focused)) |
422 topRoot.parent && | |
423 !topRoot.parent.state.focused)) | |
424 return; | 410 return; |
425 | 411 |
426 if (!ChromeVoxState.instance.currentRange) { | 412 if (!ChromeVoxState.instance.currentRange) { |
427 this.onEventDefault(evt); | 413 this.onEventDefault(evt); |
428 ChromeVoxState.instance.setCurrentRange( | 414 ChromeVoxState.instance.setCurrentRange( |
429 cursors.Range.fromNode(evt.target)); | 415 cursors.Range.fromNode(evt.target)); |
430 } | 416 } |
431 | 417 |
432 this.createTextEditHandlerIfNeeded_(evt.target); | 418 this.createTextEditHandlerIfNeeded_(evt.target); |
433 | 419 |
(...skipping 25 matching lines...) Expand all Loading... |
459 // Delegate to the edit text handler if this is an editable. | 445 // Delegate to the edit text handler if this is an editable. |
460 if (evt.target.state.editable) { | 446 if (evt.target.state.editable) { |
461 this.onEditableChanged_(evt); | 447 this.onEditableChanged_(evt); |
462 return; | 448 return; |
463 } | 449 } |
464 | 450 |
465 if (!this.shouldOutput_(evt)) | 451 if (!this.shouldOutput_(evt)) |
466 return; | 452 return; |
467 | 453 |
468 var t = evt.target; | 454 var t = evt.target; |
469 if (t.state.focused || | 455 if (t.state.focused || t.root.role == RoleType.DESKTOP || |
470 t.root.role == RoleType.DESKTOP || | |
471 AutomationUtil.isDescendantOf( | 456 AutomationUtil.isDescendantOf( |
472 ChromeVoxState.instance.currentRange.start.node, t)) { | 457 ChromeVoxState.instance.currentRange.start.node, t)) { |
473 if (new Date() - this.lastValueChanged_ <= | 458 if (new Date() - this.lastValueChanged_ <= |
474 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS) | 459 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS) |
475 return; | 460 return; |
476 | 461 |
477 this.lastValueChanged_ = new Date(); | 462 this.lastValueChanged_ = new Date(); |
478 | 463 |
479 var output = new Output(); | 464 var output = new Output(); |
480 | 465 |
(...skipping 29 matching lines...) Expand all Loading... |
510 if (focus.role == RoleType.WEB_VIEW && evt.target.role == RoleType.TAB) { | 495 if (focus.role == RoleType.WEB_VIEW && evt.target.role == RoleType.TAB) { |
511 ChromeVoxState.instance.setCurrentRange( | 496 ChromeVoxState.instance.setCurrentRange( |
512 cursors.Range.fromNode(focus.firstChild)); | 497 cursors.Range.fromNode(focus.firstChild)); |
513 return; | 498 return; |
514 } | 499 } |
515 | 500 |
516 // Some cases (e.g. in overview mode), require overriding the assumption | 501 // Some cases (e.g. in overview mode), require overriding the assumption |
517 // that focus is an ancestor of a selection target. | 502 // that focus is an ancestor of a selection target. |
518 var override = evt.target.role == RoleType.MENU_ITEM || | 503 var override = evt.target.role == RoleType.MENU_ITEM || |
519 (evt.target.root == focus.root && | 504 (evt.target.root == focus.root && |
520 focus.root.role == RoleType.DESKTOP); | 505 focus.root.role == RoleType.DESKTOP); |
521 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 506 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
522 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) | 507 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) |
523 this.onEventDefault(evt); | 508 this.onEventDefault(evt); |
524 }.bind(this)); | 509 }.bind(this)); |
525 }, | 510 }, |
526 | 511 |
527 /** | 512 /** |
528 * Provides all feedback once a menu start event fires. | 513 * Provides all feedback once a menu start event fires. |
529 * @param {!AutomationEvent} evt | 514 * @param {!AutomationEvent} evt |
530 */ | 515 */ |
(...skipping 17 matching lines...) Expand all Loading... |
548 this.onFocus(event); | 533 this.onFocus(event); |
549 } | 534 } |
550 }.bind(this)); | 535 }.bind(this)); |
551 }, | 536 }, |
552 | 537 |
553 /** | 538 /** |
554 * Create an editable text handler for the given node if needed. | 539 * Create an editable text handler for the given node if needed. |
555 * @param {!AutomationNode} node | 540 * @param {!AutomationNode} node |
556 */ | 541 */ |
557 createTextEditHandlerIfNeeded_: function(node) { | 542 createTextEditHandlerIfNeeded_: function(node) { |
558 if (!this.textEditHandler_ || | 543 if (!this.textEditHandler_ || this.textEditHandler_.node !== node) { |
559 this.textEditHandler_.node !== node) { | |
560 this.textEditHandler_ = editing.TextEditHandler.createForNode(node); | 544 this.textEditHandler_ = editing.TextEditHandler.createForNode(node); |
561 } | 545 } |
562 }, | 546 }, |
563 | 547 |
564 /** | 548 /** |
565 * Once an event handler updates ChromeVox's range based on |evt| | 549 * Once an event handler updates ChromeVox's range based on |evt| |
566 * which updates mode, returns whether |evt| should be outputted. | 550 * which updates mode, returns whether |evt| should be outputted. |
567 * @return {boolean} | 551 * @return {boolean} |
568 */ | 552 */ |
569 shouldOutput_: function(evt) { | 553 shouldOutput_: function(evt) { |
570 var mode = ChromeVoxState.instance.mode; | 554 var mode = ChromeVoxState.instance.mode; |
571 // Only output desktop rooted nodes or web nodes for next engine modes. | 555 // Only output desktop rooted nodes or web nodes for next engine modes. |
572 return evt.target.root.role == RoleType.DESKTOP || | 556 return evt.target.root.role == RoleType.DESKTOP || |
573 (mode == ChromeVoxMode.NEXT || | 557 (mode == ChromeVoxMode.NEXT || mode == ChromeVoxMode.FORCE_NEXT || |
574 mode == ChromeVoxMode.FORCE_NEXT || | |
575 mode == ChromeVoxMode.CLASSIC_COMPAT); | 558 mode == ChromeVoxMode.CLASSIC_COMPAT); |
576 } | 559 } |
577 }; | 560 }; |
578 | 561 |
579 /** | 562 /** |
580 * Initializes global state for DesktopAutomationHandler. | 563 * Initializes global state for DesktopAutomationHandler. |
581 * @private | 564 * @private |
582 */ | 565 */ |
583 DesktopAutomationHandler.init_ = function() { | 566 DesktopAutomationHandler.init_ = function() { |
584 chrome.automation.getDesktop(function(desktop) { | 567 chrome.automation.getDesktop(function(desktop) { |
585 ChromeVoxState.desktopAutomationHandler = | 568 ChromeVoxState.desktopAutomationHandler = |
586 new DesktopAutomationHandler(desktop); | 569 new DesktopAutomationHandler(desktop); |
587 }); | 570 }); |
588 }; | 571 }; |
589 | 572 |
590 DesktopAutomationHandler.init_(); | 573 DesktopAutomationHandler.init_(); |
591 | 574 |
592 }); // goog.scope | 575 }); // goog.scope |
OLD | NEW |