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 |