Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 var AutomationEvent = chrome.automation.AutomationEvent; | 5 var AutomationEvent = chrome.automation.AutomationEvent; |
| 6 var AutomationNode = chrome.automation.AutomationNode; | 6 var AutomationNode = chrome.automation.AutomationNode; |
| 7 var EventType = chrome.automation.EventType; | 7 var EventType = chrome.automation.EventType; |
| 8 var RoleType = chrome.automation.RoleType; | 8 var RoleType = chrome.automation.RoleType; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 var SelectToSpeak = function() { | 51 var SelectToSpeak = function() { |
| 52 /** @private { AutomationNode } */ | 52 /** @private { AutomationNode } */ |
| 53 this.node_ = null; | 53 this.node_ = null; |
| 54 | 54 |
| 55 /** @private { boolean } */ | 55 /** @private { boolean } */ |
| 56 this.down_ = false; | 56 this.down_ = false; |
| 57 | 57 |
| 58 /** @private {{x: number, y: number}} */ | 58 /** @private {{x: number, y: number}} */ |
| 59 this.mouseStart_ = {x: 0, y: 0}; | 59 this.mouseStart_ = {x: 0, y: 0}; |
| 60 | 60 |
| 61 /** @private {{x: number, y: number}} */ | |
| 62 this.mouseEnd_ = {x: 0, y: 0}; | |
| 63 | |
| 64 /** @private {AutomationRootNode} */ | |
| 61 chrome.automation.getDesktop(function(desktop) { | 65 chrome.automation.getDesktop(function(desktop) { |
| 66 this.desktop_ = desktop; | |
| 67 | |
| 68 // After the user selects a region of the screen, we do a hit test at | |
| 69 // the center of that box using the automation API. The result of the | |
| 70 // hit test is a MOUSE_RELEASED accessibility event. | |
| 62 desktop.addEventListener( | 71 desktop.addEventListener( |
| 63 EventType.MOUSE_PRESSED, this.onMousePressed_.bind(this), true); | 72 EventType.MOUSE_RELEASED, this.onMouseReleasedHitTest_.bind(this), |
| 73 true); | |
| 74 | |
| 75 // A MOUSE_CANCELED accessibility event is fired if the user releases | |
|
David Tseng
2017/05/07 06:10:27
Would be great to also handle key events in this e
dmazzoni
2017/05/10 19:43:18
OK, done. The event handler now forwards all keybo
| |
| 76 // the Search key while the mouse is still down. | |
| 64 desktop.addEventListener( | 77 desktop.addEventListener( |
| 65 EventType.MOUSE_DRAGGED, this.onMouseDragged_.bind(this), true); | 78 EventType.MOUSE_CANCELED, this.onMouseCanceled_.bind(this), |
| 66 desktop.addEventListener( | 79 true); |
| 67 EventType.MOUSE_RELEASED, this.onMouseReleased_.bind(this), true); | |
| 68 desktop.addEventListener( | |
| 69 EventType.MOUSE_CANCELED, this.onMouseCanceled_.bind(this), true); | |
| 70 }.bind(this)); | 80 }.bind(this)); |
| 71 | 81 |
| 72 /** @private { ?string } */ | 82 /** @private { ?string } */ |
| 73 this.voiceNameFromPrefs_ = null; | 83 this.voiceNameFromPrefs_ = null; |
| 74 | 84 |
| 75 /** @private { ?string } */ | 85 /** @private { ?string } */ |
| 76 this.voiceNameFromLocale_ = null; | 86 this.voiceNameFromLocale_ = null; |
| 77 | 87 |
| 78 /** @private { Set<string> } */ | 88 /** @private { Set<string> } */ |
| 79 this.validVoiceNames_ = new Set(); | 89 this.validVoiceNames_ = new Set(); |
| 80 | 90 |
| 81 /** @private { number } */ | 91 /** @private { number } */ |
| 82 this.speechRate_ = 1.0; | 92 this.speechRate_ = 1.0; |
| 83 | 93 |
| 84 /** @const { string } */ | 94 /** @const { string } */ |
| 85 this.color_ = "#f73a98"; | 95 this.color_ = "#f73a98"; |
| 86 | 96 |
| 87 this.initPreferences_(); | 97 this.initPreferences_(); |
| 98 | |
| 99 this.captureMouseEvents_(); | |
| 88 }; | 100 }; |
| 89 | 101 |
| 90 SelectToSpeak.prototype = { | 102 SelectToSpeak.prototype = { |
| 91 /** | 103 /** |
| 92 * Called when the mouse is pressed and the user is in a mode where | 104 * Called when the mouse is pressed and the user is in a mode where |
| 93 * select-to-speak is capturing mouse events (for example holding down | 105 * select-to-speak is capturing mouse events (for example holding down |
| 94 * Search). | 106 * Search). |
| 95 * | 107 * |
| 96 * @param {!AutomationEvent} evt | 108 * @param {!Event} evt The DOM event |
|
David Tseng
2017/05/07 06:10:27
Dom event listeners have a return value (i.e. add
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 97 */ | 109 */ |
| 98 onMousePressed_: function(evt) { | 110 onMouseDown_: function(evt) { |
| 99 this.down_ = true; | 111 this.down_ = true; |
|
David Tseng
2017/05/07 06:59:40
Now that you have the mouse event, I don't think y
dmazzoni
2017/05/10 19:43:18
Changed to this.trackingMouse_ - it's not whether
| |
| 100 this.mouseStart_ = {x: evt.mouseX, y: evt.mouseY}; | 112 this.mouseStart_ = {x: evt.screenX, y: evt.screenY}; |
| 101 this.startNode_ = evt.target; | |
| 102 chrome.tts.stop(); | 113 chrome.tts.stop(); |
| 103 this.onMouseDragged_(evt); | 114 |
| 115 // Fire a hit test event on click to warm up the cache. | |
| 116 this.desktop_.hitTest(ctrX, ctrY, EventType.NONE); | |
| 117 | |
| 118 this.onMouseMove_(evt); | |
| 104 }, | 119 }, |
| 105 | 120 |
| 106 /** | 121 /** |
| 107 * Called when the mouse is moved or dragged and the user is in a | 122 * Called when the mouse is moved or dragged and the user is in a |
| 108 * mode where select-to-speak is capturing mouse events (for example | 123 * mode where select-to-speak is capturing mouse events (for example |
| 109 * holding down Search). | 124 * holding down Search). |
| 110 * | 125 * |
| 111 * @param {!AutomationEvent} evt | 126 * @param {!Event} evt The DOM event |
|
David Tseng
2017/05/07 06:10:27
Ditto, @return
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 112 */ | 127 */ |
| 113 onMouseDragged_: function(evt) { | 128 onMouseMove_: function(evt) { |
| 114 if (!this.down_) | 129 if (!this.down_) |
| 115 return; | 130 return; |
| 116 | 131 |
| 117 var rect = rectFromPoints( | 132 var rect = rectFromPoints( |
| 118 this.mouseStart_.x, this.mouseStart_.y, | 133 this.mouseStart_.x, this.mouseStart_.y, |
| 119 evt.mouseX, evt.mouseY); | 134 evt.screenX, evt.screenY); |
| 120 chrome.accessibilityPrivate.setFocusRing([rect], this.color_); | 135 chrome.accessibilityPrivate.setFocusRing([rect], this.color_); |
| 121 }, | 136 }, |
| 122 | 137 |
| 123 /** | 138 /** |
| 124 * Called when the mouse is released and the user is in a | 139 * Called when the mouse is released and the user is in a |
| 125 * mode where select-to-speak is capturing mouse events (for example | 140 * mode where select-to-speak is capturing mouse events (for example |
| 126 * holding down Search). | 141 * holding down Search). |
| 127 * | 142 * |
| 128 * @param {!AutomationEvent} evt | 143 * @param {!AutomationEvent} evt |
|
David Tseng
2017/05/07 06:10:27
This is a DOM event listener, not an automation ev
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 129 */ | 144 */ |
|
David Tseng
2017/05/07 06:10:27
@return
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 130 onMouseReleased_: function(evt) { | 145 onMouseUp_: function(evt) { |
| 131 this.onMouseDragged_(evt); | 146 this.onMouseMove_(evt); |
| 132 this.down_ = false; | 147 this.down_ = false; |
| 133 | 148 |
| 134 chrome.accessibilityPrivate.setFocusRing([]); | 149 chrome.accessibilityPrivate.setFocusRing([]); |
| 135 | 150 |
| 151 this.mouseEnd_ = {x: evt.screenX, y: evt.screenY}; | |
| 152 var ctrX = Math.floor((this.mouseStart_.x + this.mouseEnd_.x) / 2); | |
| 153 var ctrY = Math.floor((this.mouseStart_.y + this.mouseEnd_.y) / 2); | |
| 154 | |
| 155 // Do a hit test at the center of the area the user dragged over. | |
| 156 // This will give us some context when searching the accessibility tree. | |
| 157 // The hit test will result in a EventType.MOUSE_RELEASED event being | |
| 158 // fired on the result of that hit test, which will trigger | |
| 159 // onMouseReleasedHitTest_. | |
|
David Tseng
2017/05/07 06:10:27
Just wondering, but it seems confusing to have a m
dmazzoni
2017/05/10 19:43:18
I agree, this is confusing.
I think we should get
| |
| 160 this.desktop_.hitTest(ctrX, ctrY, EventType.MOUSE_RELEASED); | |
| 161 }, | |
| 162 | |
| 163 /** | |
| 164 * Called in response to our hit test afterthe mouse is released, | |
|
David Tseng
2017/05/07 06:10:27
nit: after the
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 165 * when the user is in a mode where select-to-speak is capturing | |
| 166 * mouse events (for example holding down Search). | |
| 167 * | |
| 168 * @param {!AutomationEvent} evt The automation event. | |
| 169 */ | |
| 170 onMouseReleasedHitTest_: function(evt) { | |
|
David Tseng
2017/05/07 06:10:27
nit: Maybe rename the listeners like
onAutomationF
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 136 // Walk up to the nearest window, web area, or dialog that the | 171 // Walk up to the nearest window, web area, or dialog that the |
|
David Tseng
2017/05/07 06:10:28
Might as well include toolbar as well.
dmazzoni
2017/05/10 19:43:18
Done.
| |
| 137 // hit node is contained inside. Only speak objects within that | 172 // hit node is contained inside. Only speak objects within that |
| 138 // container. In the future we might include other container-like | 173 // container. In the future we might include other container-like |
| 139 // roles here. | 174 // roles here. |
| 140 var root = this.startNode_; | 175 var root = evt.target; |
| 141 while (root.parent && | 176 while (root.parent && |
| 142 root.role != RoleType.WINDOW && | 177 root.role != RoleType.WINDOW && |
| 143 root.role != RoleType.ROOT_WEB_AREA && | 178 root.role != RoleType.ROOT_WEB_AREA && |
| 144 root.role != RoleType.DESKTOP && | 179 root.role != RoleType.DESKTOP && |
| 145 root.role != RoleType.DIALOG) { | 180 root.role != RoleType.DIALOG) { |
| 146 root = root.parent; | 181 root = root.parent; |
| 147 } | 182 } |
| 148 | 183 |
| 149 var rect = rectFromPoints( | 184 var rect = rectFromPoints( |
| 150 this.mouseStart_.x, this.mouseStart_.y, | 185 this.mouseStart_.x, this.mouseStart_.y, |
| 151 evt.mouseX, evt.mouseY); | 186 this.mouseEnd_.x, this.mouseEnd_.y); |
| 152 var nodes = []; | 187 var nodes = []; |
| 153 this.findAllMatching_(root, rect, nodes); | 188 this.findAllMatching_(root, rect, nodes); |
| 154 this.startSpeechQueue_(nodes); | 189 this.startSpeechQueue_(nodes); |
| 155 }, | 190 }, |
| 156 | 191 |
| 157 /** | 192 /** |
| 193 * Set up event listeners for all mouse events. | |
| 194 */ | |
| 195 captureMouseEvents_: function() { | |
| 196 document.addEventListener('mousedown', this.onMouseDown_.bind(this)); | |
|
David Tseng
2017/05/07 06:10:27
Do these listeners need to be removed at some poin
dmazzoni
2017/05/10 19:43:19
We're tracking keys in the extension now, as sugge
| |
| 197 document.addEventListener('mouseup', this.onMouseUp_.bind(this)); | |
| 198 document.addEventListener('mousemove', this.onMouseMove_.bind(this)); | |
|
David Tseng
2017/05/07 06:10:27
nit: sort
dmazzoni
2017/05/10 19:43:19
Done.
| |
| 199 }, | |
| 200 | |
| 201 /** | |
| 158 * Called when the user cancels select-to-speak's capturing of mouse | 202 * Called when the user cancels select-to-speak's capturing of mouse |
| 159 * events (for example by releasing Search while the mouse is still down). | 203 * events (for example by releasing Search while the mouse is still down). |
| 160 * | 204 * |
| 161 * @param {!AutomationEvent} evt | 205 * @param {!AutomationEvent} evt |
| 162 */ | 206 */ |
| 163 onMouseCanceled_: function(evt) { | 207 onMouseCanceled_: function(evt) { |
| 164 this.down_ = false; | 208 this.down_ = false; |
| 165 chrome.accessibilityPrivate.setFocusRing([]); | 209 chrome.accessibilityPrivate.setFocusRing([]); |
| 166 chrome.tts.stop(); | 210 chrome.tts.stop(); |
| 167 }, | 211 }, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 this.voiceNameFromLocale_ = voices[0].voiceName; | 358 this.voiceNameFromLocale_ = voices[0].voiceName; |
| 315 | 359 |
| 316 chrome.storage.sync.get(['voice'], (function(prefs) { | 360 chrome.storage.sync.get(['voice'], (function(prefs) { |
| 317 if (!prefs['voice']) { | 361 if (!prefs['voice']) { |
| 318 chrome.storage.sync.set({'voice': voices[0].voiceName}); | 362 chrome.storage.sync.set({'voice': voices[0].voiceName}); |
| 319 } | 363 } |
| 320 }).bind(this)); | 364 }).bind(this)); |
| 321 }).bind(this)); | 365 }).bind(this)); |
| 322 } | 366 } |
| 323 }; | 367 }; |
| OLD | NEW |