OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/chromeos/events/event_rewriter.h" | 5 #include "chrome/browser/chromeos/events/event_rewriter.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "ash/sticky_keys/sticky_keys_controller.h" | |
10 #include "ash/wm/window_state.h" | 9 #include "ash/wm/window_state.h" |
11 #include "ash/wm/window_util.h" | 10 #include "ash/wm/window_util.h" |
12 #include "base/command_line.h" | 11 #include "base/command_line.h" |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "base/macros.h" | |
15 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
16 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
17 #include "base/sys_info.h" | 15 #include "base/sys_info.h" |
18 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" | 16 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" |
19 #include "chrome/browser/chromeos/login/users/user_manager.h" | 17 #include "chrome/browser/chromeos/login/users/user_manager.h" |
20 #include "chrome/browser/profiles/profile_manager.h" | 18 #include "chrome/browser/profiles/profile_manager.h" |
21 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
22 #include "chromeos/chromeos_switches.h" | 20 #include "chromeos/chromeos_switches.h" |
23 #include "chromeos/ime/ime_keyboard.h" | 21 #include "chromeos/ime/ime_keyboard.h" |
24 #include "chromeos/ime/input_method_manager.h" | 22 #include "chromeos/ime/input_method_manager.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 }; | 146 }; |
149 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) { | 147 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) { |
150 if (ui_flags & flags[i].ui) | 148 if (ui_flags & flags[i].ui) |
151 *x_flags |= flags[i].x; | 149 *x_flags |= flags[i].x; |
152 else | 150 else |
153 *x_flags &= ~flags[i].x; | 151 *x_flags &= ~flags[i].x; |
154 } | 152 } |
155 } | 153 } |
156 #endif | 154 #endif |
157 | 155 |
158 bool IsSendEvent(const ui::Event& event) { | |
159 #if defined(USE_X11) | |
160 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See | |
161 // crbug.com/136465. | |
162 XEvent* xev = event.native_event(); | |
163 if (xev && xev->xany.send_event) | |
164 return true; | |
165 #endif | |
166 return false; | |
167 } | |
168 | |
169 } // namespace | 156 } // namespace |
170 | 157 |
171 EventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller) | 158 EventRewriter::EventRewriter() |
172 : last_device_id_(kBadDeviceId), | 159 : last_device_id_(kBadDeviceId), |
173 ime_keyboard_for_testing_(NULL), | 160 ime_keyboard_for_testing_(NULL), |
174 pref_service_for_testing_(NULL), | 161 pref_service_for_testing_(NULL) { |
175 sticky_keys_controller_(sticky_keys_controller) { | |
176 #if defined(USE_X11) | 162 #if defined(USE_X11) |
177 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); | 163 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); |
178 if (base::SysInfo::IsRunningOnChromeOS()) { | 164 if (base::SysInfo::IsRunningOnChromeOS()) { |
179 XInputHierarchyChangedEventListener::GetInstance()->AddObserver(this); | 165 XInputHierarchyChangedEventListener::GetInstance()->AddObserver(this); |
180 } | 166 } |
181 #endif | 167 #endif |
182 } | 168 } |
183 | 169 |
184 EventRewriter::~EventRewriter() { | 170 EventRewriter::~EventRewriter() { |
185 #if defined(USE_X11) | 171 #if defined(USE_X11) |
(...skipping 11 matching lines...) Expand all Loading... |
197 } | 183 } |
198 | 184 |
199 void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event, | 185 void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event, |
200 int* flags) { | 186 int* flags) { |
201 RewriteLocatedEvent(event, flags); | 187 RewriteLocatedEvent(event, flags); |
202 } | 188 } |
203 | 189 |
204 ui::EventRewriteStatus EventRewriter::RewriteEvent( | 190 ui::EventRewriteStatus EventRewriter::RewriteEvent( |
205 const ui::Event& event, | 191 const ui::Event& event, |
206 scoped_ptr<ui::Event>* rewritten_event) { | 192 scoped_ptr<ui::Event>* rewritten_event) { |
207 if ((event.type() == ui::ET_KEY_PRESSED) || | 193 #if defined(USE_X11) |
208 (event.type() == ui::ET_KEY_RELEASED)) { | 194 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See |
209 return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event), | 195 // crbug.com/136465. |
210 rewritten_event); | 196 XEvent* xev = event.native_event(); |
| 197 if (xev && xev->xany.send_event) |
| 198 return ui::EVENT_REWRITE_CONTINUE; |
| 199 #endif |
| 200 switch (event.type()) { |
| 201 case ui::ET_KEY_PRESSED: |
| 202 case ui::ET_KEY_RELEASED: |
| 203 return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event), |
| 204 rewritten_event); |
| 205 case ui::ET_MOUSE_PRESSED: |
| 206 case ui::ET_MOUSE_RELEASED: |
| 207 return RewriteMouseEvent(static_cast<const ui::MouseEvent&>(event), |
| 208 rewritten_event); |
| 209 case ui::ET_TOUCH_PRESSED: |
| 210 case ui::ET_TOUCH_RELEASED: |
| 211 return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event), |
| 212 rewritten_event); |
| 213 default: |
| 214 return ui::EVENT_REWRITE_CONTINUE; |
211 } | 215 } |
212 if (event.IsMouseEvent()) { | 216 NOTREACHED(); |
213 return RewriteMouseEvent(static_cast<const ui::MouseEvent&>(event), | |
214 rewritten_event); | |
215 } | |
216 if ((event.type() == ui::ET_TOUCH_PRESSED) || | |
217 (event.type() == ui::ET_TOUCH_RELEASED)) { | |
218 return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event), | |
219 rewritten_event); | |
220 } | |
221 if (event.IsScrollEvent()) { | |
222 return RewriteScrollEvent(static_cast<const ui::ScrollEvent&>(event), | |
223 rewritten_event); | |
224 } | |
225 return ui::EVENT_REWRITE_CONTINUE; | |
226 } | 217 } |
227 | 218 |
228 ui::EventRewriteStatus EventRewriter::NextDispatchEvent( | 219 ui::EventRewriteStatus EventRewriter::NextDispatchEvent( |
229 const ui::Event& last_event, | 220 const ui::Event& last_event, |
230 scoped_ptr<ui::Event>* new_event) { | 221 scoped_ptr<ui::Event>* new_event) { |
231 if (sticky_keys_controller_) { | |
232 // In the case of sticky keys, we know what the events obtained here are: | |
233 // modifier key releases that match the ones previously discarded. So, we | |
234 // know that they don't have to be passed through the post-sticky key | |
235 // rewriting phases, |RewriteExtendedKeys()| and |RewriteFunctionKeys()|, | |
236 // because those phases do nothing with modifier key releases. | |
237 return sticky_keys_controller_->NextDispatchEvent(new_event); | |
238 } | |
239 NOTREACHED(); | 222 NOTREACHED(); |
240 return ui::EVENT_REWRITE_CONTINUE; | 223 return ui::EVENT_REWRITE_CONTINUE; |
241 } | 224 } |
242 | 225 |
243 #if defined(USE_X11) | 226 #if defined(USE_X11) |
244 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) { | 227 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) { |
245 if (!device_id_to_type_.count(device_id)) { | 228 if (!device_id_to_type_.count(device_id)) { |
246 // |device_id| is unknown. This means the device was connected before | 229 // |device_id| is unknown. This means the device was connected before |
247 // booting the OS. Query the name of the device and add it to the map. | 230 // booting the OS. Query the name of the device and add it to the map. |
248 DeviceAdded(device_id); | 231 DeviceAdded(device_id); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags; | 326 remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags; |
344 return true; | 327 return true; |
345 } | 328 } |
346 return false; | 329 return false; |
347 } | 330 } |
348 | 331 |
349 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( | 332 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( |
350 const ui::KeyEvent& key_event, | 333 const ui::KeyEvent& key_event, |
351 scoped_ptr<ui::Event>* rewritten_event) { | 334 scoped_ptr<ui::Event>* rewritten_event) { |
352 MutableKeyState state = {key_event.flags(), key_event.key_code()}; | 335 MutableKeyState state = {key_event.flags(), key_event.key_code()}; |
353 bool is_send_event = IsSendEvent(key_event); | 336 RewriteModifierKeys(key_event, &state); |
354 if (!is_send_event) { | 337 RewriteNumPadKeys(key_event, &state); |
355 RewriteModifierKeys(key_event, &state); | 338 RewriteExtendedKeys(key_event, &state); |
356 RewriteNumPadKeys(key_event, &state); | 339 RewriteFunctionKeys(key_event, &state); |
357 } | |
358 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; | |
359 if (sticky_keys_controller_) { | |
360 status = sticky_keys_controller_->RewriteKeyEvent( | |
361 key_event, state.key_code, &state.flags); | |
362 if (status == ui::EVENT_REWRITE_DISCARD) | |
363 return ui::EVENT_REWRITE_DISCARD; | |
364 } | |
365 if (!is_send_event) { | |
366 RewriteExtendedKeys(key_event, &state); | |
367 RewriteFunctionKeys(key_event, &state); | |
368 } | |
369 if ((key_event.flags() == state.flags) && | 340 if ((key_event.flags() == state.flags) && |
370 (key_event.key_code() == state.key_code) && | 341 (key_event.key_code() == state.key_code)) { |
371 (status == ui::EVENT_REWRITE_CONTINUE)) { | |
372 return ui::EVENT_REWRITE_CONTINUE; | 342 return ui::EVENT_REWRITE_CONTINUE; |
373 } | 343 } |
374 // Sticky keys may have returned a result other than |EVENT_REWRITE_CONTINUE|, | |
375 // in which case we need to preserve that return status. Alternatively, we | |
376 // might be here because key_event changed, in which case we need to return | |
377 // |EVENT_REWRITE_REWRITTEN|. | |
378 if (status == ui::EVENT_REWRITE_CONTINUE) | |
379 status = ui::EVENT_REWRITE_REWRITTEN; | |
380 ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event); | 344 ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event); |
381 rewritten_event->reset(rewritten_key_event); | 345 rewritten_event->reset(rewritten_key_event); |
382 rewritten_key_event->set_flags(state.flags); | 346 rewritten_key_event->set_flags(state.flags); |
383 rewritten_key_event->set_key_code(state.key_code); | 347 rewritten_key_event->set_key_code(state.key_code); |
384 rewritten_key_event->set_character( | 348 rewritten_key_event->set_character( |
385 ui::GetCharacterFromKeyCode(state.key_code, state.flags)); | 349 ui::GetCharacterFromKeyCode(state.key_code, state.flags)); |
386 rewritten_key_event->NormalizeFlags(); | 350 rewritten_key_event->NormalizeFlags(); |
387 #if defined(USE_X11) | 351 #if defined(USE_X11) |
388 XEvent* xev = rewritten_key_event->native_event(); | 352 XEvent* xev = rewritten_key_event->native_event(); |
389 if (xev) { | 353 if (xev) { |
390 CHECK(xev->type == KeyPress || xev->type == KeyRelease); | 354 CHECK(xev->type == KeyPress || xev->type == KeyRelease); |
391 XKeyEvent* xkey = &(xev->xkey); | 355 XKeyEvent* xkey = &(xev->xkey); |
392 UpdateX11EventMask(rewritten_key_event->flags(), &xkey->state); | 356 UpdateX11EventMask(rewritten_key_event->flags(), &xkey->state); |
393 xkey->keycode = | 357 xkey->keycode = |
394 XKeysymToKeycode(gfx::GetXDisplay(), | 358 XKeysymToKeycode(gfx::GetXDisplay(), |
395 ui::XKeysymForWindowsKeyCode( | 359 ui::XKeysymForWindowsKeyCode( |
396 state.key_code, state.flags & ui::EF_SHIFT_DOWN)); | 360 state.key_code, state.flags & ui::EF_SHIFT_DOWN)); |
397 } | 361 } |
398 #endif | 362 #endif |
399 return status; | 363 return ui::EVENT_REWRITE_REWRITTEN; |
400 } | 364 } |
401 | 365 |
402 ui::EventRewriteStatus EventRewriter::RewriteMouseEvent( | 366 ui::EventRewriteStatus EventRewriter::RewriteMouseEvent( |
403 const ui::MouseEvent& mouse_event, | 367 const ui::MouseEvent& mouse_event, |
404 scoped_ptr<ui::Event>* rewritten_event) { | 368 scoped_ptr<ui::Event>* rewritten_event) { |
405 int flags = mouse_event.flags(); | 369 int flags = mouse_event.flags(); |
406 if ((mouse_event.type() == ui::ET_MOUSE_PRESSED) || | 370 RewriteLocatedEvent(mouse_event, &flags); |
407 (mouse_event.type() == ui::ET_MOUSE_RELEASED)) { | 371 if (mouse_event.flags() == flags) |
408 RewriteLocatedEvent(mouse_event, &flags); | |
409 } | |
410 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; | |
411 if (sticky_keys_controller_) | |
412 status = sticky_keys_controller_->RewriteMouseEvent(mouse_event, &flags); | |
413 if ((mouse_event.flags() == flags) && | |
414 (status == ui::EVENT_REWRITE_CONTINUE)) { | |
415 return ui::EVENT_REWRITE_CONTINUE; | 372 return ui::EVENT_REWRITE_CONTINUE; |
416 } | |
417 if (status == ui::EVENT_REWRITE_CONTINUE) | |
418 status = ui::EVENT_REWRITE_REWRITTEN; | |
419 ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event); | 373 ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event); |
420 rewritten_event->reset(rewritten_mouse_event); | 374 rewritten_event->reset(rewritten_mouse_event); |
421 rewritten_mouse_event->set_flags(flags); | 375 rewritten_mouse_event->set_flags(flags); |
422 #if defined(USE_X11) | 376 #if defined(USE_X11) |
423 XEvent* xev = rewritten_mouse_event->native_event(); | 377 XEvent* xev = rewritten_mouse_event->native_event(); |
424 if (xev) { | 378 if (xev) { |
425 switch (xev->type) { | 379 switch (xev->type) { |
426 case ButtonPress: | 380 case ButtonPress: |
427 case ButtonRelease: { | 381 case ButtonRelease: { |
428 XButtonEvent* xbutton = &(xev->xbutton); | 382 XButtonEvent* xbutton = &(xev->xbutton); |
429 UpdateX11EventMask(rewritten_mouse_event->flags(), &xbutton->state); | 383 UpdateX11EventMask(rewritten_mouse_event->flags(), &xbutton->state); |
430 break; | 384 break; |
431 } | 385 } |
432 case GenericEvent: { | 386 case GenericEvent: { |
433 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 387 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
434 CHECK(xievent->evtype == XI_ButtonPress || | 388 CHECK(xievent->evtype == XI_ButtonPress || |
435 xievent->evtype == XI_ButtonRelease); | 389 xievent->evtype == XI_ButtonRelease); |
436 UpdateX11EventMask( | 390 UpdateX11EventMask( |
437 rewritten_mouse_event->flags(), | 391 rewritten_mouse_event->flags(), |
438 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); | 392 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
439 break; | 393 break; |
440 } | 394 } |
441 default: | 395 default: |
442 NOTREACHED(); | 396 NOTREACHED(); |
443 } | 397 } |
444 } | 398 } |
445 #endif | 399 #endif |
446 return status; | 400 return ui::EVENT_REWRITE_REWRITTEN; |
447 } | 401 } |
448 | 402 |
449 ui::EventRewriteStatus EventRewriter::RewriteTouchEvent( | 403 ui::EventRewriteStatus EventRewriter::RewriteTouchEvent( |
450 const ui::TouchEvent& touch_event, | 404 const ui::TouchEvent& touch_event, |
451 scoped_ptr<ui::Event>* rewritten_event) { | 405 scoped_ptr<ui::Event>* rewritten_event) { |
452 int flags = touch_event.flags(); | 406 int flags = touch_event.flags(); |
453 RewriteLocatedEvent(touch_event, &flags); | 407 RewriteLocatedEvent(touch_event, &flags); |
454 if (touch_event.flags() == flags) | 408 if (touch_event.flags() == flags) |
455 return ui::EVENT_REWRITE_CONTINUE; | 409 return ui::EVENT_REWRITE_CONTINUE; |
456 ui::TouchEvent* rewritten_touch_event = new ui::TouchEvent(touch_event); | 410 ui::TouchEvent* rewritten_touch_event = new ui::TouchEvent(touch_event); |
457 rewritten_event->reset(rewritten_touch_event); | 411 rewritten_event->reset(rewritten_touch_event); |
458 rewritten_touch_event->set_flags(flags); | 412 rewritten_touch_event->set_flags(flags); |
459 #if defined(USE_X11) | 413 #if defined(USE_X11) |
460 XEvent* xev = rewritten_touch_event->native_event(); | 414 XEvent* xev = rewritten_touch_event->native_event(); |
461 if (xev) { | 415 if (xev) { |
462 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 416 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
463 if (xievent) { | 417 if (xievent) { |
464 UpdateX11EventMask( | 418 UpdateX11EventMask( |
465 rewritten_touch_event->flags(), | 419 rewritten_touch_event->flags(), |
466 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); | 420 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
467 } | 421 } |
468 } | 422 } |
469 #endif | 423 #endif |
470 return ui::EVENT_REWRITE_REWRITTEN; | 424 return ui::EVENT_REWRITE_REWRITTEN; |
471 } | 425 } |
472 | 426 |
473 ui::EventRewriteStatus EventRewriter::RewriteScrollEvent( | |
474 const ui::ScrollEvent& scroll_event, | |
475 scoped_ptr<ui::Event>* rewritten_event) { | |
476 int flags = scroll_event.flags(); | |
477 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; | |
478 if (sticky_keys_controller_) | |
479 status = sticky_keys_controller_->RewriteScrollEvent(scroll_event, &flags); | |
480 if (status == ui::EVENT_REWRITE_CONTINUE) | |
481 return status; | |
482 ui::ScrollEvent* rewritten_scroll_event = new ui::ScrollEvent(scroll_event); | |
483 rewritten_event->reset(rewritten_scroll_event); | |
484 rewritten_scroll_event->set_flags(flags); | |
485 #if defined(USE_X11) | |
486 XEvent* xev = rewritten_scroll_event->native_event(); | |
487 if (xev) { | |
488 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
489 if (xievent) { | |
490 UpdateX11EventMask( | |
491 rewritten_scroll_event->flags(), | |
492 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); | |
493 } | |
494 } | |
495 #endif | |
496 return status; | |
497 } | |
498 | |
499 void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event, | 427 void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event, |
500 MutableKeyState* state) { | 428 MutableKeyState* state) { |
501 DCHECK(key_event.type() == ui::ET_KEY_PRESSED || | 429 DCHECK(key_event.type() == ui::ET_KEY_PRESSED || |
502 key_event.type() == ui::ET_KEY_RELEASED); | 430 key_event.type() == ui::ET_KEY_RELEASED); |
503 | 431 |
504 // Do nothing if we have just logged in as guest but have not restarted chrome | 432 // Do nothing if we have just logged in as guest but have not restarted chrome |
505 // process yet (so we are still on the login screen). In this situations we | 433 // process yet (so we are still on the login screen). In this situations we |
506 // have no user profile so can not do anything useful. | 434 // have no user profile so can not do anything useful. |
507 // Note that currently, unlike other accounts, when user logs in as guest, we | 435 // Note that currently, unlike other accounts, when user logs in as guest, we |
508 // restart chrome process. In future this is to be changed. | 436 // restart chrome process. In future this is to be changed. |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 | 814 |
887 XIFreeDeviceInfo(device_info); | 815 XIFreeDeviceInfo(device_info); |
888 } | 816 } |
889 | 817 |
890 void EventRewriter::DeviceRemoved(int device_id) { | 818 void EventRewriter::DeviceRemoved(int device_id) { |
891 device_id_to_type_.erase(device_id); | 819 device_id_to_type_.erase(device_id); |
892 } | 820 } |
893 #endif | 821 #endif |
894 | 822 |
895 } // namespace chromeos | 823 } // namespace chromeos |
OLD | NEW |