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 737e6099cb2fc3c5f099a817843279794d679228..6c5720fce7589a39e5f08c590c005681834708d2 100644 |
--- a/chrome/browser/ui/views/ash/key_rewriter.cc |
+++ b/chrome/browser/ui/views/ash/key_rewriter.cc |
@@ -179,14 +179,16 @@ void KeyRewriter::RewriteForTesting(aura::KeyEvent* event) { |
ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterKeyEvent( |
aura::KeyEvent* event) { |
- const ash::KeyRewriterDelegate::Action kActionRewrite = |
- ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; |
- if (!event->HasNativeEvent()) { |
- // Do not handle a fabricated event generated by tests. |
- return kActionRewrite; |
- } |
- Rewrite(event); |
- return kActionRewrite; // Do not drop the event. |
+ if (event->HasNativeEvent()) |
+ Rewrite(event); |
+ return ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; |
+} |
+ |
+ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterLocatedEvent( |
+ aura::LocatedEvent* event) { |
+ if (event->HasNativeEvent()) |
+ RewriteLocatedEvent(event); |
+ return ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; |
} |
void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { |
@@ -353,6 +355,54 @@ bool KeyRewriter::IsAppleKeyboard() const { |
return type == kDeviceAppleKeyboard; |
} |
+void KeyRewriter::GetRemappedModifierMasks( |
+ int original_flags, |
+ unsigned int original_native_modifiers, |
+ int* remapped_flags, |
+ unsigned int* remapped_native_modifiers) const { |
+#if defined(OS_CHROMEOS) |
+ // TODO(glotov): remove the following condition when we do not restart chrome |
+ // when user logs in as guest. See Rewrite() for details. |
+ if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && |
+ chromeos::BaseLoginDisplayHost::default_host()) { |
+ return; |
+ } |
+ |
+ const PrefService* pref_service = |
+ pref_service_ ? pref_service_ : GetPrefService(); |
+ if (!pref_service) |
+ return; |
+ |
+ for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) { |
+ if (original_native_modifiers & |
+ kModifierFlagToPrefName[i].native_modifier) { |
+ const ModifierRemapping* remapped_key = |
+ GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service); |
+ // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R. |
+ if (IsAppleKeyboard() && |
+ (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) { |
+ remapped_key = kModifierRemappingCtrl; |
+ } |
+ 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 = |
+ (original_flags & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) | |
+ *remapped_flags; |
+ *remapped_native_modifiers = |
+ (original_native_modifiers & ~(Mod4Mask | ControlMask | Mod1Mask)) | |
+ *remapped_native_modifiers; |
+#endif |
+} |
+ |
bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) { |
// Do nothing if we have just logged in as guest but have not restarted chrome |
// process yet (so we are still on the login screen). In this situations we |
@@ -381,8 +431,6 @@ bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) { |
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; |
@@ -420,30 +468,10 @@ bool KeyRewriter::RewriteModifiers(aura::KeyEvent* event) { |
} |
// 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); |
- // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R. |
- if (IsAppleKeyboard() && |
- (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) { |
- remapped_key = kModifierRemappingCtrl; |
- } |
- 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; |
+ int remapped_flags = 0; |
+ unsigned int remapped_native_modifiers = 0U; |
+ GetRemappedModifierMasks(event->flags(), xkey->state, |
+ &remapped_flags, &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 |
@@ -595,6 +623,42 @@ bool KeyRewriter::RewriteBackspaceAndArrowKeys(aura::KeyEvent* event) { |
return rewritten; |
} |
+void KeyRewriter::RewriteLocatedEvent(aura::LocatedEvent* event) { |
+#if defined(OS_CHROMEOS) |
+ XEvent* xevent = event->native_event(); |
+ if (!xevent || xevent->type != GenericEvent) |
+ return; |
+ |
+ XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); |
+ if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease) |
+ return; |
+ |
+ // First, remap modifier masks. |
+ int remapped_flags = 0; |
+ unsigned int remapped_native_modifiers = 0U; |
+ GetRemappedModifierMasks(event->flags(), xievent->mods.effective, |
+ &remapped_flags, &remapped_native_modifiers); |
+ xievent->mods.effective = remapped_native_modifiers; |
+ |
+ // Then, remap Alt+Button1 to Button3. |
+ if ((xievent->mods.effective & Mod1Mask) && xievent->detail == 1) { |
+ xievent->mods.effective &= ~Mod1Mask; |
+ xievent->detail = 3; |
+ if (xievent->evtype == XI_ButtonRelease) { |
+ // On the release clear the left button from the existing state and the |
+ // mods, and set the right button. |
+ XISetMask(xievent->buttons.mask, 3); |
+ XIClearMask(xievent->buttons.mask, 1); |
+ xievent->mods.effective &= ~Button1Mask; |
+ } |
+ } |
+ |
+ event->set_flags(ui::EventFlagsFromNative(xevent)); |
+#else |
+ // TODO(yusukes): Support Ash on other platforms if needed. |
+#endif |
+} |
+ |
void KeyRewriter::OverwriteEvent(aura::KeyEvent* event, |
unsigned int new_native_keycode, |
unsigned int new_native_state, |