15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/events/event_rewriter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ash/sticky_keys/sticky_keys_controller.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_state.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/macros.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/extension_commands_global_registry.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/chromeos_switches.h"
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chromeos/ime/ime_keyboard.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/ime/input_method_manager.h"
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/events/event.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/events/event_utils.h"
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion.h"
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(USE_X11)
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <X11/extensions/XInput2.h>
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <X11/Xlib.h>
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Get rid of macros from Xlib.h that conflicts with other parts of the code.
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#undef RootWindow
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#undef Status
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/base/x/x11_util.h"
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion_x.h"
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace chromeos {
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Table of key properties of remappable keys and/or remapping targets.
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// This is searched in two distinct ways:
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)//  - |remap_to| is an |input_method::ModifierKey|, which is the form
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)//    held in user preferences. |GetRemappedKey()| maps this to the
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)//    corresponding |key_code| and characterstic event |flag|.
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)//  - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)//    to the corresponding user preference |pref_name| for that flag's
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)//    key, so that it can then be remapped as above.
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// In addition |kModifierRemappingCtrl| is a direct reference to the
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Control key entry in the table, used in handling Chromebook Diamond
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// and Apple Command keys.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const struct ModifierRemapping {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int remap_to;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flag;
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::KeyboardCode key_code;
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const char* pref_name;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} kModifierRemappings[] = {
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {input_method::kSearchKey, ui::EF_COMMAND_DOWN, ui::VKEY_LWIN,
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       prefs::kLanguageRemapSearchKeyTo},
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {input_method::kControlKey, ui::EF_CONTROL_DOWN, ui::VKEY_CONTROL,
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       prefs::kLanguageRemapControlKeyTo},
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {input_method::kAltKey, ui::EF_ALT_DOWN, ui::VKEY_MENU,
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       prefs::kLanguageRemapAltKeyTo},
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {input_method::kVoidKey, 0, ui::VKEY_UNKNOWN, NULL},
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      {input_method::kCapsLockKey, ui::EF_MOD3_DOWN, ui::VKEY_CAPITAL,
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       prefs::kLanguageRemapCapsLockKeyTo},
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {input_method::kEscapeKey, 0, ui::VKEY_ESCAPE, NULL},
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {0, 0, ui::VKEY_F15, prefs::kLanguageRemapDiamondKeyTo},
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ModifierRemapping* kModifierRemappingCtrl = &kModifierRemappings[1];
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets a remapped key for |pref_name| key. For example, to find out which
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// key Search is currently remapped to, call the function with
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prefs::kLanguageRemapSearchKeyTo.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ModifierRemapping* GetRemappedKey(const std::string& pref_name,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const PrefService& pref_service) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pref_service.FindPreference(pref_name.c_str()))
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;  // The |pref_name| hasn't been registered. On login screen?
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int value = pref_service.GetInteger(pref_name.c_str());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kModifierRemappings); ++i) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value == kModifierRemappings[i].remap_to)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &kModifierRemappings[i];
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HasDiamondKey() {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return CommandLine::ForCurrentProcess()->HasSwitch(
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      chromeos::switches::kHasChromeOSDiamondKey);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool IsISOLevel5ShiftUsedByCurrentInputMethod() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's not possible to make both features work. For now, we don't remap
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mod3Mask when Neo2 is in use.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(yusukes): Remove the restriction.
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_method::InputMethodManager* manager =
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      input_method::InputMethodManager::Get();
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return manager->IsISOLevel5ShiftUsedByCurrentInputMethod();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)bool IsExtensionCommandRegistered(const ui::KeyEvent& key_event) {
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Some keyboard events for ChromeOS get rewritten, such as:
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Search+Shift+Left gets converted to Shift+Home (BeginDocument).
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This doesn't make sense if the user has assigned that shortcut
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // to an extension. Because:
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // 1) The extension would, upon seeing a request for Ctrl+Shift+Home have
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //    to register for Shift+Home, instead.
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // 2) The conversion is unnecessary, because Shift+Home (BeginDocument) isn't
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //    going to be executed.
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Therefore, we skip converting the accelerator if an extension has
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // registered for this shortcut.
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Profile* profile = ProfileManager::GetActiveUserProfile();
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!profile || !extensions::ExtensionCommandsGlobalRegistry::Get(profile))
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  int modifiers = key_event.flags() & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
12434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                                       ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
12534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  ui::Accelerator accelerator(key_event.key_code(), modifiers);
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return extensions::ExtensionCommandsGlobalRegistry::Get(profile)
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ->IsRegistered(accelerator);
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)EventRewriter::DeviceType GetDeviceType(const std::string& device_name) {
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<std::string> tokens;
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Tokenize(device_name, " .", &tokens);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // If the |device_name| contains the two words, "apple" and "keyboard", treat
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // it as an Apple keyboard.
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool found_apple = false;
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool found_keyboard = false;
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (size_t i = 0; i < tokens.size(); ++i) {
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple"))
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      found_apple = true;
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      found_keyboard = true;
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (found_apple && found_keyboard)
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return EventRewriter::kDeviceAppleKeyboard;
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return EventRewriter::kDeviceUnknown;
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
152116680a4aac90f2aa7413d9095a592090648e557Ben MurdochEventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller)
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : last_keyboard_device_id_(ui::ED_UNKNOWN_DEVICE),
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ime_keyboard_for_testing_(NULL),
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pref_service_for_testing_(NULL),
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      sticky_keys_controller_(sticky_keys_controller),
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_diamond_key_modifier_flags_(ui::EF_NONE) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventRewriter::~EventRewriter() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
163116680a4aac90f2aa7413d9095a592090648e557Ben MurdochEventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedForTesting(
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int device_id,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_name) {
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Tests must avoid XI2 reserved device IDs.
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK((device_id < 0) || (device_id > 1));
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return KeyboardDeviceAddedInternal(device_id, device_name);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRewriter::RewriteMouseButtonEventForTesting(
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ui::MouseEvent& event,
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<ui::Event>* rewritten_event) {
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RewriteMouseButtonEvent(event, rewritten_event);
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ui::EventRewriteStatus EventRewriter::RewriteEvent(
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const ui::Event& event,
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<ui::Event>* rewritten_event) {
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((event.type() == ui::ET_KEY_PRESSED) ||
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (event.type() == ui::ET_KEY_RELEASED)) {
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event),
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           rewritten_event);
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((event.type() == ui::ET_MOUSE_PRESSED) ||
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (event.type() == ui::ET_MOUSE_RELEASED)) {
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RewriteMouseButtonEvent(static_cast<const ui::MouseEvent&>(event),
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                   rewritten_event);
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (event.type() == ui::ET_MOUSEWHEEL) {
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RewriteMouseWheelEvent(
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        static_cast<const ui::MouseWheelEvent&>(event), rewritten_event);
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((event.type() == ui::ET_TOUCH_PRESSED) ||
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (event.type() == ui::ET_TOUCH_RELEASED)) {
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event),
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                             rewritten_event);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (event.IsScrollEvent()) {
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RewriteScrollEvent(static_cast<const ui::ScrollEvent&>(event),
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              rewritten_event);
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return ui::EVENT_REWRITE_CONTINUE;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ui::EventRewriteStatus EventRewriter::NextDispatchEvent(
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const ui::Event& last_event,
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<ui::Event>* new_event) {
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (sticky_keys_controller_) {
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // In the case of sticky keys, we know what the events obtained here are:
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // modifier key releases that match the ones previously discarded. So, we
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // know that they don't have to be passed through the post-sticky key
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // rewriting phases, |RewriteExtendedKeys()| and |RewriteFunctionKeys()|,
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // because those phases do nothing with modifier key releases.
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return sticky_keys_controller_->NextDispatchEvent(new_event);
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NOTREACHED();
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return ui::EVENT_REWRITE_CONTINUE;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRewriter::BuildRewrittenKeyEvent(
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ui::KeyEvent& key_event,
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ui::KeyboardCode key_code,
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int flags,
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<ui::Event>* rewritten_event) {
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::KeyEvent* rewritten_key_event = NULL;
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(USE_X11)
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  XEvent* xev = key_event.native_event();
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (xev) {
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    XEvent xkeyevent;
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Convert all XI2-based key events into X11 core-based key events,
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // until consumers no longer depend on receiving X11 core events.
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (xev->type == GenericEvent)
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ui::InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent);
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    else
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      xkeyevent.xkey = xev->xkey;
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    unsigned int original_x11_keycode = xkeyevent.xkey.keycode;
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Update native event to match rewritten |ui::Event|.
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // The X11 keycode represents a physical key position, so it shouldn't
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // change unless we have actually changed keys, not just modifiers.
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // This is one guard against problems like crbug.com/390263.
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (key_event.key_code() != key_code) {
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      xkeyevent.xkey.keycode =
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          XKeyCodeForWindowsKeyCode(key_code, flags, gfx::GetXDisplay());
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ui::KeyEvent x11_key_event(&xkeyevent);
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    rewritten_key_event = new ui::KeyEvent(x11_key_event);
2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // For numpad keys, the key char should always NOT be changed because
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // XKeyCodeForWindowsKeyCode method cannot handle non-US keyboard layout.
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // The correct key char can be got from original X11 keycode but not for the
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // rewritten X11 keycode.
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // For Shift+NumpadKey cases, use the rewritten X11 keycode (US layout).
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Please see crbug.com/335644.
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (key_code >= ui::VKEY_NUMPAD0 && key_code <= ui::VKEY_DIVIDE) {
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      XEvent numpad_xevent;
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      numpad_xevent.xkey = xkeyevent.xkey;
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // Remove the shift state before getting key char.
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // Because X11/XKB sometimes returns unexpected key char for
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // Shift+NumpadKey. e.g. Shift+Numpad_4 returns 'D', etc.
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      numpad_xevent.xkey.state &= ~ShiftMask;
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      numpad_xevent.xkey.state |= Mod2Mask;  // Always set NumLock mask.
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (!(flags & ui::EF_SHIFT_DOWN))
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        numpad_xevent.xkey.keycode = original_x11_keycode;
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      rewritten_key_event->set_character(
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          ui::GetCharacterFromXEvent(&numpad_xevent));
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!rewritten_key_event)
272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    rewritten_key_event = new ui::KeyEvent(key_event);
273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_key_event->set_flags(flags);
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_key_event->set_key_code(key_code);
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(USE_X11)
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::UpdateX11EventForFlags(rewritten_key_event);
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_key_event->NormalizeFlags();
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_event->reset(rewritten_key_event);
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
282116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRewriter::DeviceKeyPressedOrReleased(int device_id) {
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!device_id_to_type_.count(device_id))
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    KeyboardDeviceAdded(device_id);
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  last_keyboard_device_id_ = device_id;
286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const PrefService* EventRewriter::GetPrefService() const {
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (pref_service_for_testing_)
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return pref_service_for_testing_;
291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Profile* profile = ProfileManager::GetActiveUserProfile();
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return profile ? profile->GetPrefs() : NULL;
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRewriter::IsAppleKeyboard() const {
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (last_keyboard_device_id_ == ui::ED_UNKNOWN_DEVICE)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check which device generated |event|.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, DeviceType>::const_iterator iter =
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      device_id_to_type_.find(last_keyboard_device_id_);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == device_id_to_type_.end()) {
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(ERROR) << "Device ID " << last_keyboard_device_id_ << " is unknown.";
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DeviceType type = iter->second;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type == kDeviceAppleKeyboard;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const {
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const PrefService* prefs = GetPrefService();
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) &&
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      prefs->GetBoolean(prefs::kLanguageSendFunctionKeys))
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return true;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ash::wm::WindowState* state = ash::wm::GetActiveWindowState();
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return state ? state->top_row_keys_are_function_keys() : false;
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int EventRewriter::GetRemappedModifierMasks(const PrefService& pref_service,
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                            const ui::Event& event,
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                            int original_flags) const {
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int unmodified_flags = original_flags;
325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int rewritten_flags = current_diamond_key_modifier_flags_;
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (size_t i = 0; unmodified_flags && (i < arraysize(kModifierRemappings));
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++i) {
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ModifierRemapping* remapped_key = NULL;
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!(unmodified_flags & kModifierRemappings[i].flag))
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    switch (kModifierRemappings[i].flag) {
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      case ui::EF_COMMAND_DOWN:
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // Rewrite Command key presses on an Apple keyboard to Control.
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (IsAppleKeyboard()) {
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          DCHECK_EQ(ui::EF_CONTROL_DOWN, kModifierRemappingCtrl->flag);
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          remapped_key = kModifierRemappingCtrl;
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case ui::EF_MOD3_DOWN:
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // If EF_MOD3_DOWN is used by the current input method, leave it alone;
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // it is not remappable.
342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (IsISOLevel5ShiftUsedByCurrentInputMethod())
343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          continue;
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // Otherwise, Mod3Mask is set on X events when the Caps Lock key
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // is down, but, if Caps Lock is remapped, CapsLock is NOT set,
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // because pressing the key does not invoke caps lock. So, the
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // kModifierRemappings[] table uses EF_MOD3_DOWN for the Caps
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // Lock remapping.
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      default:
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!remapped_key && kModifierRemappings[i].pref_name) {
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      remapped_key =
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          GetRemappedKey(kModifierRemappings[i].pref_name, pref_service);
356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (remapped_key) {
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      unmodified_flags &= ~kModifierRemappings[i].flag;
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      rewritten_flags |= remapped_key->flag;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return rewritten_flags | unmodified_flags;
363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode(
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const KeyboardRemapping* remappings,
367010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    size_t num_remappings,
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const MutableKeyState& input,
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    MutableKeyState* remapped_state) {
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (size_t i = 0; i < num_remappings; ++i) {
371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const KeyboardRemapping& map = remappings[i];
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (input.key_code != map.input_key_code)
373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      continue;
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if ((input.flags & map.input_flags) != map.input_flags)
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      continue;
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    remapped_state->key_code = map.output_key_code;
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags;
378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return true;
379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return false;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ui::EventRewriteStatus EventRewriter::RewriteKeyEvent(
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ui::KeyEvent& key_event,
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<ui::Event>* rewritten_event) {
38634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  if (IsExtensionCommandRegistered(key_event))
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return ui::EVENT_REWRITE_CONTINUE;
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (key_event.source_device_id() != ui::ED_UNKNOWN_DEVICE)
389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DeviceKeyPressedOrReleased(key_event.source_device_id());
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MutableKeyState state = {key_event.flags(), key_event.key_code()};
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // crbug.com/136465.
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!(key_event.flags() & ui::EF_FINAL)) {
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RewriteModifierKeys(key_event, &state);
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RewriteNumPadKeys(key_event, &state);
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (sticky_keys_controller_) {
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status = sticky_keys_controller_->RewriteKeyEvent(
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        key_event, state.key_code, &state.flags);
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (status == ui::EVENT_REWRITE_DISCARD)
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return ui::EVENT_REWRITE_DISCARD;
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
40434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  if (!(key_event.flags() & ui::EF_FINAL)) {
405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RewriteExtendedKeys(key_event, &state);
406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    RewriteFunctionKeys(key_event, &state);
407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((key_event.flags() == state.flags) &&
409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (key_event.key_code() == state.key_code) &&
410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(USE_X11)
411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // TODO(kpschoedel): This test is present because several consumers of
412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // key events depend on having a native core X11 event, so we rewrite
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // all XI2 key events (GenericEvent) into corresponding core X11 key
414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // events. Remove this when event consumers no longer care about
415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // native X11 event details (crbug.com/380349).
416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (!key_event.HasNativeEvent() ||
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       (key_event.native_event()->type != GenericEvent)) &&
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (status == ui::EVENT_REWRITE_CONTINUE)) {
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ui::EVENT_REWRITE_CONTINUE;
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Sticky keys may have returned a result other than |EVENT_REWRITE_CONTINUE|,
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // in which case we need to preserve that return status. Alternatively, we
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // might be here because key_event changed, in which case we need to
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // return |EVENT_REWRITE_REWRITTEN|.
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (status == ui::EVENT_REWRITE_CONTINUE)
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status = ui::EVENT_REWRITE_REWRITTEN;
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BuildRewrittenKeyEvent(
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      key_event, state.key_code, state.flags, rewritten_event);
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return status;
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdochui::EventRewriteStatus EventRewriter::RewriteMouseButtonEvent(
43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ui::MouseEvent& mouse_event,
43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<ui::Event>* rewritten_event) {
43646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int flags = mouse_event.flags();
43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RewriteLocatedEvent(mouse_event, &flags);
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (sticky_keys_controller_)
440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status = sticky_keys_controller_->RewriteMouseEvent(mouse_event, &flags);
441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int changed_button = ui::EF_NONE;
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((mouse_event.type() == ui::ET_MOUSE_PRESSED) ||
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (mouse_event.type() == ui::ET_MOUSE_RELEASED)) {
444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    changed_button = RewriteModifierClick(mouse_event, &flags);
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((mouse_event.flags() == flags) &&
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (status == ui::EVENT_REWRITE_CONTINUE)) {
44846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return ui::EVENT_REWRITE_CONTINUE;
449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (status == ui::EVENT_REWRITE_CONTINUE)
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status = ui::EVENT_REWRITE_REWRITTEN;
45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event);
45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  rewritten_event->reset(rewritten_mouse_event);
45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  rewritten_mouse_event->set_flags(flags);
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(USE_X11)
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::UpdateX11EventForFlags(rewritten_mouse_event);
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (changed_button != ui::EF_NONE) {
459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    rewritten_mouse_event->set_changed_button_flags(changed_button);
46046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(USE_X11)
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ui::UpdateX11EventForChangedButtonFlags(rewritten_mouse_event);
46246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return status;
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdochui::EventRewriteStatus EventRewriter::RewriteMouseWheelEvent(
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ui::MouseWheelEvent& wheel_event,
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<ui::Event>* rewritten_event) {
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!sticky_keys_controller_)
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ui::EVENT_REWRITE_CONTINUE;
472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int flags = wheel_event.flags();
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::EventRewriteStatus status =
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      sticky_keys_controller_->RewriteMouseEvent(wheel_event, &flags);
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((wheel_event.flags() == flags) &&
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (status == ui::EVENT_REWRITE_CONTINUE)) {
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ui::EVENT_REWRITE_CONTINUE;
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (status == ui::EVENT_REWRITE_CONTINUE)
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status = ui::EVENT_REWRITE_REWRITTEN;
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::MouseWheelEvent* rewritten_wheel_event =
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new ui::MouseWheelEvent(wheel_event);
483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_event->reset(rewritten_wheel_event);
484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_wheel_event->set_flags(flags);
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(USE_X11)
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::UpdateX11EventForFlags(rewritten_wheel_event);
487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return status;
48946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
49046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
49146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ui::EventRewriteStatus EventRewriter::RewriteTouchEvent(
49246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const ui::TouchEvent& touch_event,
49346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<ui::Event>* rewritten_event) {
49446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int flags = touch_event.flags();
49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RewriteLocatedEvent(touch_event, &flags);
49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (touch_event.flags() == flags)
49746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return ui::EVENT_REWRITE_CONTINUE;
49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ui::TouchEvent* rewritten_touch_event = new ui::TouchEvent(touch_event);
49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  rewritten_event->reset(rewritten_touch_event);
50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  rewritten_touch_event->set_flags(flags);
50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(USE_X11)
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::UpdateX11EventForFlags(rewritten_touch_event);
50346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
50446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return ui::EVENT_REWRITE_REWRITTEN;
50546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
50646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
507116680a4aac90f2aa7413d9095a592090648e557Ben Murdochui::EventRewriteStatus EventRewriter::RewriteScrollEvent(
508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ui::ScrollEvent& scroll_event,
509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<ui::Event>* rewritten_event) {
510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int flags = scroll_event.flags();
511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (sticky_keys_controller_)
513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status = sticky_keys_controller_->RewriteScrollEvent(scroll_event, &flags);
514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (status == ui::EVENT_REWRITE_CONTINUE)
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return status;
516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::ScrollEvent* rewritten_scroll_event = new ui::ScrollEvent(scroll_event);
517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_event->reset(rewritten_scroll_event);
518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rewritten_scroll_event->set_flags(flags);
519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(USE_X11)
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::UpdateX11EventForFlags(rewritten_scroll_event);
521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return status;
523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
525010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event,
526010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                        MutableKeyState* state) {
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         key_event.type() == ui::ET_KEY_RELEASED);
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing if we have just logged in as guest but have not restarted chrome
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process yet (so we are still on the login screen). In this situations we
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have no user profile so can not do anything useful.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that currently, unlike other accounts, when user logs in as guest, we
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // restart chrome process. In future this is to be changed.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(glotov): remove the following condition when we do not restart chrome
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when user logs in as guest.
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(kpschoedel): check whether this is still necessary.
5386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (user_manager::UserManager::Get()->IsLoggedInAsGuest() &&
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LoginDisplayHostImpl::default_host())
540010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
5411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const PrefService* pref_service = GetPrefService();
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pref_service)
544010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MutableKeyState incoming = *state;
547010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  state->flags = ui::EF_NONE;
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int characteristic_flag = ui::EF_NONE;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // First, remap the key code.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ModifierRemapping* remapped_key = NULL;
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (incoming.key_code) {
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // On Chrome OS, F15 (XF86XK_Launch6) with NumLock (Mod2Mask) is sent
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // when Diamond key is pressed.
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case ui::VKEY_F15:
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // When diamond key is not available, the configuration UI for Diamond
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // key is not shown. Therefore, ignore the kLanguageRemapDiamondKeyTo
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // syncable pref.
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (HasDiamondKey())
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        remapped_key =
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            GetRemappedKey(prefs::kLanguageRemapDiamondKeyTo, *pref_service);
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Default behavior of F15 is Control, even if --has-chromeos-diamond-key
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // is absent, according to unit test comments.
564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (!remapped_key) {
565010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        DCHECK_EQ(ui::VKEY_CONTROL, kModifierRemappingCtrl->key_code);
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        remapped_key = kModifierRemappingCtrl;
567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // F15 is not a modifier key, so we need to track its state directly.
569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (key_event.type() == ui::ET_KEY_PRESSED) {
570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        int remapped_flag = remapped_key->flag;
571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        if (remapped_key->remap_to == input_method::kCapsLockKey)
572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          remapped_flag |= ui::EF_CAPS_LOCK_DOWN;
573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        current_diamond_key_modifier_flags_ = remapped_flag;
574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      } else {
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        current_diamond_key_modifier_flags_ = ui::EF_NONE;
576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On Chrome OS, XF86XK_Launch7 (F16) with Mod3Mask is sent when Caps Lock
579effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // is pressed (with one exception: when
580effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // IsISOLevel5ShiftUsedByCurrentInputMethod() is true, the key generates
581effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // XK_ISO_Level3_Shift with Mod3Mask, not XF86XK_Launch7).
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case ui::VKEY_F16:
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      characteristic_flag = ui::EF_CAPS_LOCK_DOWN;
584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      remapped_key =
585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          GetRemappedKey(prefs::kLanguageRemapCapsLockKeyTo, *pref_service);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case ui::VKEY_LWIN:
588010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case ui::VKEY_RWIN:
589010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      characteristic_flag = ui::EF_COMMAND_DOWN;
590010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Rewrite Command-L/R key presses on an Apple keyboard to Control.
591010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (IsAppleKeyboard()) {
592010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        DCHECK_EQ(ui::VKEY_CONTROL, kModifierRemappingCtrl->key_code);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        remapped_key = kModifierRemappingCtrl;
594010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      } else {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        remapped_key =
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetRemappedKey(prefs::kLanguageRemapSearchKeyTo, *pref_service);
597010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Default behavior is Super key, hence don't remap the event if the pref
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // is unavailable.
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
601010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case ui::VKEY_CONTROL:
602010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      characteristic_flag = ui::EF_CONTROL_DOWN;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remapped_key =
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetRemappedKey(prefs::kLanguageRemapControlKeyTo, *pref_service);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
606010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case ui::VKEY_MENU:
607010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // ALT key
608010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      characteristic_flag = ui::EF_ALT_DOWN;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remapped_key =
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetRemappedKey(prefs::kLanguageRemapAltKeyTo, *pref_service);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remapped_key) {
617010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state->key_code = remapped_key->key_code;
618010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    incoming.flags |= characteristic_flag;
619010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    characteristic_flag = remapped_key->flag;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next, remap modifier bits.
623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  state->flags |=
624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GetRemappedModifierMasks(*pref_service, key_event, incoming.flags);
625010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (key_event.type() == ui::ET_KEY_PRESSED)
626010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state->flags |= characteristic_flag;
627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else
628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state->flags &= ~characteristic_flag;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keyboard is pressed) since X can handle that case.
633010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (key_event.type() == ui::ET_KEY_PRESSED &&
634010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      incoming.key_code != ui::VKEY_CAPITAL &&
635010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state->key_code == ui::VKEY_CAPITAL) {
636010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    chromeos::input_method::ImeKeyboard* ime_keyboard =
637010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        ime_keyboard_for_testing_
638010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            ? ime_keyboard_for_testing_
639010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            : chromeos::input_method::InputMethodManager::Get()
640010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                  ->GetImeKeyboard();
641010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ime_keyboard->SetCapsLockEnabled(!ime_keyboard->CapsLockIsEnabled());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void EventRewriter::RewriteNumPadKeys(const ui::KeyEvent& key_event,
646010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                      MutableKeyState* state) {
647010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
648010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         key_event.type() == ui::ET_KEY_RELEASED);
649010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!(state->flags & ui::EF_NUMPAD_KEY))
650010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
651010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MutableKeyState incoming = *state;
652010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
653010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  static const KeyboardRemapping kNumPadRemappings[] = {
654010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_INSERT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD0, ui::EF_NUMPAD_KEY},
655010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_DELETE, ui::EF_NUMPAD_KEY, ui::VKEY_DECIMAL, ui::EF_NUMPAD_KEY},
656010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_END, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD1, ui::EF_NUMPAD_KEY},
657010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_DOWN, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD2, ui::EF_NUMPAD_KEY},
658010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_NEXT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD3, ui::EF_NUMPAD_KEY},
659010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_LEFT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD4, ui::EF_NUMPAD_KEY},
660010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_CLEAR, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD5, ui::EF_NUMPAD_KEY},
661010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_RIGHT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD6, ui::EF_NUMPAD_KEY},
662010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_HOME, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD7, ui::EF_NUMPAD_KEY},
663010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_UP, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD8, ui::EF_NUMPAD_KEY},
664010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      {ui::VKEY_PRIOR, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD9, ui::EF_NUMPAD_KEY},
665010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
666010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
667010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RewriteWithKeyboardRemappingsByKeyCode(
668010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      kNumPadRemappings, arraysize(kNumPadRemappings), incoming, state);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
671010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void EventRewriter::RewriteExtendedKeys(const ui::KeyEvent& key_event,
672010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                        MutableKeyState* state) {
673010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
674010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         key_event.type() == ui::ET_KEY_RELEASED);
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
676010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MutableKeyState incoming = *state;
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool rewritten = false;
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
679010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if ((incoming.flags & (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) ==
680010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) {
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Allow Search to avoid rewriting extended keys.
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static const KeyboardRemapping kAvoidRemappings[] = {
683010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Alt+Backspace
684010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_BACK, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_BACK,
685010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::EF_ALT_DOWN,
686010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        },
687010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Control+Alt+Up
688010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_UP,
689010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN,
690010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
691010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        },
692010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Alt+Up
693010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_UP,
694010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::EF_ALT_DOWN,
695010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        },
696010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Control+Alt+Down
697010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_DOWN,
698010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN,
699010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
700010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        },
701010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Alt+Down
702010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_DOWN,
703010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::EF_ALT_DOWN,
704010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }};
705010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
706010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    rewritten = RewriteWithKeyboardRemappingsByKeyCode(
707010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kAvoidRemappings, arraysize(kAvoidRemappings), incoming, state);
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
710010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!rewritten && (incoming.flags & ui::EF_COMMAND_DOWN)) {
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static const KeyboardRemapping kSearchRemappings[] = {
712010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Search+BackSpace -> Delete
713010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_BACK, ui::EF_COMMAND_DOWN, ui::VKEY_DELETE, 0},
714010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Search+Left -> Home
715010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_LEFT, ui::EF_COMMAND_DOWN, ui::VKEY_HOME, 0},
716010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Search+Up -> Prior (aka PageUp)
717010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_UP, ui::EF_COMMAND_DOWN, ui::VKEY_PRIOR, 0},
718010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Search+Right -> End
719010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN, ui::VKEY_END, 0},
720010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Search+Down -> Next (aka PageDown)
721010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_DOWN, ui::EF_COMMAND_DOWN, ui::VKEY_NEXT, 0},
722010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Search+Period -> Insert
723010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN, ui::VKEY_INSERT, 0}};
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
725010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    rewritten = RewriteWithKeyboardRemappingsByKeyCode(
726010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kSearchRemappings, arraysize(kSearchRemappings), incoming, state);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
729010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!rewritten && (incoming.flags & ui::EF_ALT_DOWN)) {
730010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    static const KeyboardRemapping kNonSearchRemappings[] = {
731010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Alt+BackSpace -> Delete
732010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_BACK, ui::EF_ALT_DOWN, ui::VKEY_DELETE, 0},
733010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Control+Alt+Up -> Home
734010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::VKEY_HOME, 0},
735010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Alt+Up -> Prior (aka PageUp)
736010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_UP, ui::EF_ALT_DOWN, ui::VKEY_PRIOR, 0},
737010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Control+Alt+Down -> End
738010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::VKEY_END, 0},
739010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {  // Alt+Down -> Next (aka PageDown)
740010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         ui::VKEY_DOWN, ui::EF_ALT_DOWN, ui::VKEY_NEXT, 0}};
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    rewritten = RewriteWithKeyboardRemappingsByKeyCode(
743010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kNonSearchRemappings, arraysize(kNonSearchRemappings), incoming, state);
744010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
747010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void EventRewriter::RewriteFunctionKeys(const ui::KeyEvent& key_event,
748010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                        MutableKeyState* state) {
749010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(key_event.type() == ui::ET_KEY_PRESSED ||
750010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        key_event.type() == ui::ET_KEY_RELEASED);
751010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MutableKeyState incoming = *state;
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool rewritten = false;
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
754010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if ((incoming.key_code >= ui::VKEY_F1) &&
755010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      (incoming.key_code <= ui::VKEY_F24)) {
756010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // By default the top row (F1-F12) keys are system keys for back, forward,
757010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // brightness, volume, etc. However, windows for v2 apps can optionally
758010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // request raw function keys for these keys.
759010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool top_row_keys_are_function_keys = TopRowKeysAreFunctionKeys(key_event);
760010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool search_is_pressed = (incoming.flags & ui::EF_COMMAND_DOWN) != 0;
761010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
762010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //  Search? Top Row   Result
763010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //  ------- --------  ------
764010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //  No      Fn        Unchanged
765010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //  No      System    Fn -> System
766010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //  Yes     Fn        Fn -> System
767010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    //  Yes     System    Search+Fn -> Fn
768010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (top_row_keys_are_function_keys == search_is_pressed) {
769010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Rewrite the F1-F12 keys on a Chromebook keyboard to system keys.
770010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      static const KeyboardRemapping kFkeysToSystemKeys[] = {
771010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F1, 0, ui::VKEY_BROWSER_BACK, 0},
772010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F2, 0, ui::VKEY_BROWSER_FORWARD, 0},
773010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F3, 0, ui::VKEY_BROWSER_REFRESH, 0},
774010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F4, 0, ui::VKEY_MEDIA_LAUNCH_APP2, 0},
775010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F5, 0, ui::VKEY_MEDIA_LAUNCH_APP1, 0},
776010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F6, 0, ui::VKEY_BRIGHTNESS_DOWN, 0},
777010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F7, 0, ui::VKEY_BRIGHTNESS_UP, 0},
778010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F8, 0, ui::VKEY_VOLUME_MUTE, 0},
779010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F9, 0, ui::VKEY_VOLUME_DOWN, 0},
780010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          {ui::VKEY_F10, 0, ui::VKEY_VOLUME_UP, 0},
781010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      };
782010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      MutableKeyState incoming_without_command = incoming;
783010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      incoming_without_command.flags &= ~ui::EF_COMMAND_DOWN;
784010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      rewritten =
785010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          RewriteWithKeyboardRemappingsByKeyCode(kFkeysToSystemKeys,
786010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                 arraysize(kFkeysToSystemKeys),
787010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                 incoming_without_command,
788010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                 state);
789010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (search_is_pressed) {
790010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Allow Search to avoid rewriting F1-F12.
791010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state->flags &= ~ui::EF_COMMAND_DOWN;
792010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      rewritten = true;
7934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
796010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!rewritten && (incoming.flags & ui::EF_COMMAND_DOWN)) {
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remap Search+<number> to F<number>.
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We check the keycode here instead of the keysym, as these keys have
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // different keysyms when modifiers are pressed, such as shift.
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(danakj): On some i18n keyboards, these choices will be bad and we
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // should make layout-specific choices here. For eg. on a french keyboard
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // "-" and "6" are the same key, so F11 will not be accessible.
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static const KeyboardRemapping kNumberKeysToFkeys[] = {
805010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_1, ui::EF_COMMAND_DOWN, ui::VKEY_F1, 0},
806010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_2, ui::EF_COMMAND_DOWN, ui::VKEY_F2, 0},
807010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_3, ui::EF_COMMAND_DOWN, ui::VKEY_F3, 0},
808010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_4, ui::EF_COMMAND_DOWN, ui::VKEY_F4, 0},
809010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_5, ui::EF_COMMAND_DOWN, ui::VKEY_F5, 0},
810010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_6, ui::EF_COMMAND_DOWN, ui::VKEY_F6, 0},
811010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_7, ui::EF_COMMAND_DOWN, ui::VKEY_F7, 0},
812010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_8, ui::EF_COMMAND_DOWN, ui::VKEY_F8, 0},
813010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_9, ui::EF_COMMAND_DOWN, ui::VKEY_F9, 0},
814010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_0, ui::EF_COMMAND_DOWN, ui::VKEY_F10, 0},
815010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_OEM_MINUS, ui::EF_COMMAND_DOWN, ui::VKEY_F11, 0},
816010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        {ui::VKEY_OEM_PLUS, ui::EF_COMMAND_DOWN, ui::VKEY_F12, 0}};
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rewritten = RewriteWithKeyboardRemappingsByKeyCode(
818010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kNumberKeysToFkeys, arraysize(kNumberKeysToFkeys), incoming, state);
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
822010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void EventRewriter::RewriteLocatedEvent(const ui::Event& event,
82346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        int* flags) {
824010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const PrefService* pref_service = GetPrefService();
825010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!pref_service)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
82746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  *flags = GetRemappedModifierMasks(*pref_service, event, *flags);
828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
829010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
830116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint EventRewriter::RewriteModifierClick(const ui::MouseEvent& mouse_event,
831116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        int* flags) {
832116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Remap Alt+Button1 to Button3.
833116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const int kAltLeftButton = (ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON);
834116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (((*flags & kAltLeftButton) == kAltLeftButton) &&
835116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ((mouse_event.type() == ui::ET_MOUSE_PRESSED) ||
836116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       pressed_device_ids_.count(mouse_event.source_device_id()))) {
837116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *flags &= ~kAltLeftButton;
83846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    *flags |= ui::EF_RIGHT_MOUSE_BUTTON;
839116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (mouse_event.type() == ui::ET_MOUSE_PRESSED)
840116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pressed_device_ids_.insert(mouse_event.source_device_id());
841116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    else
842116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pressed_device_ids_.erase(mouse_event.source_device_id());
843116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ui::EF_RIGHT_MOUSE_BUTTON;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return ui::EF_NONE;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
848116680a4aac90f2aa7413d9095a592090648e557Ben MurdochEventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedInternal(
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int device_id,
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_name) {
851010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const DeviceType type = GetDeviceType(device_name);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == kDeviceAppleKeyboard) {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "id=" << device_id;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always overwrite the existing device_id since the X server may reuse a
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // device id for an unattached device.
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device_id_to_type_[device_id] = type;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
862116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRewriter::KeyboardDeviceAdded(int device_id) {
863010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(USE_X11)
864010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_NE(XIAllDevices, device_id);
865010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_NE(XIAllMasterDevices, device_id);
866010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (device_id == XIAllDevices || device_id == XIAllMasterDevices) {
867010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LOG(ERROR) << "Unexpected device_id passed: " << device_id;
868010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
869010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
870010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
871010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int ndevices_return = 0;
872010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  XIDeviceInfo* device_info =
873010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return);
874010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
875010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices,
876010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // the number of devices found should be either 0 (not found) or 1.
877010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!device_info) {
878010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown.";
879010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
880010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
881010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
882010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(1, ndevices_return);
883010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (int i = 0; i < ndevices_return; ++i) {
884010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK_EQ(device_id, device_info[i].deviceid);  // see the comment above.
885010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(device_info[i].name);
886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    KeyboardDeviceAddedInternal(device_info[i].deviceid, device_info[i].name);
887010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
888010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
889010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  XIFreeDeviceInfo(device_info);
890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else
891116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  KeyboardDeviceAddedInternal(device_id, "keyboard");
892010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
894010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace chromeos
896