Home | History | Annotate | Download | only in events
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/events/event_rewriter.h"
      6 
      7 #include <vector>
      8 
      9 #include "ash/sticky_keys/sticky_keys_controller.h"
     10 #include "ash/wm/window_state.h"
     11 #include "ash/wm/window_util.h"
     12 #include "base/command_line.h"
     13 #include "base/logging.h"
     14 #include "base/macros.h"
     15 #include "base/prefs/pref_service.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/sys_info.h"
     18 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
     19 #include "chrome/browser/extensions/extension_commands_global_registry.h"
     20 #include "chrome/browser/profiles/profile_manager.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "chromeos/chromeos_switches.h"
     23 #include "chromeos/ime/ime_keyboard.h"
     24 #include "chromeos/ime/input_method_manager.h"
     25 #include "components/user_manager/user_manager.h"
     26 #include "ui/events/event.h"
     27 #include "ui/events/event_utils.h"
     28 #include "ui/events/keycodes/keyboard_code_conversion.h"
     29 #include "ui/wm/core/window_util.h"
     30 
     31 #if defined(USE_X11)
     32 #include <X11/extensions/XInput2.h>
     33 #include <X11/Xlib.h>
     34 // Get rid of macros from Xlib.h that conflicts with other parts of the code.
     35 #undef RootWindow
     36 #undef Status
     37 
     38 #include "ui/base/x/x11_util.h"
     39 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
     40 #endif
     41 
     42 namespace chromeos {
     43 
     44 namespace {
     45 
     46 // Table of key properties of remappable keys and/or remapping targets.
     47 // This is searched in two distinct ways:
     48 //  - |remap_to| is an |input_method::ModifierKey|, which is the form
     49 //    held in user preferences. |GetRemappedKey()| maps this to the
     50 //    corresponding |key_code| and characterstic event |flag|.
     51 //  - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this
     52 //    to the corresponding user preference |pref_name| for that flag's
     53 //    key, so that it can then be remapped as above.
     54 // In addition |kModifierRemappingCtrl| is a direct reference to the
     55 // Control key entry in the table, used in handling Chromebook Diamond
     56 // and Apple Command keys.
     57 const struct ModifierRemapping {
     58   int remap_to;
     59   int flag;
     60   ui::KeyboardCode key_code;
     61   const char* pref_name;
     62 } kModifierRemappings[] = {
     63       {input_method::kSearchKey, ui::EF_COMMAND_DOWN, ui::VKEY_LWIN,
     64        prefs::kLanguageRemapSearchKeyTo},
     65       {input_method::kControlKey, ui::EF_CONTROL_DOWN, ui::VKEY_CONTROL,
     66        prefs::kLanguageRemapControlKeyTo},
     67       {input_method::kAltKey, ui::EF_ALT_DOWN, ui::VKEY_MENU,
     68        prefs::kLanguageRemapAltKeyTo},
     69       {input_method::kVoidKey, 0, ui::VKEY_UNKNOWN, NULL},
     70       {input_method::kCapsLockKey, ui::EF_MOD3_DOWN, ui::VKEY_CAPITAL,
     71        prefs::kLanguageRemapCapsLockKeyTo},
     72       {input_method::kEscapeKey, 0, ui::VKEY_ESCAPE, NULL},
     73       {0, 0, ui::VKEY_F15, prefs::kLanguageRemapDiamondKeyTo},
     74 };
     75 
     76 const ModifierRemapping* kModifierRemappingCtrl = &kModifierRemappings[1];
     77 
     78 // Gets a remapped key for |pref_name| key. For example, to find out which
     79 // key Search is currently remapped to, call the function with
     80 // prefs::kLanguageRemapSearchKeyTo.
     81 const ModifierRemapping* GetRemappedKey(const std::string& pref_name,
     82                                         const PrefService& pref_service) {
     83   if (!pref_service.FindPreference(pref_name.c_str()))
     84     return NULL;  // The |pref_name| hasn't been registered. On login screen?
     85   const int value = pref_service.GetInteger(pref_name.c_str());
     86   for (size_t i = 0; i < arraysize(kModifierRemappings); ++i) {
     87     if (value == kModifierRemappings[i].remap_to)
     88       return &kModifierRemappings[i];
     89   }
     90   return NULL;
     91 }
     92 
     93 bool HasDiamondKey() {
     94   return CommandLine::ForCurrentProcess()->HasSwitch(
     95       chromeos::switches::kHasChromeOSDiamondKey);
     96 }
     97 
     98 bool IsISOLevel5ShiftUsedByCurrentInputMethod() {
     99   // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask,
    100   // it's not possible to make both features work. For now, we don't remap
    101   // Mod3Mask when Neo2 is in use.
    102   // TODO(yusukes): Remove the restriction.
    103   input_method::InputMethodManager* manager =
    104       input_method::InputMethodManager::Get();
    105   return manager->IsISOLevel5ShiftUsedByCurrentInputMethod();
    106 }
    107 
    108 bool IsExtensionCommandRegistered(const ui::KeyEvent& key_event) {
    109   // Some keyboard events for ChromeOS get rewritten, such as:
    110   // Search+Shift+Left gets converted to Shift+Home (BeginDocument).
    111   // This doesn't make sense if the user has assigned that shortcut
    112   // to an extension. Because:
    113   // 1) The extension would, upon seeing a request for Ctrl+Shift+Home have
    114   //    to register for Shift+Home, instead.
    115   // 2) The conversion is unnecessary, because Shift+Home (BeginDocument) isn't
    116   //    going to be executed.
    117   // Therefore, we skip converting the accelerator if an extension has
    118   // registered for this shortcut.
    119   Profile* profile = ProfileManager::GetActiveUserProfile();
    120   if (!profile || !extensions::ExtensionCommandsGlobalRegistry::Get(profile))
    121     return false;
    122 
    123   int modifiers = key_event.flags() & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
    124                                        ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
    125   ui::Accelerator accelerator(key_event.key_code(), modifiers);
    126   return extensions::ExtensionCommandsGlobalRegistry::Get(profile)
    127       ->IsRegistered(accelerator);
    128 }
    129 
    130 EventRewriter::DeviceType GetDeviceType(const std::string& device_name) {
    131   std::vector<std::string> tokens;
    132   Tokenize(device_name, " .", &tokens);
    133 
    134   // If the |device_name| contains the two words, "apple" and "keyboard", treat
    135   // it as an Apple keyboard.
    136   bool found_apple = false;
    137   bool found_keyboard = false;
    138   for (size_t i = 0; i < tokens.size(); ++i) {
    139     if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple"))
    140       found_apple = true;
    141     if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
    142       found_keyboard = true;
    143     if (found_apple && found_keyboard)
    144       return EventRewriter::kDeviceAppleKeyboard;
    145   }
    146 
    147   return EventRewriter::kDeviceUnknown;
    148 }
    149 
    150 }  // namespace
    151 
    152 EventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller)
    153     : last_keyboard_device_id_(ui::ED_UNKNOWN_DEVICE),
    154       ime_keyboard_for_testing_(NULL),
    155       pref_service_for_testing_(NULL),
    156       sticky_keys_controller_(sticky_keys_controller),
    157       current_diamond_key_modifier_flags_(ui::EF_NONE) {
    158 }
    159 
    160 EventRewriter::~EventRewriter() {
    161 }
    162 
    163 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedForTesting(
    164     int device_id,
    165     const std::string& device_name) {
    166   // Tests must avoid XI2 reserved device IDs.
    167   DCHECK((device_id < 0) || (device_id > 1));
    168   return KeyboardDeviceAddedInternal(device_id, device_name);
    169 }
    170 
    171 void EventRewriter::RewriteMouseButtonEventForTesting(
    172     const ui::MouseEvent& event,
    173     scoped_ptr<ui::Event>* rewritten_event) {
    174   RewriteMouseButtonEvent(event, rewritten_event);
    175 }
    176 
    177 ui::EventRewriteStatus EventRewriter::RewriteEvent(
    178     const ui::Event& event,
    179     scoped_ptr<ui::Event>* rewritten_event) {
    180   if ((event.type() == ui::ET_KEY_PRESSED) ||
    181       (event.type() == ui::ET_KEY_RELEASED)) {
    182     return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event),
    183                            rewritten_event);
    184   }
    185   if ((event.type() == ui::ET_MOUSE_PRESSED) ||
    186       (event.type() == ui::ET_MOUSE_RELEASED)) {
    187     return RewriteMouseButtonEvent(static_cast<const ui::MouseEvent&>(event),
    188                                    rewritten_event);
    189   }
    190   if (event.type() == ui::ET_MOUSEWHEEL) {
    191     return RewriteMouseWheelEvent(
    192         static_cast<const ui::MouseWheelEvent&>(event), rewritten_event);
    193   }
    194   if ((event.type() == ui::ET_TOUCH_PRESSED) ||
    195       (event.type() == ui::ET_TOUCH_RELEASED)) {
    196     return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event),
    197                              rewritten_event);
    198   }
    199   if (event.IsScrollEvent()) {
    200     return RewriteScrollEvent(static_cast<const ui::ScrollEvent&>(event),
    201                               rewritten_event);
    202   }
    203   return ui::EVENT_REWRITE_CONTINUE;
    204 }
    205 
    206 ui::EventRewriteStatus EventRewriter::NextDispatchEvent(
    207     const ui::Event& last_event,
    208     scoped_ptr<ui::Event>* new_event) {
    209   if (sticky_keys_controller_) {
    210     // In the case of sticky keys, we know what the events obtained here are:
    211     // modifier key releases that match the ones previously discarded. So, we
    212     // know that they don't have to be passed through the post-sticky key
    213     // rewriting phases, |RewriteExtendedKeys()| and |RewriteFunctionKeys()|,
    214     // because those phases do nothing with modifier key releases.
    215     return sticky_keys_controller_->NextDispatchEvent(new_event);
    216   }
    217   NOTREACHED();
    218   return ui::EVENT_REWRITE_CONTINUE;
    219 }
    220 
    221 void EventRewriter::BuildRewrittenKeyEvent(
    222     const ui::KeyEvent& key_event,
    223     ui::KeyboardCode key_code,
    224     int flags,
    225     scoped_ptr<ui::Event>* rewritten_event) {
    226   ui::KeyEvent* rewritten_key_event = NULL;
    227 #if defined(USE_X11)
    228   XEvent* xev = key_event.native_event();
    229   if (xev) {
    230     XEvent xkeyevent;
    231     // Convert all XI2-based key events into X11 core-based key events,
    232     // until consumers no longer depend on receiving X11 core events.
    233     if (xev->type == GenericEvent)
    234       ui::InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent);
    235     else
    236       xkeyevent.xkey = xev->xkey;
    237 
    238     unsigned int original_x11_keycode = xkeyevent.xkey.keycode;
    239     // Update native event to match rewritten |ui::Event|.
    240     // The X11 keycode represents a physical key position, so it shouldn't
    241     // change unless we have actually changed keys, not just modifiers.
    242     // This is one guard against problems like crbug.com/390263.
    243     if (key_event.key_code() != key_code) {
    244       xkeyevent.xkey.keycode =
    245           XKeyCodeForWindowsKeyCode(key_code, flags, gfx::GetXDisplay());
    246     }
    247     ui::KeyEvent x11_key_event(&xkeyevent);
    248     rewritten_key_event = new ui::KeyEvent(x11_key_event);
    249 
    250     // For numpad keys, the key char should always NOT be changed because
    251     // XKeyCodeForWindowsKeyCode method cannot handle non-US keyboard layout.
    252     // The correct key char can be got from original X11 keycode but not for the
    253     // rewritten X11 keycode.
    254     // For Shift+NumpadKey cases, use the rewritten X11 keycode (US layout).
    255     // Please see crbug.com/335644.
    256     if (key_code >= ui::VKEY_NUMPAD0 && key_code <= ui::VKEY_DIVIDE) {
    257       XEvent numpad_xevent;
    258       numpad_xevent.xkey = xkeyevent.xkey;
    259       // Remove the shift state before getting key char.
    260       // Because X11/XKB sometimes returns unexpected key char for
    261       // Shift+NumpadKey. e.g. Shift+Numpad_4 returns 'D', etc.
    262       numpad_xevent.xkey.state &= ~ShiftMask;
    263       numpad_xevent.xkey.state |= Mod2Mask;  // Always set NumLock mask.
    264       if (!(flags & ui::EF_SHIFT_DOWN))
    265         numpad_xevent.xkey.keycode = original_x11_keycode;
    266       rewritten_key_event->set_character(
    267           ui::GetCharacterFromXEvent(&numpad_xevent));
    268     }
    269   }
    270 #endif
    271   if (!rewritten_key_event)
    272     rewritten_key_event = new ui::KeyEvent(key_event);
    273   rewritten_key_event->set_flags(flags);
    274   rewritten_key_event->set_key_code(key_code);
    275 #if defined(USE_X11)
    276   ui::UpdateX11EventForFlags(rewritten_key_event);
    277   rewritten_key_event->NormalizeFlags();
    278 #endif
    279   rewritten_event->reset(rewritten_key_event);
    280 }
    281 
    282 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) {
    283   if (!device_id_to_type_.count(device_id))
    284     KeyboardDeviceAdded(device_id);
    285   last_keyboard_device_id_ = device_id;
    286 }
    287 
    288 const PrefService* EventRewriter::GetPrefService() const {
    289   if (pref_service_for_testing_)
    290     return pref_service_for_testing_;
    291   Profile* profile = ProfileManager::GetActiveUserProfile();
    292   return profile ? profile->GetPrefs() : NULL;
    293 }
    294 
    295 bool EventRewriter::IsAppleKeyboard() const {
    296   if (last_keyboard_device_id_ == ui::ED_UNKNOWN_DEVICE)
    297     return false;
    298 
    299   // Check which device generated |event|.
    300   std::map<int, DeviceType>::const_iterator iter =
    301       device_id_to_type_.find(last_keyboard_device_id_);
    302   if (iter == device_id_to_type_.end()) {
    303     LOG(ERROR) << "Device ID " << last_keyboard_device_id_ << " is unknown.";
    304     return false;
    305   }
    306 
    307   const DeviceType type = iter->second;
    308   return type == kDeviceAppleKeyboard;
    309 }
    310 
    311 bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const {
    312   const PrefService* prefs = GetPrefService();
    313   if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) &&
    314       prefs->GetBoolean(prefs::kLanguageSendFunctionKeys))
    315     return true;
    316 
    317   ash::wm::WindowState* state = ash::wm::GetActiveWindowState();
    318   return state ? state->top_row_keys_are_function_keys() : false;
    319 }
    320 
    321 int EventRewriter::GetRemappedModifierMasks(const PrefService& pref_service,
    322                                             const ui::Event& event,
    323                                             int original_flags) const {
    324   int unmodified_flags = original_flags;
    325   int rewritten_flags = current_diamond_key_modifier_flags_;
    326   for (size_t i = 0; unmodified_flags && (i < arraysize(kModifierRemappings));
    327        ++i) {
    328     const ModifierRemapping* remapped_key = NULL;
    329     if (!(unmodified_flags & kModifierRemappings[i].flag))
    330       continue;
    331     switch (kModifierRemappings[i].flag) {
    332       case ui::EF_COMMAND_DOWN:
    333         // Rewrite Command key presses on an Apple keyboard to Control.
    334         if (IsAppleKeyboard()) {
    335           DCHECK_EQ(ui::EF_CONTROL_DOWN, kModifierRemappingCtrl->flag);
    336           remapped_key = kModifierRemappingCtrl;
    337         }
    338         break;
    339       case ui::EF_MOD3_DOWN:
    340         // If EF_MOD3_DOWN is used by the current input method, leave it alone;
    341         // it is not remappable.
    342         if (IsISOLevel5ShiftUsedByCurrentInputMethod())
    343           continue;
    344         // Otherwise, Mod3Mask is set on X events when the Caps Lock key
    345         // is down, but, if Caps Lock is remapped, CapsLock is NOT set,
    346         // because pressing the key does not invoke caps lock. So, the
    347         // kModifierRemappings[] table uses EF_MOD3_DOWN for the Caps
    348         // Lock remapping.
    349         break;
    350       default:
    351         break;
    352     }
    353     if (!remapped_key && kModifierRemappings[i].pref_name) {
    354       remapped_key =
    355           GetRemappedKey(kModifierRemappings[i].pref_name, pref_service);
    356     }
    357     if (remapped_key) {
    358       unmodified_flags &= ~kModifierRemappings[i].flag;
    359       rewritten_flags |= remapped_key->flag;
    360     }
    361   }
    362   return rewritten_flags | unmodified_flags;
    363 }
    364 
    365 bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode(
    366     const KeyboardRemapping* remappings,
    367     size_t num_remappings,
    368     const MutableKeyState& input,
    369     MutableKeyState* remapped_state) {
    370   for (size_t i = 0; i < num_remappings; ++i) {
    371     const KeyboardRemapping& map = remappings[i];
    372     if (input.key_code != map.input_key_code)
    373       continue;
    374     if ((input.flags & map.input_flags) != map.input_flags)
    375       continue;
    376     remapped_state->key_code = map.output_key_code;
    377     remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags;
    378     return true;
    379   }
    380   return false;
    381 }
    382 
    383 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent(
    384     const ui::KeyEvent& key_event,
    385     scoped_ptr<ui::Event>* rewritten_event) {
    386   if (IsExtensionCommandRegistered(key_event))
    387     return ui::EVENT_REWRITE_CONTINUE;
    388   if (key_event.source_device_id() != ui::ED_UNKNOWN_DEVICE)
    389     DeviceKeyPressedOrReleased(key_event.source_device_id());
    390   MutableKeyState state = {key_event.flags(), key_event.key_code()};
    391   // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
    392   // crbug.com/136465.
    393   if (!(key_event.flags() & ui::EF_FINAL)) {
    394     RewriteModifierKeys(key_event, &state);
    395     RewriteNumPadKeys(key_event, &state);
    396   }
    397   ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
    398   if (sticky_keys_controller_) {
    399     status = sticky_keys_controller_->RewriteKeyEvent(
    400         key_event, state.key_code, &state.flags);
    401     if (status == ui::EVENT_REWRITE_DISCARD)
    402       return ui::EVENT_REWRITE_DISCARD;
    403   }
    404   if (!(key_event.flags() & ui::EF_FINAL)) {
    405     RewriteExtendedKeys(key_event, &state);
    406     RewriteFunctionKeys(key_event, &state);
    407   }
    408   if ((key_event.flags() == state.flags) &&
    409       (key_event.key_code() == state.key_code) &&
    410 #if defined(USE_X11)
    411       // TODO(kpschoedel): This test is present because several consumers of
    412       // key events depend on having a native core X11 event, so we rewrite
    413       // all XI2 key events (GenericEvent) into corresponding core X11 key
    414       // events. Remove this when event consumers no longer care about
    415       // native X11 event details (crbug.com/380349).
    416       (!key_event.HasNativeEvent() ||
    417        (key_event.native_event()->type != GenericEvent)) &&
    418 #endif
    419       (status == ui::EVENT_REWRITE_CONTINUE)) {
    420     return ui::EVENT_REWRITE_CONTINUE;
    421   }
    422   // Sticky keys may have returned a result other than |EVENT_REWRITE_CONTINUE|,
    423   // in which case we need to preserve that return status. Alternatively, we
    424   // might be here because key_event changed, in which case we need to
    425   // return |EVENT_REWRITE_REWRITTEN|.
    426   if (status == ui::EVENT_REWRITE_CONTINUE)
    427     status = ui::EVENT_REWRITE_REWRITTEN;
    428   BuildRewrittenKeyEvent(
    429       key_event, state.key_code, state.flags, rewritten_event);
    430   return status;
    431 }
    432 
    433 ui::EventRewriteStatus EventRewriter::RewriteMouseButtonEvent(
    434     const ui::MouseEvent& mouse_event,
    435     scoped_ptr<ui::Event>* rewritten_event) {
    436   int flags = mouse_event.flags();
    437   RewriteLocatedEvent(mouse_event, &flags);
    438   ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
    439   if (sticky_keys_controller_)
    440     status = sticky_keys_controller_->RewriteMouseEvent(mouse_event, &flags);
    441   int changed_button = ui::EF_NONE;
    442   if ((mouse_event.type() == ui::ET_MOUSE_PRESSED) ||
    443       (mouse_event.type() == ui::ET_MOUSE_RELEASED)) {
    444     changed_button = RewriteModifierClick(mouse_event, &flags);
    445   }
    446   if ((mouse_event.flags() == flags) &&
    447       (status == ui::EVENT_REWRITE_CONTINUE)) {
    448     return ui::EVENT_REWRITE_CONTINUE;
    449   }
    450   if (status == ui::EVENT_REWRITE_CONTINUE)
    451     status = ui::EVENT_REWRITE_REWRITTEN;
    452   ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event);
    453   rewritten_event->reset(rewritten_mouse_event);
    454   rewritten_mouse_event->set_flags(flags);
    455 #if defined(USE_X11)
    456   ui::UpdateX11EventForFlags(rewritten_mouse_event);
    457 #endif
    458   if (changed_button != ui::EF_NONE) {
    459     rewritten_mouse_event->set_changed_button_flags(changed_button);
    460 #if defined(USE_X11)
    461     ui::UpdateX11EventForChangedButtonFlags(rewritten_mouse_event);
    462 #endif
    463   }
    464   return status;
    465 }
    466 
    467 ui::EventRewriteStatus EventRewriter::RewriteMouseWheelEvent(
    468     const ui::MouseWheelEvent& wheel_event,
    469     scoped_ptr<ui::Event>* rewritten_event) {
    470   if (!sticky_keys_controller_)
    471     return ui::EVENT_REWRITE_CONTINUE;
    472   int flags = wheel_event.flags();
    473   ui::EventRewriteStatus status =
    474       sticky_keys_controller_->RewriteMouseEvent(wheel_event, &flags);
    475   if ((wheel_event.flags() == flags) &&
    476       (status == ui::EVENT_REWRITE_CONTINUE)) {
    477     return ui::EVENT_REWRITE_CONTINUE;
    478   }
    479   if (status == ui::EVENT_REWRITE_CONTINUE)
    480     status = ui::EVENT_REWRITE_REWRITTEN;
    481   ui::MouseWheelEvent* rewritten_wheel_event =
    482       new ui::MouseWheelEvent(wheel_event);
    483   rewritten_event->reset(rewritten_wheel_event);
    484   rewritten_wheel_event->set_flags(flags);
    485 #if defined(USE_X11)
    486   ui::UpdateX11EventForFlags(rewritten_wheel_event);
    487 #endif
    488   return status;
    489 }
    490 
    491 ui::EventRewriteStatus EventRewriter::RewriteTouchEvent(
    492     const ui::TouchEvent& touch_event,
    493     scoped_ptr<ui::Event>* rewritten_event) {
    494   int flags = touch_event.flags();
    495   RewriteLocatedEvent(touch_event, &flags);
    496   if (touch_event.flags() == flags)
    497     return ui::EVENT_REWRITE_CONTINUE;
    498   ui::TouchEvent* rewritten_touch_event = new ui::TouchEvent(touch_event);
    499   rewritten_event->reset(rewritten_touch_event);
    500   rewritten_touch_event->set_flags(flags);
    501 #if defined(USE_X11)
    502   ui::UpdateX11EventForFlags(rewritten_touch_event);
    503 #endif
    504   return ui::EVENT_REWRITE_REWRITTEN;
    505 }
    506 
    507 ui::EventRewriteStatus EventRewriter::RewriteScrollEvent(
    508     const ui::ScrollEvent& scroll_event,
    509     scoped_ptr<ui::Event>* rewritten_event) {
    510   int flags = scroll_event.flags();
    511   ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
    512   if (sticky_keys_controller_)
    513     status = sticky_keys_controller_->RewriteScrollEvent(scroll_event, &flags);
    514   if (status == ui::EVENT_REWRITE_CONTINUE)
    515     return status;
    516   ui::ScrollEvent* rewritten_scroll_event = new ui::ScrollEvent(scroll_event);
    517   rewritten_event->reset(rewritten_scroll_event);
    518   rewritten_scroll_event->set_flags(flags);
    519 #if defined(USE_X11)
    520   ui::UpdateX11EventForFlags(rewritten_scroll_event);
    521 #endif
    522   return status;
    523 }
    524 
    525 void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event,
    526                                         MutableKeyState* state) {
    527   DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
    528          key_event.type() == ui::ET_KEY_RELEASED);
    529 
    530   // Do nothing if we have just logged in as guest but have not restarted chrome
    531   // process yet (so we are still on the login screen). In this situations we
    532   // have no user profile so can not do anything useful.
    533   // Note that currently, unlike other accounts, when user logs in as guest, we
    534   // restart chrome process. In future this is to be changed.
    535   // TODO(glotov): remove the following condition when we do not restart chrome
    536   // when user logs in as guest.
    537   // TODO(kpschoedel): check whether this is still necessary.
    538   if (user_manager::UserManager::Get()->IsLoggedInAsGuest() &&
    539       LoginDisplayHostImpl::default_host())
    540     return;
    541 
    542   const PrefService* pref_service = GetPrefService();
    543   if (!pref_service)
    544     return;
    545 
    546   MutableKeyState incoming = *state;
    547   state->flags = ui::EF_NONE;
    548   int characteristic_flag = ui::EF_NONE;
    549 
    550   // First, remap the key code.
    551   const ModifierRemapping* remapped_key = NULL;
    552   switch (incoming.key_code) {
    553     // On Chrome OS, F15 (XF86XK_Launch6) with NumLock (Mod2Mask) is sent
    554     // when Diamond key is pressed.
    555     case ui::VKEY_F15:
    556       // When diamond key is not available, the configuration UI for Diamond
    557       // key is not shown. Therefore, ignore the kLanguageRemapDiamondKeyTo
    558       // syncable pref.
    559       if (HasDiamondKey())
    560         remapped_key =
    561             GetRemappedKey(prefs::kLanguageRemapDiamondKeyTo, *pref_service);
    562       // Default behavior of F15 is Control, even if --has-chromeos-diamond-key
    563       // is absent, according to unit test comments.
    564       if (!remapped_key) {
    565         DCHECK_EQ(ui::VKEY_CONTROL, kModifierRemappingCtrl->key_code);
    566         remapped_key = kModifierRemappingCtrl;
    567       }
    568       // F15 is not a modifier key, so we need to track its state directly.
    569       if (key_event.type() == ui::ET_KEY_PRESSED) {
    570         int remapped_flag = remapped_key->flag;
    571         if (remapped_key->remap_to == input_method::kCapsLockKey)
    572           remapped_flag |= ui::EF_CAPS_LOCK_DOWN;
    573         current_diamond_key_modifier_flags_ = remapped_flag;
    574       } else {
    575         current_diamond_key_modifier_flags_ = ui::EF_NONE;
    576       }
    577       break;
    578     // On Chrome OS, XF86XK_Launch7 (F16) with Mod3Mask is sent when Caps Lock
    579     // is pressed (with one exception: when
    580     // IsISOLevel5ShiftUsedByCurrentInputMethod() is true, the key generates
    581     // XK_ISO_Level3_Shift with Mod3Mask, not XF86XK_Launch7).
    582     case ui::VKEY_F16:
    583       characteristic_flag = ui::EF_CAPS_LOCK_DOWN;
    584       remapped_key =
    585           GetRemappedKey(prefs::kLanguageRemapCapsLockKeyTo, *pref_service);
    586       break;
    587     case ui::VKEY_LWIN:
    588     case ui::VKEY_RWIN:
    589       characteristic_flag = ui::EF_COMMAND_DOWN;
    590       // Rewrite Command-L/R key presses on an Apple keyboard to Control.
    591       if (IsAppleKeyboard()) {
    592         DCHECK_EQ(ui::VKEY_CONTROL, kModifierRemappingCtrl->key_code);
    593         remapped_key = kModifierRemappingCtrl;
    594       } else {
    595         remapped_key =
    596             GetRemappedKey(prefs::kLanguageRemapSearchKeyTo, *pref_service);
    597       }
    598       // Default behavior is Super key, hence don't remap the event if the pref
    599       // is unavailable.
    600       break;
    601     case ui::VKEY_CONTROL:
    602       characteristic_flag = ui::EF_CONTROL_DOWN;
    603       remapped_key =
    604           GetRemappedKey(prefs::kLanguageRemapControlKeyTo, *pref_service);
    605       break;
    606     case ui::VKEY_MENU:
    607       // ALT key
    608       characteristic_flag = ui::EF_ALT_DOWN;
    609       remapped_key =
    610           GetRemappedKey(prefs::kLanguageRemapAltKeyTo, *pref_service);
    611       break;
    612     default:
    613       break;
    614   }
    615 
    616   if (remapped_key) {
    617     state->key_code = remapped_key->key_code;
    618     incoming.flags |= characteristic_flag;
    619     characteristic_flag = remapped_key->flag;
    620   }
    621 
    622   // Next, remap modifier bits.
    623   state->flags |=
    624       GetRemappedModifierMasks(*pref_service, key_event, incoming.flags);
    625   if (key_event.type() == ui::ET_KEY_PRESSED)
    626     state->flags |= characteristic_flag;
    627   else
    628     state->flags &= ~characteristic_flag;
    629 
    630   // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
    631   // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
    632   // keyboard is pressed) since X can handle that case.
    633   if (key_event.type() == ui::ET_KEY_PRESSED &&
    634       incoming.key_code != ui::VKEY_CAPITAL &&
    635       state->key_code == ui::VKEY_CAPITAL) {
    636     chromeos::input_method::ImeKeyboard* ime_keyboard =
    637         ime_keyboard_for_testing_
    638             ? ime_keyboard_for_testing_
    639             : chromeos::input_method::InputMethodManager::Get()
    640                   ->GetImeKeyboard();
    641     ime_keyboard->SetCapsLockEnabled(!ime_keyboard->CapsLockIsEnabled());
    642   }
    643 }
    644 
    645 void EventRewriter::RewriteNumPadKeys(const ui::KeyEvent& key_event,
    646                                       MutableKeyState* state) {
    647   DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
    648          key_event.type() == ui::ET_KEY_RELEASED);
    649   if (!(state->flags & ui::EF_NUMPAD_KEY))
    650     return;
    651   MutableKeyState incoming = *state;
    652 
    653   static const KeyboardRemapping kNumPadRemappings[] = {
    654       {ui::VKEY_INSERT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD0, ui::EF_NUMPAD_KEY},
    655       {ui::VKEY_DELETE, ui::EF_NUMPAD_KEY, ui::VKEY_DECIMAL, ui::EF_NUMPAD_KEY},
    656       {ui::VKEY_END, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD1, ui::EF_NUMPAD_KEY},
    657       {ui::VKEY_DOWN, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD2, ui::EF_NUMPAD_KEY},
    658       {ui::VKEY_NEXT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD3, ui::EF_NUMPAD_KEY},
    659       {ui::VKEY_LEFT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD4, ui::EF_NUMPAD_KEY},
    660       {ui::VKEY_CLEAR, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD5, ui::EF_NUMPAD_KEY},
    661       {ui::VKEY_RIGHT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD6, ui::EF_NUMPAD_KEY},
    662       {ui::VKEY_HOME, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD7, ui::EF_NUMPAD_KEY},
    663       {ui::VKEY_UP, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD8, ui::EF_NUMPAD_KEY},
    664       {ui::VKEY_PRIOR, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD9, ui::EF_NUMPAD_KEY},
    665   };
    666 
    667   RewriteWithKeyboardRemappingsByKeyCode(
    668       kNumPadRemappings, arraysize(kNumPadRemappings), incoming, state);
    669 }
    670 
    671 void EventRewriter::RewriteExtendedKeys(const ui::KeyEvent& key_event,
    672                                         MutableKeyState* state) {
    673   DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
    674          key_event.type() == ui::ET_KEY_RELEASED);
    675 
    676   MutableKeyState incoming = *state;
    677   bool rewritten = false;
    678 
    679   if ((incoming.flags & (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) ==
    680       (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) {
    681     // Allow Search to avoid rewriting extended keys.
    682     static const KeyboardRemapping kAvoidRemappings[] = {
    683         {  // Alt+Backspace
    684          ui::VKEY_BACK, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_BACK,
    685          ui::EF_ALT_DOWN,
    686         },
    687         {  // Control+Alt+Up
    688          ui::VKEY_UP,
    689          ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN,
    690          ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
    691         },
    692         {  // Alt+Up
    693          ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_UP,
    694          ui::EF_ALT_DOWN,
    695         },
    696         {  // Control+Alt+Down
    697          ui::VKEY_DOWN,
    698          ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN,
    699          ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
    700         },
    701         {  // Alt+Down
    702          ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_DOWN,
    703          ui::EF_ALT_DOWN,
    704         }};
    705 
    706     rewritten = RewriteWithKeyboardRemappingsByKeyCode(
    707         kAvoidRemappings, arraysize(kAvoidRemappings), incoming, state);
    708   }
    709 
    710   if (!rewritten && (incoming.flags & ui::EF_COMMAND_DOWN)) {
    711     static const KeyboardRemapping kSearchRemappings[] = {
    712         {  // Search+BackSpace -> Delete
    713          ui::VKEY_BACK, ui::EF_COMMAND_DOWN, ui::VKEY_DELETE, 0},
    714         {  // Search+Left -> Home
    715          ui::VKEY_LEFT, ui::EF_COMMAND_DOWN, ui::VKEY_HOME, 0},
    716         {  // Search+Up -> Prior (aka PageUp)
    717          ui::VKEY_UP, ui::EF_COMMAND_DOWN, ui::VKEY_PRIOR, 0},
    718         {  // Search+Right -> End
    719          ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN, ui::VKEY_END, 0},
    720         {  // Search+Down -> Next (aka PageDown)
    721          ui::VKEY_DOWN, ui::EF_COMMAND_DOWN, ui::VKEY_NEXT, 0},
    722         {  // Search+Period -> Insert
    723          ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN, ui::VKEY_INSERT, 0}};
    724 
    725     rewritten = RewriteWithKeyboardRemappingsByKeyCode(
    726         kSearchRemappings, arraysize(kSearchRemappings), incoming, state);
    727   }
    728 
    729   if (!rewritten && (incoming.flags & ui::EF_ALT_DOWN)) {
    730     static const KeyboardRemapping kNonSearchRemappings[] = {
    731         {  // Alt+BackSpace -> Delete
    732          ui::VKEY_BACK, ui::EF_ALT_DOWN, ui::VKEY_DELETE, 0},
    733         {  // Control+Alt+Up -> Home
    734          ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::VKEY_HOME, 0},
    735         {  // Alt+Up -> Prior (aka PageUp)
    736          ui::VKEY_UP, ui::EF_ALT_DOWN, ui::VKEY_PRIOR, 0},
    737         {  // Control+Alt+Down -> End
    738          ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::VKEY_END, 0},
    739         {  // Alt+Down -> Next (aka PageDown)
    740          ui::VKEY_DOWN, ui::EF_ALT_DOWN, ui::VKEY_NEXT, 0}};
    741 
    742     rewritten = RewriteWithKeyboardRemappingsByKeyCode(
    743         kNonSearchRemappings, arraysize(kNonSearchRemappings), incoming, state);
    744   }
    745 }
    746 
    747 void EventRewriter::RewriteFunctionKeys(const ui::KeyEvent& key_event,
    748                                         MutableKeyState* state) {
    749   CHECK(key_event.type() == ui::ET_KEY_PRESSED ||
    750         key_event.type() == ui::ET_KEY_RELEASED);
    751   MutableKeyState incoming = *state;
    752   bool rewritten = false;
    753 
    754   if ((incoming.key_code >= ui::VKEY_F1) &&
    755       (incoming.key_code <= ui::VKEY_F24)) {
    756     // By default the top row (F1-F12) keys are system keys for back, forward,
    757     // brightness, volume, etc. However, windows for v2 apps can optionally
    758     // request raw function keys for these keys.
    759     bool top_row_keys_are_function_keys = TopRowKeysAreFunctionKeys(key_event);
    760     bool search_is_pressed = (incoming.flags & ui::EF_COMMAND_DOWN) != 0;
    761 
    762     //  Search? Top Row   Result
    763     //  ------- --------  ------
    764     //  No      Fn        Unchanged
    765     //  No      System    Fn -> System
    766     //  Yes     Fn        Fn -> System
    767     //  Yes     System    Search+Fn -> Fn
    768     if (top_row_keys_are_function_keys == search_is_pressed) {
    769       // Rewrite the F1-F12 keys on a Chromebook keyboard to system keys.
    770       static const KeyboardRemapping kFkeysToSystemKeys[] = {
    771           {ui::VKEY_F1, 0, ui::VKEY_BROWSER_BACK, 0},
    772           {ui::VKEY_F2, 0, ui::VKEY_BROWSER_FORWARD, 0},
    773           {ui::VKEY_F3, 0, ui::VKEY_BROWSER_REFRESH, 0},
    774           {ui::VKEY_F4, 0, ui::VKEY_MEDIA_LAUNCH_APP2, 0},
    775           {ui::VKEY_F5, 0, ui::VKEY_MEDIA_LAUNCH_APP1, 0},
    776           {ui::VKEY_F6, 0, ui::VKEY_BRIGHTNESS_DOWN, 0},
    777           {ui::VKEY_F7, 0, ui::VKEY_BRIGHTNESS_UP, 0},
    778           {ui::VKEY_F8, 0, ui::VKEY_VOLUME_MUTE, 0},
    779           {ui::VKEY_F9, 0, ui::VKEY_VOLUME_DOWN, 0},
    780           {ui::VKEY_F10, 0, ui::VKEY_VOLUME_UP, 0},
    781       };
    782       MutableKeyState incoming_without_command = incoming;
    783       incoming_without_command.flags &= ~ui::EF_COMMAND_DOWN;
    784       rewritten =
    785           RewriteWithKeyboardRemappingsByKeyCode(kFkeysToSystemKeys,
    786                                                  arraysize(kFkeysToSystemKeys),
    787                                                  incoming_without_command,
    788                                                  state);
    789     } else if (search_is_pressed) {
    790       // Allow Search to avoid rewriting F1-F12.
    791       state->flags &= ~ui::EF_COMMAND_DOWN;
    792       rewritten = true;
    793     }
    794   }
    795 
    796   if (!rewritten && (incoming.flags & ui::EF_COMMAND_DOWN)) {
    797     // Remap Search+<number> to F<number>.
    798     // We check the keycode here instead of the keysym, as these keys have
    799     // different keysyms when modifiers are pressed, such as shift.
    800 
    801     // TODO(danakj): On some i18n keyboards, these choices will be bad and we
    802     // should make layout-specific choices here. For eg. on a french keyboard
    803     // "-" and "6" are the same key, so F11 will not be accessible.
    804     static const KeyboardRemapping kNumberKeysToFkeys[] = {
    805         {ui::VKEY_1, ui::EF_COMMAND_DOWN, ui::VKEY_F1, 0},
    806         {ui::VKEY_2, ui::EF_COMMAND_DOWN, ui::VKEY_F2, 0},
    807         {ui::VKEY_3, ui::EF_COMMAND_DOWN, ui::VKEY_F3, 0},
    808         {ui::VKEY_4, ui::EF_COMMAND_DOWN, ui::VKEY_F4, 0},
    809         {ui::VKEY_5, ui::EF_COMMAND_DOWN, ui::VKEY_F5, 0},
    810         {ui::VKEY_6, ui::EF_COMMAND_DOWN, ui::VKEY_F6, 0},
    811         {ui::VKEY_7, ui::EF_COMMAND_DOWN, ui::VKEY_F7, 0},
    812         {ui::VKEY_8, ui::EF_COMMAND_DOWN, ui::VKEY_F8, 0},
    813         {ui::VKEY_9, ui::EF_COMMAND_DOWN, ui::VKEY_F9, 0},
    814         {ui::VKEY_0, ui::EF_COMMAND_DOWN, ui::VKEY_F10, 0},
    815         {ui::VKEY_OEM_MINUS, ui::EF_COMMAND_DOWN, ui::VKEY_F11, 0},
    816         {ui::VKEY_OEM_PLUS, ui::EF_COMMAND_DOWN, ui::VKEY_F12, 0}};
    817     rewritten = RewriteWithKeyboardRemappingsByKeyCode(
    818         kNumberKeysToFkeys, arraysize(kNumberKeysToFkeys), incoming, state);
    819   }
    820 }
    821 
    822 void EventRewriter::RewriteLocatedEvent(const ui::Event& event,
    823                                         int* flags) {
    824   const PrefService* pref_service = GetPrefService();
    825   if (!pref_service)
    826     return;
    827   *flags = GetRemappedModifierMasks(*pref_service, event, *flags);
    828 }
    829 
    830 int EventRewriter::RewriteModifierClick(const ui::MouseEvent& mouse_event,
    831                                         int* flags) {
    832   // Remap Alt+Button1 to Button3.
    833   const int kAltLeftButton = (ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON);
    834   if (((*flags & kAltLeftButton) == kAltLeftButton) &&
    835       ((mouse_event.type() == ui::ET_MOUSE_PRESSED) ||
    836        pressed_device_ids_.count(mouse_event.source_device_id()))) {
    837     *flags &= ~kAltLeftButton;
    838     *flags |= ui::EF_RIGHT_MOUSE_BUTTON;
    839     if (mouse_event.type() == ui::ET_MOUSE_PRESSED)
    840       pressed_device_ids_.insert(mouse_event.source_device_id());
    841     else
    842       pressed_device_ids_.erase(mouse_event.source_device_id());
    843     return ui::EF_RIGHT_MOUSE_BUTTON;
    844   }
    845   return ui::EF_NONE;
    846 }
    847 
    848 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedInternal(
    849     int device_id,
    850     const std::string& device_name) {
    851   const DeviceType type = GetDeviceType(device_name);
    852   if (type == kDeviceAppleKeyboard) {
    853     VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
    854             << "id=" << device_id;
    855   }
    856   // Always overwrite the existing device_id since the X server may reuse a
    857   // device id for an unattached device.
    858   device_id_to_type_[device_id] = type;
    859   return type;
    860 }
    861 
    862 void EventRewriter::KeyboardDeviceAdded(int device_id) {
    863 #if defined(USE_X11)
    864   DCHECK_NE(XIAllDevices, device_id);
    865   DCHECK_NE(XIAllMasterDevices, device_id);
    866   if (device_id == XIAllDevices || device_id == XIAllMasterDevices) {
    867     LOG(ERROR) << "Unexpected device_id passed: " << device_id;
    868     return;
    869   }
    870 
    871   int ndevices_return = 0;
    872   XIDeviceInfo* device_info =
    873       XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return);
    874 
    875   // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices,
    876   // the number of devices found should be either 0 (not found) or 1.
    877   if (!device_info) {
    878     LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown.";
    879     return;
    880   }
    881 
    882   DCHECK_EQ(1, ndevices_return);
    883   for (int i = 0; i < ndevices_return; ++i) {
    884     DCHECK_EQ(device_id, device_info[i].deviceid);  // see the comment above.
    885     DCHECK(device_info[i].name);
    886     KeyboardDeviceAddedInternal(device_info[i].deviceid, device_info[i].name);
    887   }
    888 
    889   XIFreeDeviceInfo(device_info);
    890 #else
    891   KeyboardDeviceAddedInternal(device_id, "keyboard");
    892 #endif
    893 }
    894 
    895 }  // namespace chromeos
    896