| 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 Implements support for live regions in ChromeVox Next. | 6 * @fileoverview Implements support for live regions in ChromeVox Next. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 goog.provide('LiveRegions'); | 9 goog.provide('LiveRegions'); |
| 10 | 10 |
| 11 goog.require('ChromeVoxState'); | 11 goog.require('ChromeVoxState'); |
| 12 | 12 |
| 13 goog.scope(function() { | 13 goog.scope(function() { |
| 14 var AutomationNode = chrome.automation.AutomationNode; | 14 var AutomationNode = chrome.automation.AutomationNode; |
| 15 var RoleType = chrome.automation.RoleType; |
| 15 var TreeChange = chrome.automation.TreeChange; | 16 var TreeChange = chrome.automation.TreeChange; |
| 16 | 17 |
| 17 /** | 18 /** |
| 18 * ChromeVox2 live region handler. | 19 * ChromeVox2 live region handler. |
| 19 * @param {!ChromeVoxState} chromeVoxState The ChromeVox state object, | 20 * @param {!ChromeVoxState} chromeVoxState The ChromeVox state object, |
| 20 * keeping track of the current mode and current range. | 21 * keeping track of the current mode and current range. |
| 21 * @constructor | 22 * @constructor |
| 22 */ | 23 */ |
| 23 LiveRegions = function(chromeVoxState) { | 24 LiveRegions = function(chromeVoxState) { |
| 24 /** | 25 /** |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 | 81 |
| 81 var mode = this.chromeVoxState_.mode; | 82 var mode = this.chromeVoxState_.mode; |
| 82 var currentRange = this.chromeVoxState_.currentRange; | 83 var currentRange = this.chromeVoxState_.currentRange; |
| 83 | 84 |
| 84 if (mode === ChromeVoxMode.CLASSIC || !cvox.ChromeVox.isActive) | 85 if (mode === ChromeVoxMode.CLASSIC || !cvox.ChromeVox.isActive) |
| 85 return; | 86 return; |
| 86 | 87 |
| 87 if (!currentRange) | 88 if (!currentRange) |
| 88 return; | 89 return; |
| 89 | 90 |
| 91 var webView = AutomationUtil.getTopLevelRoot(node); |
| 92 webView = webView ? webView.parent : null; |
| 90 if (!LiveRegions.announceLiveRegionsFromBackgroundTabs_ && | 93 if (!LiveRegions.announceLiveRegionsFromBackgroundTabs_ && |
| 91 !AutomationUtil.isInSameWebpage(node, currentRange.start.node)) { | 94 currentRange.start.node.role != RoleType.desktop && |
| 95 (!webView || !webView.state.focused)) { |
| 92 return; | 96 return; |
| 93 } | 97 } |
| 94 | 98 |
| 95 var type = treeChange.type; | 99 var type = treeChange.type; |
| 96 var relevant = node.containerLiveRelevant; | 100 var relevant = node.containerLiveRelevant; |
| 97 if (relevant.indexOf('additions') >= 0 && | 101 if (relevant.indexOf('additions') >= 0 && |
| 98 (type == 'nodeCreated' || type == 'subtreeCreated')) { | 102 (type == 'nodeCreated' || type == 'subtreeCreated')) { |
| 99 this.outputLiveRegionChange_(node, null); | 103 this.outputLiveRegionChange_(node, null); |
| 100 } | 104 } |
| 101 | 105 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 137 |
| 134 if (!output.hasSpeech && node.liveAtomic) | 138 if (!output.hasSpeech && node.liveAtomic) |
| 135 output.format('$joinedDescendants', node); | 139 output.format('$joinedDescendants', node); |
| 136 | 140 |
| 137 output.withSpeechCategory(cvox.TtsCategory.LIVE); | 141 output.withSpeechCategory(cvox.TtsCategory.LIVE); |
| 138 | 142 |
| 139 var currentTime = new Date(); | 143 var currentTime = new Date(); |
| 140 if (!output.hasSpeech) | 144 if (!output.hasSpeech) |
| 141 return; | 145 return; |
| 142 | 146 |
| 147 // Queue live regions coming from background tabs. |
| 148 var webView = AutomationUtil.getTopLevelRoot(node); |
| 149 webView = webView ? webView.parent : null; |
| 150 var forceQueueForBackgroundedLiveRegion = |
| 151 !webView || !webView.state.focused; |
| 152 |
| 143 // Enqueue live region updates that were received at approximately | 153 // Enqueue live region updates that were received at approximately |
| 144 // the same time, otherwise flush previous live region updates. | 154 // the same time, otherwise flush previous live region updates. |
| 145 var queueTime = LiveRegions.LIVE_REGION_QUEUE_TIME_MS; | 155 var queueTime = LiveRegions.LIVE_REGION_QUEUE_TIME_MS; |
| 146 var delta = currentTime - this.lastLiveRegionTime_; | 156 var delta = currentTime - this.lastLiveRegionTime_; |
| 147 if (delta > queueTime) | 157 if (delta > queueTime && !forceQueueForBackgroundedLiveRegion) |
| 148 output.withQueueMode(cvox.QueueMode.CATEGORY_FLUSH); | 158 output.withQueueMode(cvox.QueueMode.CATEGORY_FLUSH); |
| 149 else | 159 else |
| 150 output.withQueueMode(cvox.QueueMode.QUEUE); | 160 output.withQueueMode(cvox.QueueMode.QUEUE); |
| 151 | 161 |
| 152 if (delta > LiveRegions.LIVE_REGION_MIN_SAME_NODE_MS) | 162 if (delta > LiveRegions.LIVE_REGION_MIN_SAME_NODE_MS) |
| 153 this.liveRegionNodeSet_ = new WeakSet(); | 163 this.liveRegionNodeSet_ = new WeakSet(); |
| 154 | 164 |
| 155 var parent = node; | 165 var parent = node; |
| 156 while (parent) { | 166 while (parent) { |
| 157 if (this.liveRegionNodeSet_.has(parent)) { | 167 if (this.liveRegionNodeSet_.has(parent)) { |
| 158 this.lastLiveRegionTime_ = currentTime; | 168 this.lastLiveRegionTime_ = currentTime; |
| 159 return; | 169 return; |
| 160 } | 170 } |
| 161 parent = parent.parent; | 171 parent = parent.parent; |
| 162 } | 172 } |
| 163 | 173 |
| 164 this.liveRegionNodeSet_.add(node); | 174 this.liveRegionNodeSet_.add(node); |
| 165 output.go(); | 175 output.go(); |
| 166 this.lastLiveRegionTime_ = currentTime; | 176 this.lastLiveRegionTime_ = currentTime; |
| 167 }, | 177 }, |
| 168 }; | 178 }; |
| 169 | 179 |
| 170 }); // goog.scope | 180 }); // goog.scope |
| OLD | NEW |