| 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 |