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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 * @param {!AutomationEvent} evt | 255 * @param {!AutomationEvent} evt |
272 */ | 256 */ |
273 onChildrenChanged: function(evt) { | 257 onChildrenChanged: function(evt) { |
274 if (!this.shouldOutput_(evt)) | 258 if (!this.shouldOutput_(evt)) |
275 return; | 259 return; |
276 | 260 |
277 var curRange = ChromeVoxState.instance.currentRange; | 261 var curRange = ChromeVoxState.instance.currentRange; |
278 | 262 |
279 // Always refresh the braille contents. | 263 // Always refresh the braille contents. |
280 if (curRange && curRange.equals(cursors.Range.fromNode(evt.target))) { | 264 if (curRange && curRange.equals(cursors.Range.fromNode(evt.target))) { |
281 new Output().withBraille(curRange, curRange, Output.EventType.NAVIGATE) | 265 new Output() |
| 266 .withBraille(curRange, curRange, Output.EventType.NAVIGATE) |
282 .go(); | 267 .go(); |
283 } | 268 } |
284 | 269 |
285 this.onActiveDescendantChanged(evt); | 270 this.onActiveDescendantChanged(evt); |
286 }, | 271 }, |
287 | 272 |
288 /** | 273 /** |
289 * Provides all feedback once a focus event fires. | 274 * Provides all feedback once a focus event fires. |
290 * @param {!AutomationEvent} evt | 275 * @param {!AutomationEvent} evt |
291 */ | 276 */ |
(...skipping 14 matching lines...) Expand all Loading... |
306 if (evt.eventFrom == '') | 291 if (evt.eventFrom == '') |
307 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); | 292 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); |
308 if (!node.root) | 293 if (!node.root) |
309 return; | 294 return; |
310 | 295 |
311 var root = AutomationUtil.getTopLevelRoot(node.root); | 296 var root = AutomationUtil.getTopLevelRoot(node.root); |
312 // If we're crossing out of a root, save it in case it needs recovering. | 297 // If we're crossing out of a root, save it in case it needs recovering. |
313 var prevRange = ChromeVoxState.instance.currentRange; | 298 var prevRange = ChromeVoxState.instance.currentRange; |
314 var prevNode = prevRange ? prevRange.start.node : null; | 299 var prevNode = prevRange ? prevRange.start.node : null; |
315 if (prevNode) { | 300 if (prevNode) { |
316 var prevRoot = AutomationUtil.getTopLevelRoot(prevNode); | 301 var prevRoot = AutomationUtil.getTopLevelRoot(prevNode); |
317 if (prevRoot && prevRoot !== root) | 302 if (prevRoot && prevRoot !== root) |
318 ChromeVoxState.instance.focusRecoveryMap.set(prevRoot, prevRange); | 303 ChromeVoxState.instance.focusRecoveryMap.set(prevRoot, prevRange); |
319 } | 304 } |
320 // If a previous node was saved for this focus, restore it. | 305 // If a previous node was saved for this focus, restore it. |
321 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); | 306 var savedRange = ChromeVoxState.instance.focusRecoveryMap.get(root); |
322 ChromeVoxState.instance.focusRecoveryMap.delete(root); | 307 ChromeVoxState.instance.focusRecoveryMap.delete(root); |
323 if (savedRange) { | 308 if (savedRange) { |
324 ChromeVoxState.instance.navigateToRange(savedRange, false); | 309 ChromeVoxState.instance.navigateToRange(savedRange, false); |
325 return; | 310 return; |
326 } | 311 } |
327 var event = new CustomAutomationEvent(EventType.FOCUS, node, evt.eventFrom); | 312 var event = new CustomAutomationEvent(EventType.FOCUS, node, evt.eventFrom); |
328 this.onEventDefault(event); | 313 this.onEventDefault(event); |
329 }, | 314 }, |
330 | 315 |
331 /** | 316 /** |
332 * Provides all feedback once a load complete event fires. | 317 * Provides all feedback once a load complete event fires. |
333 * @param {!AutomationEvent} evt | 318 * @param {!AutomationEvent} evt |
334 */ | 319 */ |
335 onLoadComplete: function(evt) { | 320 onLoadComplete: function(evt) { |
336 chrome.automation.getFocus(function(focus) { | 321 chrome.automation.getFocus(function(focus) { |
337 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) | 322 if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) |
338 return; | 323 return; |
339 | 324 |
340 // Create text edit handler, if needed, now in order not to miss initial | 325 // Create text edit handler, if needed, now in order not to miss initial |
341 // value change if text field has already been focused when initializing | 326 // value change if text field has already been focused when initializing |
342 // ChromeVox. | 327 // ChromeVox. |
343 this.createTextEditHandlerIfNeeded_(focus); | 328 this.createTextEditHandlerIfNeeded_(focus); |
344 | 329 |
345 // If auto read is set, skip focus recovery and start reading from the top
. | 330 // If auto read is set, skip focus recovery and start reading from the |
| 331 // top. |
346 if (localStorage['autoRead'] == 'true' && | 332 if (localStorage['autoRead'] == 'true' && |
347 AutomationUtil.getTopLevelRoot(evt.target) == evt.target) { | 333 AutomationUtil.getTopLevelRoot(evt.target) == evt.target) { |
348 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(evt.targe
t)); | 334 ChromeVoxState.instance.setCurrentRange( |
| 335 cursors.Range.fromNode(evt.target)); |
349 cvox.ChromeVox.tts.stop(); | 336 cvox.ChromeVox.tts.stop(); |
350 CommandHandler.onCommand('readFromHere'); | 337 CommandHandler.onCommand('readFromHere'); |
351 return; | 338 return; |
352 } | 339 } |
353 | 340 |
354 // If initial focus was already placed on this page (e.g. if a user starts | 341 // If initial focus was already placed on this page (e.g. if a user starts |
355 // tabbing before load complete), then don't move ChromeVox's position on | 342 // tabbing before load complete), then don't move ChromeVox's position on |
356 // the page. | 343 // the page. |
357 if (ChromeVoxState.instance.currentRange && | 344 if (ChromeVoxState.instance.currentRange && |
358 ChromeVoxState.instance.currentRange.start.node.root == focus.root) | 345 ChromeVoxState.instance.currentRange.start.node.root == focus.root) |
(...skipping 10 matching lines...) Expand all Loading... |
369 if (focus != focus.root) | 356 if (focus != focus.root) |
370 o.format('$name', focus.root); | 357 o.format('$name', focus.root); |
371 } | 358 } |
372 } | 359 } |
373 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus)); | 360 ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus)); |
374 if (!this.shouldOutput_(evt)) | 361 if (!this.shouldOutput_(evt)) |
375 return; | 362 return; |
376 | 363 |
377 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 364 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
378 o.withRichSpeechAndBraille( | 365 o.withRichSpeechAndBraille( |
379 ChromeVoxState.instance.currentRange, null, evt.type).go(); | 366 ChromeVoxState.instance.currentRange, null, evt.type) |
| 367 .go(); |
380 }.bind(this)); | 368 }.bind(this)); |
381 }, | 369 }, |
382 | 370 |
383 /** | 371 /** |
384 * Provides all feedback once a text changed event fires. | 372 * Provides all feedback once a text changed event fires. |
385 * @param {!AutomationEvent} evt | 373 * @param {!AutomationEvent} evt |
386 */ | 374 */ |
387 onTextChanged: function(evt) { | 375 onTextChanged: function(evt) { |
388 if (evt.target.state.editable) | 376 if (evt.target.state.editable) |
389 this.onEditableChanged_(evt); | 377 this.onEditableChanged_(evt); |
390 }, | 378 }, |
391 | 379 |
392 /** | 380 /** |
393 * Provides all feedback once a text selection changed event fires. | 381 * Provides all feedback once a text selection changed event fires. |
394 * @param {!AutomationEvent} evt | 382 * @param {!AutomationEvent} evt |
395 */ | 383 */ |
396 onTextSelectionChanged: function(evt) { | 384 onTextSelectionChanged: function(evt) { |
397 if (evt.target.state.editable) | 385 if (evt.target.state.editable) |
398 this.onEditableChanged_(evt); | 386 this.onEditableChanged_(evt); |
399 }, | 387 }, |
400 | 388 |
401 /** | 389 /** |
402 * Provides all feedback once a change event in a text field fires. | 390 * Provides all feedback once a change event in a text field fires. |
403 * @param {!AutomationEvent} evt | 391 * @param {!AutomationEvent} evt |
404 * @private | 392 * @private |
405 */ | 393 */ |
406 onEditableChanged_: function(evt) { | 394 onEditableChanged_: function(evt) { |
407 var topRoot = AutomationUtil.getTopLevelRoot(evt.target); | 395 var topRoot = AutomationUtil.getTopLevelRoot(evt.target); |
408 if (!evt.target.state.focused || | 396 if (!evt.target.state.focused || |
409 (topRoot && | 397 (topRoot && topRoot.parent && !topRoot.parent.state.focused)) |
410 topRoot.parent && | |
411 !topRoot.parent.state.focused)) | |
412 return; | 398 return; |
413 | 399 |
414 if (!ChromeVoxState.instance.currentRange) { | 400 if (!ChromeVoxState.instance.currentRange) { |
415 this.onEventDefault(evt); | 401 this.onEventDefault(evt); |
416 ChromeVoxState.instance.setCurrentRange( | 402 ChromeVoxState.instance.setCurrentRange( |
417 cursors.Range.fromNode(evt.target)); | 403 cursors.Range.fromNode(evt.target)); |
418 } | 404 } |
419 | 405 |
420 this.createTextEditHandlerIfNeeded_(evt.target); | 406 this.createTextEditHandlerIfNeeded_(evt.target); |
421 | 407 |
(...skipping 25 matching lines...) Expand all Loading... |
447 // Delegate to the edit text handler if this is an editable. | 433 // Delegate to the edit text handler if this is an editable. |
448 if (evt.target.state.editable) { | 434 if (evt.target.state.editable) { |
449 this.onEditableChanged_(evt); | 435 this.onEditableChanged_(evt); |
450 return; | 436 return; |
451 } | 437 } |
452 | 438 |
453 if (!this.shouldOutput_(evt)) | 439 if (!this.shouldOutput_(evt)) |
454 return; | 440 return; |
455 | 441 |
456 var t = evt.target; | 442 var t = evt.target; |
457 if (t.state.focused || | 443 if (t.state.focused || t.root.role == RoleType.DESKTOP || |
458 t.root.role == RoleType.DESKTOP || | |
459 AutomationUtil.isDescendantOf( | 444 AutomationUtil.isDescendantOf( |
460 ChromeVoxState.instance.currentRange.start.node, t)) { | 445 ChromeVoxState.instance.currentRange.start.node, t)) { |
461 if (new Date() - this.lastValueChanged_ <= | 446 if (new Date() - this.lastValueChanged_ <= |
462 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS) | 447 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS) |
463 return; | 448 return; |
464 | 449 |
465 this.lastValueChanged_ = new Date(); | 450 this.lastValueChanged_ = new Date(); |
466 | 451 |
467 var output = new Output(); | 452 var output = new Output(); |
468 | 453 |
(...skipping 29 matching lines...) Expand all Loading... |
498 if (focus.role == RoleType.WEB_VIEW && evt.target.role == RoleType.TAB) { | 483 if (focus.role == RoleType.WEB_VIEW && evt.target.role == RoleType.TAB) { |
499 ChromeVoxState.instance.setCurrentRange( | 484 ChromeVoxState.instance.setCurrentRange( |
500 cursors.Range.fromNode(focus.firstChild)); | 485 cursors.Range.fromNode(focus.firstChild)); |
501 return; | 486 return; |
502 } | 487 } |
503 | 488 |
504 // Some cases (e.g. in overview mode), require overriding the assumption | 489 // Some cases (e.g. in overview mode), require overriding the assumption |
505 // that focus is an ancestor of a selection target. | 490 // that focus is an ancestor of a selection target. |
506 var override = evt.target.role == RoleType.MENU_ITEM || | 491 var override = evt.target.role == RoleType.MENU_ITEM || |
507 (evt.target.root == focus.root && | 492 (evt.target.root == focus.root && |
508 focus.root.role == RoleType.DESKTOP); | 493 focus.root.role == RoleType.DESKTOP); |
509 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); | 494 Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); |
510 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) | 495 if (override || AutomationUtil.isDescendantOf(evt.target, focus)) |
511 this.onEventDefault(evt); | 496 this.onEventDefault(evt); |
512 }.bind(this)); | 497 }.bind(this)); |
513 }, | 498 }, |
514 | 499 |
515 /** | 500 /** |
516 * Provides all feedback once a menu start event fires. | 501 * Provides all feedback once a menu start event fires. |
517 * @param {!AutomationEvent} evt | 502 * @param {!AutomationEvent} evt |
518 */ | 503 */ |
(...skipping 17 matching lines...) Expand all Loading... |
536 this.onFocus(event); | 521 this.onFocus(event); |
537 } | 522 } |
538 }.bind(this)); | 523 }.bind(this)); |
539 }, | 524 }, |
540 | 525 |
541 /** | 526 /** |
542 * Create an editable text handler for the given node if needed. | 527 * Create an editable text handler for the given node if needed. |
543 * @param {!AutomationNode} node | 528 * @param {!AutomationNode} node |
544 */ | 529 */ |
545 createTextEditHandlerIfNeeded_: function(node) { | 530 createTextEditHandlerIfNeeded_: function(node) { |
546 if (!this.textEditHandler_ || | 531 if (!this.textEditHandler_ || this.textEditHandler_.node !== node) { |
547 this.textEditHandler_.node !== node) { | |
548 this.textEditHandler_ = editing.TextEditHandler.createForNode(node); | 532 this.textEditHandler_ = editing.TextEditHandler.createForNode(node); |
549 } | 533 } |
550 }, | 534 }, |
551 | 535 |
552 /** | 536 /** |
553 * Once an event handler updates ChromeVox's range based on |evt| | 537 * Once an event handler updates ChromeVox's range based on |evt| |
554 * which updates mode, returns whether |evt| should be outputted. | 538 * which updates mode, returns whether |evt| should be outputted. |
555 * @return {boolean} | 539 * @return {boolean} |
556 */ | 540 */ |
557 shouldOutput_: function(evt) { | 541 shouldOutput_: function(evt) { |
558 var mode = ChromeVoxState.instance.mode; | 542 var mode = ChromeVoxState.instance.mode; |
559 // Only output desktop rooted nodes or web nodes for next engine modes. | 543 // Only output desktop rooted nodes or web nodes for next engine modes. |
560 return evt.target.root.role == RoleType.DESKTOP || | 544 return evt.target.root.role == RoleType.DESKTOP || |
561 (mode == ChromeVoxMode.NEXT || | 545 (mode == ChromeVoxMode.NEXT || mode == ChromeVoxMode.FORCE_NEXT || |
562 mode == ChromeVoxMode.FORCE_NEXT || | |
563 mode == ChromeVoxMode.CLASSIC_COMPAT); | 546 mode == ChromeVoxMode.CLASSIC_COMPAT); |
564 } | 547 } |
565 }; | 548 }; |
566 | 549 |
567 /** | 550 /** |
568 * Initializes global state for DesktopAutomationHandler. | 551 * Initializes global state for DesktopAutomationHandler. |
569 * @private | 552 * @private |
570 */ | 553 */ |
571 DesktopAutomationHandler.init_ = function() { | 554 DesktopAutomationHandler.init_ = function() { |
572 chrome.automation.getDesktop(function(desktop) { | 555 chrome.automation.getDesktop(function(desktop) { |
573 ChromeVoxState.desktopAutomationHandler = | 556 ChromeVoxState.desktopAutomationHandler = |
574 new DesktopAutomationHandler(desktop); | 557 new DesktopAutomationHandler(desktop); |
575 }); | 558 }); |
576 }; | 559 }; |
577 | 560 |
578 DesktopAutomationHandler.init_(); | 561 DesktopAutomationHandler.init_(); |
579 | 562 |
580 }); // goog.scope | 563 }); // goog.scope |
OLD | NEW |