Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: chrome/browser/ui/views/ash/key_rewriter.cc

Issue 10756003: Apply Ash's key rewriter to an aura::MouseEvent so that Modifler+Click is handled correctly (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ui/views/ash/key_rewriter.h" 5 #include "chrome/browser/ui/views/ash/key_rewriter.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "ash/shell.h" 9 #include "ash/shell.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 const ash::KeyRewriterDelegate::Action kActionRewrite = 182 const ash::KeyRewriterDelegate::Action kActionRewrite =
183 ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; 183 ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT;
184 if (!event->HasNativeEvent()) { 184 if (!event->HasNativeEvent()) {
185 // Do not handle a fabricated event generated by tests. 185 // Do not handle a fabricated event generated by tests.
186 return kActionRewrite; 186 return kActionRewrite;
187 } 187 }
188 Rewrite(event); 188 Rewrite(event);
189 return kActionRewrite; // Do not drop the event. 189 return kActionRewrite; // Do not drop the event.
190 } 190 }
191 191
192 ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterLocatedEvent(
193 aura::LocatedEvent* event) {
194 const ash::KeyRewriterDelegate::Action kActionRewrite =
195 ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT;
196 if (!event->HasNativeEvent()) {
197 // Do not handle a fabricated event generated by tests.
198 return kActionRewrite;
199 }
200 RewriteLocatedEvent(event);
201 return kActionRewrite;
Daniel Erat 2012/07/09 18:18:28 nit: just simplify this to three lines? ... KeyRe
Yusuke Sato 2012/07/09 20:36:50 Done.
202 }
203
192 void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { 204 void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) {
193 #if defined(OS_CHROMEOS) 205 #if defined(OS_CHROMEOS)
194 RefreshKeycodes(); 206 RefreshKeycodes();
195 #endif 207 #endif
196 } 208 }
197 209
198 #if defined(OS_CHROMEOS) 210 #if defined(OS_CHROMEOS)
199 void KeyRewriter::DeviceAdded(int device_id) { 211 void KeyRewriter::DeviceAdded(int device_id) {
200 DCHECK_NE(XIAllDevices, device_id); 212 DCHECK_NE(XIAllDevices, device_id);
201 DCHECK_NE(XIAllMasterDevices, device_id); 213 DCHECK_NE(XIAllMasterDevices, device_id);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 device_id_to_type_.find(last_device_id_); 358 device_id_to_type_.find(last_device_id_);
347 if (iter == device_id_to_type_.end()) { 359 if (iter == device_id_to_type_.end()) {
348 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; 360 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown.";
349 return false; 361 return false;
350 } 362 }
351 363
352 const DeviceType type = iter->second; 364 const DeviceType type = iter->second;
353 return type == kDeviceAppleKeyboard; 365 return type == kDeviceAppleKeyboard;
354 } 366 }
355 367
368 void KeyRewriter::GetRemappedModifierMasks(
369 int original_flags,
370 unsigned int original_native_modifiers,
371 int* remapped_flags,
372 unsigned int* remapped_native_modifiers) const {
373 #if defined(OS_CHROMEOS)
374 // TODO(glotov): remove the following condition when we do not restart chrome
375 // when user logs in as guest. See Rewrite() for details.
376 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
377 chromeos::BaseLoginDisplayHost::default_host()) {
378 return;
379 }
380
381 const PrefService* pref_service =
382 pref_service_ ? pref_service_ : GetPrefService();
383 if (!pref_service)
384 return;
385
386 for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) {
387 if (original_native_modifiers &
388 kModifierFlagToPrefName[i].native_modifier) {
389 const ModifierRemapping* remapped_key =
390 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service);
391 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
392 if (IsAppleKeyboard() &&
393 (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) {
394 remapped_key = kModifierRemappingCtrl;
395 }
396 if (remapped_key) {
397 *remapped_flags |= remapped_key->flag;
398 *remapped_native_modifiers |= remapped_key->native_modifier;
399 } else {
400 *remapped_flags |= kModifierFlagToPrefName[i].flag;
401 *remapped_native_modifiers |=
402 kModifierFlagToPrefName[i].native_modifier;
403 }
404 }
405 }
406
407 *remapped_flags =
408 (original_flags & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) |
409 *remapped_flags;
410 *remapped_native_modifiers =
411 (original_native_modifiers & ~(Mod4Mask | ControlMask | Mod1Mask)) |
412 *remapped_native_modifiers;
413 #endif
414 }
415
356 bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) { 416 bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) {
357 // Do nothing if we have just logged in as guest but have not restarted chrome 417 // Do nothing if we have just logged in as guest but have not restarted chrome
358 // process yet (so we are still on the login screen). In this situations we 418 // process yet (so we are still on the login screen). In this situations we
359 // have no user profile so can not do anything useful. 419 // have no user profile so can not do anything useful.
360 // Note that currently, unlike other accounts, when user logs in as guest, we 420 // Note that currently, unlike other accounts, when user logs in as guest, we
361 // restart chrome process. In future this is to be changed. 421 // restart chrome process. In future this is to be changed.
362 // TODO(glotov): remove the following condition when we do not restart chrome 422 // TODO(glotov): remove the following condition when we do not restart chrome
363 // when user logs in as guest. 423 // when user logs in as guest.
364 #if defined(OS_CHROMEOS) 424 #if defined(OS_CHROMEOS)
365 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && 425 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
366 chromeos::BaseLoginDisplayHost::default_host()) 426 chromeos::BaseLoginDisplayHost::default_host())
367 return false; 427 return false;
368 #endif // defined(OS_CHROMEOS) 428 #endif // defined(OS_CHROMEOS)
369 const PrefService* pref_service = 429 const PrefService* pref_service =
370 pref_service_ ? pref_service_ : GetPrefService(); 430 pref_service_ ? pref_service_ : GetPrefService();
371 if (!pref_service) 431 if (!pref_service)
372 return false; 432 return false;
373 433
374 #if defined(OS_CHROMEOS) 434 #if defined(OS_CHROMEOS)
375 DCHECK_EQ(chromeos::input_method::kControlKey, 435 DCHECK_EQ(chromeos::input_method::kControlKey,
376 kModifierRemappingCtrl->remap_to); 436 kModifierRemappingCtrl->remap_to);
377 437
378 XEvent* xev = event->native_event(); 438 XEvent* xev = event->native_event();
379 XKeyEvent* xkey = &(xev->xkey); 439 XKeyEvent* xkey = &(xev->xkey);
380 KeySym keysym = XLookupKeysym(xkey, 0); 440 KeySym keysym = XLookupKeysym(xkey, 0);
381 441
382 ui::KeyboardCode remapped_keycode = event->key_code(); 442 ui::KeyboardCode remapped_keycode = event->key_code();
383 KeyCode remapped_native_keycode = xkey->keycode; 443 KeyCode remapped_native_keycode = xkey->keycode;
384 int remapped_flags = 0;
385 unsigned int remapped_native_modifiers = 0U;
386 444
387 // First, remap |keysym|. 445 // First, remap |keysym|.
388 const char* pref_name = NULL; 446 const char* pref_name = NULL;
389 switch (keysym) { 447 switch (keysym) {
390 case XK_Super_L: 448 case XK_Super_L:
391 case XK_Super_R: 449 case XK_Super_R:
392 pref_name = prefs::kLanguageXkbRemapSearchKeyTo; 450 pref_name = prefs::kLanguageXkbRemapSearchKeyTo;
393 break; 451 break;
394 case XK_Control_L: 452 case XK_Control_L:
395 case XK_Control_R: 453 case XK_Control_R:
(...skipping 17 matching lines...) Expand all
413 if (remapped_key) { 471 if (remapped_key) {
414 remapped_keycode = remapped_key->keycode; 472 remapped_keycode = remapped_key->keycode;
415 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) + 473 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) +
416 (IsRight(keysym) ? (1 << 0) : 0); 474 (IsRight(keysym) ? (1 << 0) : 0);
417 const KeySym native_keysym = remapped_key->native_keysyms[level]; 475 const KeySym native_keysym = remapped_key->native_keysyms[level];
418 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym); 476 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
419 } 477 }
420 } 478 }
421 479
422 // Next, remap modifier bits. 480 // Next, remap modifier bits.
423 for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) { 481 int remapped_flags = 0;
424 if (xkey->state & kModifierFlagToPrefName[i].native_modifier) { 482 unsigned int remapped_native_modifiers = 0U;
425 const ModifierRemapping* remapped_key = 483 GetRemappedModifierMasks(event->flags(), xkey->state,
426 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service); 484 &remapped_flags, &remapped_native_modifiers);
427 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
428 if (IsAppleKeyboard() &&
429 (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) {
430 remapped_key = kModifierRemappingCtrl;
431 }
432 if (remapped_key) {
433 remapped_flags |= remapped_key->flag;
434 remapped_native_modifiers |= remapped_key->native_modifier;
435 } else {
436 remapped_flags |= kModifierFlagToPrefName[i].flag;
437 remapped_native_modifiers |= kModifierFlagToPrefName[i].native_modifier;
438 }
439 }
440 }
441
442 remapped_flags = (event->flags() & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) |
443 remapped_flags;
444 remapped_native_modifiers =
445 (xkey->state & ~(Mod4Mask | ControlMask | Mod1Mask)) |
446 remapped_native_modifiers;
447 485
448 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if 486 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
449 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external 487 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
450 // keyboard is pressed) since X can handle that case. 488 // keyboard is pressed) since X can handle that case.
451 if ((event->type() == ui::ET_KEY_PRESSED) && 489 if ((event->type() == ui::ET_KEY_PRESSED) &&
452 (event->key_code() != ui::VKEY_CAPITAL) && 490 (event->key_code() != ui::VKEY_CAPITAL) &&
453 (remapped_keycode == ui::VKEY_CAPITAL)) { 491 (remapped_keycode == ui::VKEY_CAPITAL)) {
454 chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_ ? 492 chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_ ?
455 xkeyboard_ : InputMethodManager::GetInstance()->GetXKeyboard(); 493 xkeyboard_ : InputMethodManager::GetInstance()->GetXKeyboard();
456 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled()); 494 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled());
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask, 626 OverwriteEvent(event, next_xkeycode_, xkey->state & ~Mod1Mask,
589 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN); 627 ui::VKEY_NEXT, event->flags() & ~ui::EF_ALT_DOWN);
590 rewritten = true; 628 rewritten = true;
591 } 629 }
592 #else 630 #else
593 // TODO(yusukes): Support Ash on other platforms if needed. 631 // TODO(yusukes): Support Ash on other platforms if needed.
594 #endif 632 #endif
595 return rewritten; 633 return rewritten;
596 } 634 }
597 635
636 void KeyRewriter::RewriteLocatedEvent(aura::LocatedEvent* event) {
637 #if defined(OS_CHROMEOS)
638 XEvent* xevent = event->native_event();
639 if (!xevent || xevent->type != GenericEvent)
640 return;
641
642 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
643 if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease)
644 return;
645
646 // First, remap modifier masks.
647 int remapped_flags = 0;
648 unsigned int remapped_native_modifiers = 0U;
649 GetRemappedModifierMasks(event->flags(), xievent->mods.effective,
650 &remapped_flags, &remapped_native_modifiers);
651 xievent->mods.effective = remapped_native_modifiers;
652
653 // Then, remap Alt+Button1 to Button3.
654 if ((xievent->mods.effective & Mod1Mask) && xievent->detail == 1) {
655 xievent->mods.effective &= ~Mod1Mask;
656 xievent->detail = 3;
657 if (xievent->evtype == XI_ButtonRelease) {
658 // On the release clear the left button from the existing state and the
659 // mods, and set the right button.
660 XISetMask(xievent->buttons.mask, 3);
661 XIClearMask(xievent->buttons.mask, 1);
662 xievent->mods.effective &= ~Button1Mask;
663 }
664 }
665
666 event->set_flags(ui::EventFlagsFromNative(xevent));
667 #else
668 // TODO(yusukes): Support Ash on other platforms if needed.
669 #endif
670 }
671
598 void KeyRewriter::OverwriteEvent(aura::KeyEvent* event, 672 void KeyRewriter::OverwriteEvent(aura::KeyEvent* event,
599 unsigned int new_native_keycode, 673 unsigned int new_native_keycode,
600 unsigned int new_native_state, 674 unsigned int new_native_state,
601 ui::KeyboardCode new_keycode, 675 ui::KeyboardCode new_keycode,
602 int new_flags) { 676 int new_flags) {
603 #if defined(OS_CHROMEOS) 677 #if defined(OS_CHROMEOS)
604 XEvent* xev = event->native_event(); 678 XEvent* xev = event->native_event();
605 XKeyEvent* xkey = &(xev->xkey); 679 XKeyEvent* xkey = &(xev->xkey);
606 xkey->keycode = new_native_keycode; 680 xkey->keycode = new_native_keycode;
607 xkey->state = new_native_state; 681 xkey->state = new_native_state;
(...skipping 12 matching lines...) Expand all
620 const DeviceType type = KeyRewriter::GetDeviceType(device_name); 694 const DeviceType type = KeyRewriter::GetDeviceType(device_name);
621 if (type == kDeviceAppleKeyboard) { 695 if (type == kDeviceAppleKeyboard) {
622 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 696 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
623 << "id=" << device_id; 697 << "id=" << device_id;
624 } 698 }
625 // Always overwrite the existing device_id since the X server may reuse a 699 // Always overwrite the existing device_id since the X server may reuse a
626 // device id for an unattached device. 700 // device id for an unattached device.
627 device_id_to_type_[device_id] = type; 701 device_id_to_type_[device_id] = type;
628 return type; 702 return type;
629 } 703 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698