OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "ash/sticky_keys/sticky_keys_controller.h" | 5 #include "ash/sticky_keys/sticky_keys_controller.h" |
6 | 6 |
7 #if defined(USE_X11) | 7 #if defined(USE_X11) |
8 #include <X11/extensions/XInput2.h> | 8 #include <X11/extensions/XInput2.h> |
9 #include <X11/Xlib.h> | 9 #include <X11/Xlib.h> |
10 #undef RootWindow | 10 #undef RootWindow |
11 #endif | 11 #endif |
12 | 12 |
| 13 #include "ash/sticky_keys/sticky_keys_overlay.h" |
13 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
14 #include "base/debug/stack_trace.h" | 15 #include "base/debug/stack_trace.h" |
15 #include "ui/aura/root_window.h" | 16 #include "ui/aura/root_window.h" |
16 #include "ui/aura/window.h" | 17 #include "ui/aura/window.h" |
17 #include "ui/aura/window_tracker.h" | 18 #include "ui/aura/window_tracker.h" |
18 #include "ui/events/event.h" | 19 #include "ui/events/event.h" |
19 #include "ui/events/keycodes/keyboard_code_conversion.h" | 20 #include "ui/events/keycodes/keyboard_code_conversion.h" |
20 | 21 |
21 namespace ash { | 22 namespace ash { |
22 | 23 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 DCHECK(target); | 83 DCHECK(target); |
83 target->GetDispatcher()->AsWindowTreeHostDelegate() | 84 target->GetDispatcher()->AsWindowTreeHostDelegate() |
84 ->OnHostScrollEvent(event); | 85 ->OnHostScrollEvent(event); |
85 } | 86 } |
86 | 87 |
87 } // namespace | 88 } // namespace |
88 | 89 |
89 /////////////////////////////////////////////////////////////////////////////// | 90 /////////////////////////////////////////////////////////////////////////////// |
90 // StickyKeys | 91 // StickyKeys |
91 StickyKeysController::StickyKeysController() | 92 StickyKeysController::StickyKeysController() |
92 : enabled_(false), | 93 : enabled_(false) { |
93 shift_sticky_key_( | |
94 new StickyKeysHandler(ui::EF_SHIFT_DOWN, | |
95 new StickyKeysHandlerDelegateImpl())), | |
96 alt_sticky_key_( | |
97 new StickyKeysHandler(ui::EF_ALT_DOWN, | |
98 new StickyKeysHandlerDelegateImpl())), | |
99 ctrl_sticky_key_( | |
100 new StickyKeysHandler(ui::EF_CONTROL_DOWN, | |
101 new StickyKeysHandlerDelegateImpl())) { | |
102 } | 94 } |
103 | 95 |
104 StickyKeysController::~StickyKeysController() { | 96 StickyKeysController::~StickyKeysController() { |
105 } | 97 } |
106 | 98 |
107 void StickyKeysController::Enable(bool enabled) { | 99 void StickyKeysController::Enable(bool enabled) { |
108 if (enabled_ != enabled) { | 100 if (enabled_ != enabled) { |
109 enabled_ = enabled; | 101 enabled_ = enabled; |
110 | 102 |
111 // Reset key handlers when activating sticky keys to ensure all | 103 // Reset key handlers when activating sticky keys to ensure all |
112 // the handlers' states are reset. | 104 // the handlers' states are reset. |
113 if (enabled_) { | 105 if (enabled_) { |
114 shift_sticky_key_.reset( | 106 shift_sticky_key_.reset( |
115 new StickyKeysHandler(ui::EF_SHIFT_DOWN, | 107 new StickyKeysHandler(ui::EF_SHIFT_DOWN, |
116 new StickyKeysHandlerDelegateImpl())); | 108 new StickyKeysHandlerDelegateImpl())); |
117 alt_sticky_key_.reset( | 109 alt_sticky_key_.reset( |
118 new StickyKeysHandler(ui::EF_ALT_DOWN, | 110 new StickyKeysHandler(ui::EF_ALT_DOWN, |
119 new StickyKeysHandlerDelegateImpl())); | 111 new StickyKeysHandlerDelegateImpl())); |
120 ctrl_sticky_key_.reset( | 112 ctrl_sticky_key_.reset( |
121 new StickyKeysHandler(ui::EF_CONTROL_DOWN, | 113 new StickyKeysHandler(ui::EF_CONTROL_DOWN, |
122 new StickyKeysHandlerDelegateImpl())); | 114 new StickyKeysHandlerDelegateImpl())); |
| 115 |
| 116 overlay_.reset(new StickyKeysOverlay()); |
| 117 } else if (overlay_.get()) { |
| 118 overlay_->Show(false); |
123 } | 119 } |
124 } | 120 } |
125 } | 121 } |
126 | 122 |
127 bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) { | 123 bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) { |
128 return shift_sticky_key_->HandleKeyEvent(event) || | 124 return shift_sticky_key_->HandleKeyEvent(event) || |
129 alt_sticky_key_->HandleKeyEvent(event) || | 125 alt_sticky_key_->HandleKeyEvent(event) || |
130 ctrl_sticky_key_->HandleKeyEvent(event); | 126 ctrl_sticky_key_->HandleKeyEvent(event); |
131 } | 127 } |
132 | 128 |
133 bool StickyKeysController::HandleMouseEvent(ui::MouseEvent* event) { | 129 bool StickyKeysController::HandleMouseEvent(ui::MouseEvent* event) { |
134 return shift_sticky_key_->HandleMouseEvent(event) || | 130 return shift_sticky_key_->HandleMouseEvent(event) || |
135 alt_sticky_key_->HandleMouseEvent(event) || | 131 alt_sticky_key_->HandleMouseEvent(event) || |
136 ctrl_sticky_key_->HandleMouseEvent(event); | 132 ctrl_sticky_key_->HandleMouseEvent(event); |
137 } | 133 } |
138 | 134 |
139 bool StickyKeysController::HandleScrollEvent(ui::ScrollEvent* event) { | 135 bool StickyKeysController::HandleScrollEvent(ui::ScrollEvent* event) { |
140 return shift_sticky_key_->HandleScrollEvent(event) || | 136 return shift_sticky_key_->HandleScrollEvent(event) || |
141 alt_sticky_key_->HandleScrollEvent(event) || | 137 alt_sticky_key_->HandleScrollEvent(event) || |
142 ctrl_sticky_key_->HandleScrollEvent(event); | 138 ctrl_sticky_key_->HandleScrollEvent(event); |
143 } | 139 } |
144 | 140 |
145 void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) { | 141 void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) { |
146 // Do not consume a translated key event which is generated by an IME. | 142 // Do not consume a translated key event which is generated by an IME. |
147 if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || | 143 if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || |
148 event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { | 144 event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { |
149 return; | 145 return; |
150 } | 146 } |
151 | 147 |
152 if (enabled_ && HandleKeyEvent(event)) | 148 if (enabled_) { |
153 event->StopPropagation(); | 149 if (HandleKeyEvent(event)) |
| 150 event->StopPropagation(); |
| 151 UpdateOverlay(); |
| 152 } |
154 } | 153 } |
155 | 154 |
156 void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) { | 155 void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) { |
157 if (enabled_ && HandleMouseEvent(event)) | 156 if (enabled_) { |
158 event->StopPropagation(); | 157 if (HandleMouseEvent(event)) |
| 158 event->StopPropagation(); |
| 159 UpdateOverlay(); |
| 160 } |
159 } | 161 } |
160 | 162 |
161 void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) { | 163 void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) { |
162 if (enabled_ && HandleScrollEvent(event)) | 164 if (enabled_) { |
163 event->StopPropagation(); | 165 if (HandleScrollEvent(event)) |
| 166 event->StopPropagation(); |
| 167 UpdateOverlay(); |
| 168 } |
| 169 } |
| 170 |
| 171 void StickyKeysController::UpdateOverlay() { |
| 172 overlay_->SetModifierKeyState( |
| 173 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state()); |
| 174 overlay_->SetModifierKeyState( |
| 175 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state()); |
| 176 overlay_->SetModifierKeyState( |
| 177 ui::EF_ALT_DOWN, alt_sticky_key_->current_state()); |
| 178 |
| 179 bool key_in_use = |
| 180 shift_sticky_key_->current_state() != STICKY_KEY_STATE_DISABLED || |
| 181 alt_sticky_key_->current_state() != STICKY_KEY_STATE_DISABLED || |
| 182 ctrl_sticky_key_->current_state() != STICKY_KEY_STATE_DISABLED; |
| 183 |
| 184 overlay_->Show(enabled_ && key_in_use); |
| 185 } |
| 186 |
| 187 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() { |
| 188 return overlay_.get(); |
164 } | 189 } |
165 | 190 |
166 /////////////////////////////////////////////////////////////////////////////// | 191 /////////////////////////////////////////////////////////////////////////////// |
167 // StickyKeysHandler | 192 // StickyKeysHandler |
168 StickyKeysHandler::StickyKeysHandler(ui::EventFlags target_modifier_flag, | 193 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag, |
169 StickyKeysHandlerDelegate* delegate) | 194 StickyKeysHandlerDelegate* delegate) |
170 : modifier_flag_(target_modifier_flag), | 195 : modifier_flag_(modifier_flag), |
171 current_state_(DISABLED), | 196 current_state_(STICKY_KEY_STATE_DISABLED), |
172 event_from_myself_(false), | 197 event_from_myself_(false), |
173 preparing_to_enable_(false), | 198 preparing_to_enable_(false), |
174 scroll_delta_(0), | 199 scroll_delta_(0), |
175 delegate_(delegate) { | 200 delegate_(delegate) { |
176 } | 201 } |
177 | 202 |
178 StickyKeysHandler::~StickyKeysHandler() { | 203 StickyKeysHandler::~StickyKeysHandler() { |
179 } | 204 } |
180 | 205 |
181 StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { | 206 StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { |
182 } | 207 } |
183 | 208 |
184 StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { | 209 StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { |
185 } | 210 } |
186 | 211 |
187 bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) { | 212 bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) { |
188 if (event_from_myself_) | 213 if (event_from_myself_) |
189 return false; // Do not handle self-generated key event. | 214 return false; // Do not handle self-generated key event. |
190 switch (current_state_) { | 215 switch (current_state_) { |
191 case DISABLED: | 216 case STICKY_KEY_STATE_DISABLED: |
192 return HandleDisabledState(event); | 217 return HandleDisabledState(event); |
193 case ENABLED: | 218 case STICKY_KEY_STATE_ENABLED: |
194 return HandleEnabledState(event); | 219 return HandleEnabledState(event); |
195 case LOCKED: | 220 case STICKY_KEY_STATE_LOCKED: |
196 return HandleLockedState(event); | 221 return HandleLockedState(event); |
197 } | 222 } |
198 NOTREACHED(); | 223 NOTREACHED(); |
199 return false; | 224 return false; |
200 } | 225 } |
201 | 226 |
202 bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { | 227 bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { |
203 if (ShouldModifyMouseEvent(event)) | 228 if (ShouldModifyMouseEvent(event)) |
204 preparing_to_enable_ = false; | 229 preparing_to_enable_ = false; |
205 | 230 |
206 if (event_from_myself_ || current_state_ == DISABLED | 231 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED |
207 || !ShouldModifyMouseEvent(event)) { | 232 || !ShouldModifyMouseEvent(event)) { |
208 return false; | 233 return false; |
209 } | 234 } |
210 DCHECK(current_state_ == ENABLED || current_state_ == LOCKED); | 235 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
| 236 current_state_ == STICKY_KEY_STATE_LOCKED); |
211 | 237 |
212 AppendModifier(event); | 238 AppendModifier(event); |
213 // Only disable on the mouse released event in normal, non-locked mode. | 239 // Only disable on the mouse released event in normal, non-locked mode. |
214 if (current_state_ == ENABLED && event->type() != ui::ET_MOUSE_PRESSED) { | 240 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
215 current_state_ = DISABLED; | 241 event->type() != ui::ET_MOUSE_PRESSED) { |
| 242 current_state_ = STICKY_KEY_STATE_DISABLED; |
216 DispatchEventAndReleaseModifier(event); | 243 DispatchEventAndReleaseModifier(event); |
217 return true; | 244 return true; |
218 } | 245 } |
219 | 246 |
220 return false; | 247 return false; |
221 } | 248 } |
222 | 249 |
223 bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { | 250 bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { |
224 preparing_to_enable_ = false; | 251 preparing_to_enable_ = false; |
225 if (event_from_myself_ || current_state_ == DISABLED) | 252 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED) |
226 return false; | 253 return false; |
227 DCHECK(current_state_ == ENABLED || current_state_ == LOCKED); | 254 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
| 255 current_state_ == STICKY_KEY_STATE_LOCKED); |
228 | 256 |
229 // We detect a direction change if the current |scroll_delta_| is assigned | 257 // We detect a direction change if the current |scroll_delta_| is assigned |
230 // and the offset of the current scroll event has the opposing sign. | 258 // and the offset of the current scroll event has the opposing sign. |
231 bool direction_changed = false; | 259 bool direction_changed = false; |
232 if (current_state_ == ENABLED && event->type() == ui::ET_SCROLL) { | 260 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
| 261 event->type() == ui::ET_SCROLL) { |
233 int offset = event->y_offset(); | 262 int offset = event->y_offset(); |
234 if (scroll_delta_) | 263 if (scroll_delta_) |
235 direction_changed = offset * scroll_delta_ <= 0; | 264 direction_changed = offset * scroll_delta_ <= 0; |
236 scroll_delta_ = offset; | 265 scroll_delta_ = offset; |
237 } | 266 } |
238 | 267 |
239 if (!direction_changed) | 268 if (!direction_changed) |
240 AppendModifier(event); | 269 AppendModifier(event); |
241 | 270 |
242 // We want to modify all the scroll events in the scroll sequence, which ends | 271 // We want to modify all the scroll events in the scroll sequence, which ends |
243 // with a fling start event. We also stop when the scroll sequence changes | 272 // with a fling start event. We also stop when the scroll sequence changes |
244 // direction. | 273 // direction. |
245 if (current_state_ == ENABLED && | 274 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
246 (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { | 275 (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { |
247 current_state_ = DISABLED; | 276 current_state_ = STICKY_KEY_STATE_DISABLED; |
248 scroll_delta_ = 0; | 277 scroll_delta_ = 0; |
249 DispatchEventAndReleaseModifier(event); | 278 DispatchEventAndReleaseModifier(event); |
250 return true; | 279 return true; |
251 } | 280 } |
252 | 281 |
253 return false; | 282 return false; |
254 } | 283 } |
255 | 284 |
256 StickyKeysHandler::KeyEventType | 285 StickyKeysHandler::KeyEventType |
257 StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { | 286 StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { |
(...skipping 22 matching lines...) Expand all Loading... |
280 return event->type() == ui::ET_KEY_PRESSED ? | 309 return event->type() == ui::ET_KEY_PRESSED ? |
281 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; | 310 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; |
282 } | 311 } |
283 | 312 |
284 bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { | 313 bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { |
285 switch (TranslateKeyEvent(event)) { | 314 switch (TranslateKeyEvent(event)) { |
286 case TARGET_MODIFIER_UP: | 315 case TARGET_MODIFIER_UP: |
287 if (preparing_to_enable_) { | 316 if (preparing_to_enable_) { |
288 preparing_to_enable_ = false; | 317 preparing_to_enable_ = false; |
289 scroll_delta_ = 0; | 318 scroll_delta_ = 0; |
290 current_state_ = ENABLED; | 319 current_state_ = STICKY_KEY_STATE_ENABLED; |
291 modifier_up_event_.reset(new ui::KeyEvent(*event)); | 320 modifier_up_event_.reset(new ui::KeyEvent(*event)); |
292 return true; | 321 return true; |
293 } | 322 } |
294 return false; | 323 return false; |
295 case TARGET_MODIFIER_DOWN: | 324 case TARGET_MODIFIER_DOWN: |
296 preparing_to_enable_ = true; | 325 preparing_to_enable_ = true; |
297 return false; | 326 return false; |
298 case NORMAL_KEY_DOWN: | 327 case NORMAL_KEY_DOWN: |
299 preparing_to_enable_ = false; | 328 preparing_to_enable_ = false; |
300 return false; | 329 return false; |
301 case NORMAL_KEY_UP: | 330 case NORMAL_KEY_UP: |
302 case OTHER_MODIFIER_DOWN: | 331 case OTHER_MODIFIER_DOWN: |
303 case OTHER_MODIFIER_UP: | 332 case OTHER_MODIFIER_UP: |
304 return false; | 333 return false; |
305 } | 334 } |
306 NOTREACHED(); | 335 NOTREACHED(); |
307 return false; | 336 return false; |
308 } | 337 } |
309 | 338 |
310 bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { | 339 bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { |
311 switch (TranslateKeyEvent(event)) { | 340 switch (TranslateKeyEvent(event)) { |
312 case NORMAL_KEY_UP: | 341 case NORMAL_KEY_UP: |
313 case TARGET_MODIFIER_DOWN: | 342 case TARGET_MODIFIER_DOWN: |
314 return true; | 343 return true; |
315 case TARGET_MODIFIER_UP: | 344 case TARGET_MODIFIER_UP: |
316 current_state_ = LOCKED; | 345 current_state_ = STICKY_KEY_STATE_LOCKED; |
317 modifier_up_event_.reset(); | 346 modifier_up_event_.reset(); |
318 return true; | 347 return true; |
319 case NORMAL_KEY_DOWN: { | 348 case NORMAL_KEY_DOWN: { |
320 current_state_ = DISABLED; | 349 current_state_ = STICKY_KEY_STATE_DISABLED; |
321 AppendModifier(event); | 350 AppendModifier(event); |
322 DispatchEventAndReleaseModifier(event); | 351 DispatchEventAndReleaseModifier(event); |
323 return true; | 352 return true; |
324 } | 353 } |
325 case OTHER_MODIFIER_DOWN: | 354 case OTHER_MODIFIER_DOWN: |
326 case OTHER_MODIFIER_UP: | 355 case OTHER_MODIFIER_UP: |
327 return false; | 356 return false; |
328 } | 357 } |
329 NOTREACHED(); | 358 NOTREACHED(); |
330 return false; | 359 return false; |
331 } | 360 } |
332 | 361 |
333 bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { | 362 bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { |
334 switch (TranslateKeyEvent(event)) { | 363 switch (TranslateKeyEvent(event)) { |
335 case TARGET_MODIFIER_DOWN: | 364 case TARGET_MODIFIER_DOWN: |
336 return true; | 365 return true; |
337 case TARGET_MODIFIER_UP: | 366 case TARGET_MODIFIER_UP: |
338 current_state_ = DISABLED; | 367 current_state_ = STICKY_KEY_STATE_DISABLED; |
339 return false; | 368 return false; |
340 case NORMAL_KEY_DOWN: | 369 case NORMAL_KEY_DOWN: |
341 case NORMAL_KEY_UP: | 370 case NORMAL_KEY_UP: |
342 AppendModifier(event); | 371 AppendModifier(event); |
343 return false; | 372 return false; |
344 case OTHER_MODIFIER_DOWN: | 373 case OTHER_MODIFIER_DOWN: |
345 case OTHER_MODIFIER_UP: | 374 case OTHER_MODIFIER_UP: |
346 return false; | 375 return false; |
347 } | 376 } |
348 NOTREACHED(); | 377 NOTREACHED(); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 &xievent->mods.effective)); | 466 &xievent->mods.effective)); |
438 } | 467 } |
439 } | 468 } |
440 #elif defined(USE_OZONE) | 469 #elif defined(USE_OZONE) |
441 NOTIMPLEMENTED() << "Modifier key is not handled"; | 470 NOTIMPLEMENTED() << "Modifier key is not handled"; |
442 #endif | 471 #endif |
443 event->set_flags(event->flags() | modifier_flag_); | 472 event->set_flags(event->flags() | modifier_flag_); |
444 } | 473 } |
445 | 474 |
446 } // namespace ash | 475 } // namespace ash |
OLD | NEW |