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

Side by Side Diff: chrome/browser/ui/ash/event_rewriter.cc

Issue 11346028: Allow Caps Lock to be remapped [part 2 of 2] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased, added more tests Created 8 years, 1 month 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/ash/event_rewriter.h" 5 #include "chrome/browser/ui/ash/event_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"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "chrome/browser/prefs/pref_service.h" 12 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/profiles/profile_manager.h" 13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "ui/aura/root_window.h" 14 #include "ui/aura/root_window.h"
15 #include "ui/base/events/event.h" 15 #include "ui/base/events/event.h"
16 #include "ui/base/keycodes/keyboard_code_conversion.h" 16 #include "ui/base/keycodes/keyboard_code_conversion.h"
17 17
18 #if defined(OS_CHROMEOS) 18 #if defined(OS_CHROMEOS)
19 #include <X11/extensions/XInput2.h> 19 #include <X11/extensions/XInput2.h>
20 #include <X11/keysym.h> 20 #include <X11/keysym.h>
21 #include <X11/XF86keysym.h> 21 #include <X11/XF86keysym.h>
22 #include <X11/Xlib.h> 22 #include <X11/Xlib.h>
23 23
24 // Get rid of a macro from Xlib.h that conflicts with OwnershipService class. 24 // Get rid of a macro from Xlib.h that conflicts with OwnershipService class.
25 #undef Status 25 #undef Status
26 26
27 #include "base/chromeos/chromeos_version.h" 27 #include "base/chromeos/chromeos_version.h"
28 #include "base/command_line.h"
28 #include "chrome/browser/chromeos/input_method/input_method_manager.h" 29 #include "chrome/browser/chromeos/input_method/input_method_manager.h"
29 #include "chrome/browser/chromeos/input_method/xkeyboard.h" 30 #include "chrome/browser/chromeos/input_method/xkeyboard.h"
30 #include "chrome/browser/chromeos/login/base_login_display_host.h" 31 #include "chrome/browser/chromeos/login/base_login_display_host.h"
31 #include "chrome/browser/chromeos/login/user_manager.h" 32 #include "chrome/browser/chromeos/login/user_manager.h"
32 #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h" 33 #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
34 #include "chrome/common/chrome_switches.h"
33 #include "chrome/common/pref_names.h" 35 #include "chrome/common/pref_names.h"
34 #include "ui/base/keycodes/keyboard_code_conversion_x.h" 36 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
35 #include "ui/base/x/x11_util.h" 37 #include "ui/base/x/x11_util.h"
36 38
37 using chromeos::input_method::InputMethodManager; 39 using chromeos::input_method::InputMethodManager;
38 #endif 40 #endif
39 41
40 namespace { 42 namespace {
41 43
42 const int kBadDeviceId = -1; 44 const int kBadDeviceId = -1;
(...skipping 16 matching lines...) Expand all
59 { XK_Control_L, XK_Control_R, XK_Control_L, XK_Control_R }}, 61 { XK_Control_L, XK_Control_R, XK_Control_L, XK_Control_R }},
60 { chromeos::input_method::kAltKey, ui::EF_ALT_DOWN, Mod1Mask, 62 { chromeos::input_method::kAltKey, ui::EF_ALT_DOWN, Mod1Mask,
61 ui::VKEY_MENU, { XK_Alt_L, XK_Alt_R, XK_Meta_L, XK_Meta_R }}, 63 ui::VKEY_MENU, { XK_Alt_L, XK_Alt_R, XK_Meta_L, XK_Meta_R }},
62 { chromeos::input_method::kVoidKey, 0, 0U, ui::VKEY_UNKNOWN, 64 { chromeos::input_method::kVoidKey, 0, 0U, ui::VKEY_UNKNOWN,
63 { XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol }}, 65 { XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol }},
64 { chromeos::input_method::kCapsLockKey, 0, 0U, ui::VKEY_CAPITAL, 66 { chromeos::input_method::kCapsLockKey, 0, 0U, ui::VKEY_CAPITAL,
65 { XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock }}, 67 { XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock }},
66 }; 68 };
67 69
68 const ModifierRemapping* kModifierRemappingCtrl = &kModifierRemappings[1]; 70 const ModifierRemapping* kModifierRemappingCtrl = &kModifierRemappings[1];
71 const ModifierRemapping* kModifierRemappingCapsLock = &kModifierRemappings[4];
69 72
70 // A structure for converting |native_modifier| to a pair of |flag| and 73 // A structure for converting |native_modifier| to a pair of |flag| and
71 // |pref_name|. 74 // |pref_name|.
72 const struct ModifierFlagToPrefName { 75 const struct ModifierFlagToPrefName {
73 unsigned int native_modifier; 76 unsigned int native_modifier;
74 int flag; 77 int flag;
75 const char* pref_name; 78 const char* pref_name;
76 } kModifierFlagToPrefName[] = { 79 } kModifierFlagToPrefName[] = {
77 // TODO(yusukes): When the device has a Chrome keyboard (i.e. the one without 80 // TODO(yusukes): When the device has a Chrome keyboard (i.e. the one without
78 // Caps Lock), we should not check kLanguageRemapCapsLockKeyTo. 81 // Caps Lock), we should not check kLanguageRemapCapsLockKeyTo.
(...skipping 26 matching lines...) Expand all
105 case XK_Meta_R: 108 case XK_Meta_R:
106 case XK_Shift_R: 109 case XK_Shift_R:
107 case XK_Super_R: 110 case XK_Super_R:
108 return true; 111 return true;
109 default: 112 default:
110 break; 113 break;
111 } 114 }
112 return false; 115 return false;
113 } 116 }
114 117
115 bool ShouldRemapCapsLock() { 118 bool HasChromeOSKeyboard() {
116 // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask, it's 119 return CommandLine::ForCurrentProcess()->HasSwitch(
117 // not possible to make both features work. For now, we don't remap Mod3Mask 120 switches::kHasChromeOSKeyboard);
118 // when Neo2 is in use. 121 }
122
123 bool IsMod3InUse() {
Daniel Erat 2012/11/01 19:13:06 nit: IsMod3UsedByCurrentInputMethod() may be a bit
Yusuke Sato 2012/11/01 19:25:27 Thanks, done.
124 // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask,
125 // it's not possible to make both features work. For now, we don't remap
126 // Mod3Mask when Neo2 is in use.
119 // TODO(yusukes): Remove the restriction. 127 // TODO(yusukes): Remove the restriction.
120 return InputMethodManager::GetInstance()->GetCurrentInputMethod().id() != 128 return InputMethodManager::GetInstance()->GetCurrentInputMethod().id() ==
121 kNeo2LayoutId; 129 kNeo2LayoutId;
122 } 130 }
123 #endif 131 #endif
124 132
125 const PrefService* GetPrefService() { 133 const PrefService* GetPrefService() {
126 Profile* profile = ProfileManager::GetDefaultProfile(); 134 Profile* profile = ProfileManager::GetDefaultProfile();
127 if (profile) 135 if (profile)
128 return profile->GetPrefs(); 136 return profile->GetPrefs();
129 return NULL; 137 return NULL;
130 } 138 }
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && 395 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() &&
388 chromeos::BaseLoginDisplayHost::default_host()) { 396 chromeos::BaseLoginDisplayHost::default_host()) {
389 return; 397 return;
390 } 398 }
391 399
392 const PrefService* pref_service = 400 const PrefService* pref_service =
393 pref_service_ ? pref_service_ : GetPrefService(); 401 pref_service_ ? pref_service_ : GetPrefService();
394 if (!pref_service) 402 if (!pref_service)
395 return; 403 return;
396 404
397 const bool skip_mod3 = !ShouldRemapCapsLock(); 405 // When a Chrome OS keyboard is available, the configuration UI for Caps Lock
406 // is not shown. Therefore, ignore the kLanguageRemapCapsLockKeyTo syncable
407 // pref. If Mod3 is in use, don't check the pref either.
408 const bool skip_mod3 = HasChromeOSKeyboard() || IsMod3InUse();
409
398 for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) { 410 for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) {
399 if (skip_mod3 && 411 if (skip_mod3 &&
400 (kModifierFlagToPrefName[i].native_modifier == Mod3Mask)) { 412 (kModifierFlagToPrefName[i].native_modifier == Mod3Mask)) {
401 continue; 413 continue;
402 } 414 }
403 if (original_native_modifiers & 415 if (original_native_modifiers &
404 kModifierFlagToPrefName[i].native_modifier) { 416 kModifierFlagToPrefName[i].native_modifier) {
405 const ModifierRemapping* remapped_key = 417 const ModifierRemapping* remapped_key =
406 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service); 418 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service);
407 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R. 419 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 DCHECK_EQ(chromeos::input_method::kControlKey, 467 DCHECK_EQ(chromeos::input_method::kControlKey,
456 kModifierRemappingCtrl->remap_to); 468 kModifierRemappingCtrl->remap_to);
457 469
458 XEvent* xev = event->native_event(); 470 XEvent* xev = event->native_event();
459 XKeyEvent* xkey = &(xev->xkey); 471 XKeyEvent* xkey = &(xev->xkey);
460 KeySym keysym = XLookupKeysym(xkey, 0); 472 KeySym keysym = XLookupKeysym(xkey, 0);
461 473
462 ui::KeyboardCode remapped_keycode = event->key_code(); 474 ui::KeyboardCode remapped_keycode = event->key_code();
463 KeyCode remapped_native_keycode = xkey->keycode; 475 KeyCode remapped_native_keycode = xkey->keycode;
464 476
465 const bool skip_mod3 = !ShouldRemapCapsLock();
466
467 // First, remap |keysym|. 477 // First, remap |keysym|.
468 const char* pref_name = NULL; 478 const ModifierRemapping* remapped_key = NULL;
469 switch (keysym) { 479 switch (keysym) {
470 // XF86XK_Launch7 (F16) with Mod3Mask is sent when Caps Lock is pressed. 480 // On Chrome OS, XF86XK_Launch7 (F16) with Mod3Mask is sent when Caps Lock
481 // is pressed (with one exception: when IsMod3InUse() is true, the key
482 // generates XK_ISO_Level3_Shift with Mod3Mask, not XF86XK_Launch7).
471 case XF86XK_Launch7: 483 case XF86XK_Launch7:
472 pref_name = skip_mod3 ? NULL : prefs::kLanguageRemapCapsLockKeyTo; 484 // When a Chrome OS keyboard is available, the configuration UI for Caps
485 // Lock is not shown. Therefore, ignore the kLanguageRemapCapsLockKeyTo
486 // syncable pref.
487 if (HasChromeOSKeyboard())
488 remapped_key = kModifierRemappingCapsLock;
489 else
490 remapped_key =
491 GetRemappedKey(prefs::kLanguageRemapCapsLockKeyTo, *pref_service);
473 break; 492 break;
474 case XK_Super_L: 493 case XK_Super_L:
475 case XK_Super_R: 494 case XK_Super_R:
476 pref_name = prefs::kLanguageRemapSearchKeyTo; 495 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
496 if (IsAppleKeyboard())
497 remapped_key = kModifierRemappingCtrl;
498 else
499 remapped_key =
500 GetRemappedKey(prefs::kLanguageRemapSearchKeyTo, *pref_service);
477 break; 501 break;
478 case XK_Control_L: 502 case XK_Control_L:
479 case XK_Control_R: 503 case XK_Control_R:
480 pref_name = prefs::kLanguageRemapControlKeyTo; 504 remapped_key =
505 GetRemappedKey(prefs::kLanguageRemapControlKeyTo, *pref_service);
481 break; 506 break;
482 case XK_Alt_L: 507 case XK_Alt_L:
483 case XK_Alt_R: 508 case XK_Alt_R:
484 case XK_Meta_L: 509 case XK_Meta_L:
485 case XK_Meta_R: 510 case XK_Meta_R:
486 pref_name = prefs::kLanguageRemapAltKeyTo; 511 remapped_key =
512 GetRemappedKey(prefs::kLanguageRemapAltKeyTo, *pref_service);
487 break; 513 break;
488 default: 514 default:
489 break; 515 break;
490 } 516 }
491 if (pref_name) { 517
492 const ModifierRemapping* remapped_key = 518 if (remapped_key) {
493 GetRemappedKey(pref_name, *pref_service); 519 remapped_keycode = remapped_key->keycode;
494 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R. 520 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) +
495 if (IsAppleKeyboard() && (keysym == XK_Super_L || keysym == XK_Super_R)) 521 (IsRight(keysym) ? (1 << 0) : 0);
496 remapped_key = kModifierRemappingCtrl; 522 const KeySym native_keysym = remapped_key->native_keysyms[level];
497 if (remapped_key) { 523 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
498 remapped_keycode = remapped_key->keycode;
499 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) +
500 (IsRight(keysym) ? (1 << 0) : 0);
501 const KeySym native_keysym = remapped_key->native_keysyms[level];
502 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
503 }
504 } 524 }
505 525
506 // Next, remap modifier bits. 526 // Next, remap modifier bits.
507 int remapped_flags = 0; 527 int remapped_flags = 0;
508 unsigned int remapped_native_modifiers = 0U; 528 unsigned int remapped_native_modifiers = 0U;
509 GetRemappedModifierMasks(event->flags(), xkey->state, 529 GetRemappedModifierMasks(event->flags(), xkey->state,
510 &remapped_flags, &remapped_native_modifiers); 530 &remapped_flags, &remapped_native_modifiers);
511 531
512 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if 532 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
513 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external 533 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 const DeviceType type = EventRewriter::GetDeviceType(device_name); 747 const DeviceType type = EventRewriter::GetDeviceType(device_name);
728 if (type == kDeviceAppleKeyboard) { 748 if (type == kDeviceAppleKeyboard) {
729 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 749 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
730 << "id=" << device_id; 750 << "id=" << device_id;
731 } 751 }
732 // Always overwrite the existing device_id since the X server may reuse a 752 // Always overwrite the existing device_id since the X server may reuse a
733 // device id for an unattached device. 753 // device id for an unattached device.
734 device_id_to_type_[device_id] = type; 754 device_id_to_type_[device_id] = type;
735 return type; 755 return type;
736 } 756 }
OLDNEW
« no previous file with comments | « chrome/browser/resources/options/chromeos/keyboard_overlay.js ('k') | chrome/browser/ui/ash/event_rewriter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698