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

Unified Diff: chrome/browser/ui/views/ash/key_rewriter.cc

Issue 10383301: Move modifier remapping code from X to Ash (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: style fix Created 8 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/views/ash/key_rewriter.h ('k') | chrome/browser/ui/views/ash/key_rewriter_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/views/ash/key_rewriter.cc
diff --git a/chrome/browser/ui/views/ash/key_rewriter.cc b/chrome/browser/ui/views/ash/key_rewriter.cc
index 951fccaa47c1595cb647981fb2ed4714ebf37bee..5f9ba116d15d4fdd3c734ad0e15562e4856fc3f4 100644
--- a/chrome/browser/ui/views/ash/key_rewriter.cc
+++ b/chrome/browser/ui/views/ash/key_rewriter.cc
@@ -9,6 +9,8 @@
#include "ash/shell.h"
#include "base/logging.h"
#include "base/string_util.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
#include "ui/base/keycodes/keyboard_code_conversion.h"
@@ -19,18 +21,100 @@
#include <X11/Xlib.h>
#include "base/chromeos/chromeos_version.h"
+#include "chrome/browser/chromeos/input_method/input_method_manager.h"
+#include "chrome/browser/chromeos/input_method/xkeyboard.h"
#include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
+#include "chrome/common/pref_names.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/x/x11_util.h"
+
+using chromeos::input_method::InputMethodManager;
#endif
namespace {
const int kBadDeviceId = -1;
+#if defined(OS_CHROMEOS)
+// A key code and a flag we should use when a key is remapped to |remap_to|.
+const struct ModifierRemapping {
+ int remap_to;
+ int flag;
+ unsigned int native_modifier;
Daniel Erat 2012/05/24 14:55:12 nit: s/modifier/modifiers/ (since there are multip
Yusuke Sato 2012/05/25 01:34:15 Actually only one modifier mask is used per entry
+ ui::KeyboardCode keycode;
+ KeySym native_keysyms[4]; // left, right, shift+left, shift+right.
+} kModifierRemappings[] = {
+ { chromeos::input_method::kSearchKey, 0, Mod4Mask, ui::VKEY_LWIN,
+ { XK_Super_L, XK_Super_L, XK_Super_L, XK_Super_L}},
+ { chromeos::input_method::kControlKey, ui::EF_CONTROL_DOWN, ControlMask,
+ ui::VKEY_CONTROL,
+ { XK_Control_L, XK_Control_R, XK_Control_L, XK_Control_R }},
+ { chromeos::input_method::kAltKey, ui::EF_ALT_DOWN, Mod1Mask,
+ ui::VKEY_MENU, { XK_Alt_L, XK_Alt_R, XK_Meta_L, XK_Meta_R }},
+ { chromeos::input_method::kVoidKey, 0, 0U, ui::VKEY_UNKNOWN,
+ { XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol }},
+ { chromeos::input_method::kCapsLockKey, 0, 0U, ui::VKEY_CAPITAL,
+ { XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock }},
+};
+
+// A structure for converting |native_modifier| to a pair of |flag| and
+// |pref_name|.
+const struct ModifierFlagToPrefName {
+ unsigned int native_modifier;
+ int flag;
+ const char* pref_name;
+} kModifierFlagToPrefName[] = {
+ { Mod4Mask, 0, prefs::kLanguageXkbRemapSearchKeyTo },
+ { ControlMask, ui::EF_CONTROL_DOWN, prefs::kLanguageXkbRemapControlKeyTo },
+ { Mod1Mask, ui::EF_ALT_DOWN, prefs::kLanguageXkbRemapAltKeyTo },
+};
+
+// Gets a remapped key for |pref_name| key. For example, to find out which
+// key Search is currently remapped to, call the function with
+// prefs::kLanguageXkbRemapSearchKeyTo.
+const ModifierRemapping* GetRemappedKey(const std::string& pref_name,
+ const PrefService& pref_service) {
+ if (!pref_service.FindPreference(pref_name.c_str()))
+ return NULL; // The |pref_name| hasn't been registered. On login screen?
+ const int value = pref_service.GetInteger(pref_name.c_str());
+ for (size_t i = 0; i < arraysize(kModifierRemappings); ++i) {
+ if (value == kModifierRemappings[i].remap_to)
+ return &kModifierRemappings[i];
+ }
+ return NULL;
+}
+
+bool IsRight(KeySym native_keysym) {
+ switch (native_keysym) {
+ case XK_Alt_R:
+ case XK_Control_R:
+ case XK_Hyper_R:
+ case XK_Meta_R:
+ case XK_Shift_R:
+ case XK_Super_R:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+#endif
+
+const PrefService* GetPrefService() {
+ Profile* profile = ProfileManager::GetDefaultProfile();
+ if (profile)
+ return profile->GetPrefs();
+ return NULL;
+}
+
} // namespace
-KeyRewriter::KeyRewriter() : last_device_id_(kBadDeviceId) {
+KeyRewriter::KeyRewriter()
+ : last_device_id_(kBadDeviceId),
+#if defined(OS_CHROMEOS)
+ xkeyboard_(NULL),
+#endif
+ pref_service_(NULL) {
// The ash shell isn't instantiated for our unit tests.
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->GetRootWindow()->AddRootWindowObserver(this);
@@ -155,6 +239,13 @@ void KeyRewriter::RefreshKeycodes() {
Display* display = ui::GetXDisplay();
control_l_xkeycode_ = XKeysymToKeycode(display, XK_Control_L);
control_r_xkeycode_ = XKeysymToKeycode(display, XK_Control_R);
+ alt_l_xkeycode_ = XKeysymToKeycode(display, XK_Alt_L);
+ alt_r_xkeycode_ = XKeysymToKeycode(display, XK_Alt_R);
+ meta_l_xkeycode_ = XKeysymToKeycode(display, XK_Meta_L);
+ meta_r_xkeycode_ = XKeysymToKeycode(display, XK_Meta_R);
+ windows_l_xkeycode_ = XKeysymToKeycode(display, XK_Super_L);
+ caps_lock_xkeycode_ = XKeysymToKeycode(display, XK_Caps_Lock);
+ void_symbol_xkeycode_ = XKeysymToKeycode(display, XK_VoidSymbol);
kp_0_xkeycode_ = XKeysymToKeycode(display, XK_KP_0);
kp_1_xkeycode_ = XKeysymToKeycode(display, XK_KP_1);
kp_2_xkeycode_ = XKeysymToKeycode(display, XK_KP_2);
@@ -167,13 +258,61 @@ void KeyRewriter::RefreshKeycodes() {
kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9);
kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal);
}
+
+KeyCode KeyRewriter::NativeKeySymToNativeKeycode(KeySym keysym) {
+ switch (keysym) {
+ case XK_Control_L:
+ return control_l_xkeycode_;
+ case XK_Control_R:
+ return control_r_xkeycode_;
+ case XK_Alt_L:
+ return alt_l_xkeycode_;
+ case XK_Alt_R:
+ return alt_r_xkeycode_;
+ case XK_Meta_L:
+ return meta_l_xkeycode_;
+ case XK_Meta_R:
+ return meta_r_xkeycode_;
+ case XK_Super_L:
+ return windows_l_xkeycode_;
+ case XK_Caps_Lock:
+ return caps_lock_xkeycode_;
+ case XK_VoidSymbol:
+ return void_symbol_xkeycode_;
+ case XK_KP_0:
+ return kp_0_xkeycode_;
+ case XK_KP_1:
+ return kp_1_xkeycode_;
+ case XK_KP_2:
+ return kp_2_xkeycode_;
+ case XK_KP_3:
+ return kp_3_xkeycode_;
+ case XK_KP_4:
+ return kp_4_xkeycode_;
+ case XK_KP_5:
+ return kp_5_xkeycode_;
+ case XK_KP_6:
+ return kp_6_xkeycode_;
+ case XK_KP_7:
+ return kp_7_xkeycode_;
+ case XK_KP_8:
+ return kp_8_xkeycode_;
+ case XK_KP_9:
+ return kp_9_xkeycode_;
+ case XK_KP_Decimal:
+ return kp_decimal_xkeycode_;
+ default:
+ break;
+ }
+ return 0U;
+}
#endif
void KeyRewriter::Rewrite(aura::KeyEvent* event) {
RewriteCommandToControl(event);
+ RewriteModifiers(event);
RewriteNumPadKeys(event);
- // TODO(yusukes): Implement crbug.com/115112 (Search/Ctrl/Alt remapping) and
- // crosbug.com/27167 (allow sending function keys) here.
+ // TODO(yusukes): Implement crosbug.com/27167 (allow sending function keys).
}
bool KeyRewriter::RewriteCommandToControl(aura::KeyEvent* event) {
@@ -232,6 +371,95 @@ bool KeyRewriter::RewriteCommandToControl(aura::KeyEvent* event) {
return rewritten;
}
+bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) {
+ const PrefService* pref_service =
+ pref_service_ ? pref_service_ : GetPrefService();
+ if (!pref_service)
+ return false;
+
+#if defined(OS_CHROMEOS)
+ XEvent* xev = event->native_event();
+ XKeyEvent* xkey = &(xev->xkey);
+ KeySym keysym = XLookupKeysym(xkey, 0);
+
+ ui::KeyboardCode remapped_keycode = event->key_code();
+ KeyCode remapped_native_keycode = xkey->keycode;
+ int remapped_flags = 0;
+ unsigned int remapped_native_modifiers = 0U;
+
+ // First, remap |keysym|.
+ const char* pref_name = NULL;
+ switch (keysym) {
+ case XK_Super_L:
+ pref_name = prefs::kLanguageXkbRemapSearchKeyTo;
+ break;
+ case XK_Control_L:
+ case XK_Control_R:
+ pref_name = prefs::kLanguageXkbRemapControlKeyTo;
+ break;
+ case XK_Alt_L:
+ case XK_Alt_R:
+ case XK_Meta_L:
+ case XK_Meta_R:
+ pref_name = prefs::kLanguageXkbRemapAltKeyTo;
+ break;
+ default:
+ break;
+ }
+ if (pref_name) {
+ const ModifierRemapping* remapped_key =
+ GetRemappedKey(pref_name, *pref_service);
+ if (remapped_key) {
+ remapped_keycode = remapped_key->keycode;
+ const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) +
+ (IsRight(keysym) ? (1 << 0) : 0);
+ const KeySym native_keysym = remapped_key->native_keysyms[level];
+ remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
+ }
+ }
+
+ // Next, remap modifier bits.
+ for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) {
+ if (xkey->state & kModifierFlagToPrefName[i].native_modifier) {
+ const ModifierRemapping* remapped_key =
+ GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service);
+ if (remapped_key) {
+ remapped_flags |= remapped_key->flag;
+ remapped_native_modifiers |= remapped_key->native_modifier;
+ } else {
+ remapped_flags |= kModifierFlagToPrefName[i].flag;
+ remapped_native_modifiers |= kModifierFlagToPrefName[i].native_modifier;
+ }
+ }
+ }
+
+ remapped_flags = (event->flags() & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) |
+ remapped_flags;
+ remapped_native_modifiers =
+ (xkey->state & ~(Mod4Mask | ControlMask | Mod1Mask)) |
+ remapped_native_modifiers;
+
+ // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
+ // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
+ // keyboard is pressed) since X can handle that case.
+ if ((event->type() == ui::ET_KEY_PRESSED) &&
+ (event->key_code() != ui::VKEY_CAPITAL) &&
+ (remapped_keycode == ui::VKEY_CAPITAL)) {
+ chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_ ?
+ xkeyboard_ : InputMethodManager::GetInstance()->GetXKeyboard();
+ xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled());
+ }
+
+ OverwriteEvent(event,
+ remapped_native_keycode, remapped_native_modifiers,
+ remapped_keycode, remapped_flags);
+ return true;
+#else
+ // TODO(yusukes): Support Ash on other platforms if needed.
+ return false;
+#endif
+}
+
bool KeyRewriter::RewriteNumPadKeys(aura::KeyEvent* event) {
bool rewritten = false;
#if defined(OS_CHROMEOS)
« no previous file with comments | « chrome/browser/ui/views/ash/key_rewriter.h ('k') | chrome/browser/ui/views/ash/key_rewriter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698