Home | History | Annotate | Download | only in ash
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_
      6 #define CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "ash/event_rewriter_delegate.h"
     12 #include "base/basictypes.h"
     13 #include "base/compiler_specific.h"
     14 #include "base/containers/hash_tables.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "ui/aura/root_window_observer.h"
     17 #include "ui/events/keycodes/keyboard_codes.h"
     18 
     19 #if defined(OS_CHROMEOS)
     20 #include "chrome/browser/chromeos/device_hierarchy_observer.h"
     21 #endif
     22 
     23 class PrefService;
     24 
     25 namespace aura {
     26 class RootWindow;
     27 }
     28 
     29 #if defined(OS_CHROMEOS)
     30 namespace chromeos {
     31 
     32 class KeyboardDrivenEventRewriter;
     33 
     34 namespace input_method {
     35 class XKeyboard;
     36 }
     37 }
     38 #endif
     39 
     40 class EventRewriter : public ash::EventRewriterDelegate,
     41                       public aura::RootWindowObserver
     42 #if defined(OS_CHROMEOS)
     43                     , public chromeos::DeviceHierarchyObserver
     44 #endif
     45 {
     46  public:
     47   enum DeviceType {
     48     kDeviceUnknown = 0,
     49     kDeviceAppleKeyboard,
     50   };
     51 
     52   EventRewriter();
     53   virtual ~EventRewriter();
     54 
     55   // Calls DeviceAddedInternal.
     56   DeviceType DeviceAddedForTesting(int device_id,
     57                                    const std::string& device_name);
     58   // Calls Rewrite.
     59   void RewriteForTesting(ui::KeyEvent* event);
     60 
     61   const std::map<int, DeviceType>& device_id_to_type_for_testing() const {
     62     return device_id_to_type_;
     63   }
     64   void set_last_device_id_for_testing(int device_id) {
     65     last_device_id_ = device_id;
     66   }
     67   void set_pref_service_for_testing(const PrefService* pref_service) {
     68     pref_service_for_testing_ = pref_service;
     69   }
     70 #if defined(OS_CHROMEOS)
     71   void set_xkeyboard_for_testing(chromeos::input_method::XKeyboard* xkeyboard) {
     72     xkeyboard_for_testing_ = xkeyboard;
     73   }
     74 #endif
     75 
     76   // Gets DeviceType from the |device_name|.
     77   static DeviceType GetDeviceType(const std::string& device_name);
     78 
     79  private:
     80   friend class EventRewriterAshTest;
     81 
     82   // ash::EventRewriterDelegate overrides:
     83   virtual ash::EventRewriterDelegate::Action RewriteOrFilterKeyEvent(
     84       ui::KeyEvent* event) OVERRIDE;
     85   virtual ash::EventRewriterDelegate::Action RewriteOrFilterLocatedEvent(
     86       ui::LocatedEvent* event) OVERRIDE;
     87 
     88   // aura::RootWindowObserver overrides:
     89   virtual void OnKeyboardMappingChanged(const aura::RootWindow* root) OVERRIDE;
     90 
     91 #if defined(OS_CHROMEOS)
     92   // chromeos::DeviceHierarchyObserver overrides:
     93   virtual void DeviceHierarchyChanged() OVERRIDE {}
     94   virtual void DeviceAdded(int device_id) OVERRIDE;
     95   virtual void DeviceRemoved(int device_id) OVERRIDE;
     96   virtual void DeviceKeyPressedOrReleased(int device_id) OVERRIDE;
     97 
     98   // We don't want to include Xlib.h here since it has polluting macros, so
     99   // define these locally.
    100   typedef unsigned long KeySym;
    101   typedef unsigned char KeyCode;
    102 
    103   // Updates |*_xkeycode_| in response to a keyboard map change.
    104   void RefreshKeycodes();
    105   // Converts an X key symbol like XK_Control_L to a key code.
    106   unsigned char NativeKeySymToNativeKeycode(KeySym keysym);
    107 
    108   struct KeyboardRemapping {
    109     KeySym input_keysym;
    110     unsigned int input_mods;
    111     unsigned int input_native_mods;
    112     KeySym output_keysym;
    113     ui::KeyboardCode output_keycode;
    114     unsigned int output_mods;
    115     unsigned int output_native_mods;
    116   };
    117 
    118   // Returns true if the target for |event| would prefer to receive raw function
    119   // keys instead of having them rewritten into back, forward, brightness,
    120   // volume, etc. or if the user has specified that they desire top-row keys to
    121   // be treated as function keys globally.
    122   bool TopRowKeysAreFunctionKeys(ui::KeyEvent* event) const;
    123 
    124   // Given a set of KeyboardRemapping structs, it finds a matching struct
    125   // if possible, and updates the remapped event values. Returns true if a
    126   // remapping was found and remapped values were updated.
    127   bool RewriteWithKeyboardRemappingsByKeySym(
    128       const KeyboardRemapping* remappings,
    129       size_t num_remappings,
    130       KeySym keysym,
    131       unsigned int native_mods,
    132       unsigned int mods,
    133       KeySym* remapped_native_keysym,
    134       unsigned int* remapped_native_mods,
    135       ui::KeyboardCode* remapped_keycode,
    136       unsigned int* remapped_mods);
    137 
    138   // Given a set of KeyboardRemapping structs, it finds a matching struct
    139   // if possible, and updates the remapped event values. This function converts
    140   // the KeySym in the KeyboardRemapping struct into the KeyCode before matching
    141   // to allow any KeyCode on the same physical key as the given KeySym to match.
    142   // Returns true if a remapping was found and remapped values were updated.
    143   bool RewriteWithKeyboardRemappingsByKeyCode(
    144       const KeyboardRemapping* remappings,
    145       size_t num_remappings,
    146       KeyCode keycode,
    147       unsigned int native_mods,
    148       unsigned int mods,
    149       KeySym* remapped_native_keysym,
    150       unsigned int* remapped_native_mods,
    151       ui::KeyboardCode* remapped_keycode,
    152       unsigned int* remapped_mods);
    153 #endif
    154 
    155   // Returns the PrefService that should be used.
    156   const PrefService* GetPrefService() const;
    157 
    158   // Rewrites the |event| by applying all RewriteXXX functions as needed.
    159   void Rewrite(ui::KeyEvent* event);
    160 
    161   // Rewrites a modifier key press/release following the current user
    162   // preferences.
    163   bool RewriteModifiers(ui::KeyEvent* event);
    164 
    165   // Rewrites Fn key press/release to Control. In some cases, Fn key is not
    166   // intercepted by the EC, but generates a key event like "XK_F15 + Mod3Mask"
    167   // as shown in crosbug.com/p/14339.
    168   bool RewriteFnKey(ui::KeyEvent* event);
    169 
    170   // Rewrites a NumPad key press/release without Num Lock to a corresponding key
    171   // press/release with the lock.  Returns true when |event| is rewritten.
    172   bool RewriteNumPadKeys(ui::KeyEvent* event);
    173 
    174   // Rewrites Backspace and Arrow keys following the Chrome OS keyboard spec.
    175   //  * Alt+Backspace -> Delete
    176   //  * Alt+Up -> Prior (aka PageUp)
    177   //  * Alt+Down -> Next (aka PageDown)
    178   //  * Ctrl+Alt+Up -> Home
    179   //  * Ctrl+Alt+Down -> End
    180   // When the Search key acts as a function key, it instead maps:
    181   //  * Search+Backspace -> Delete
    182   //  * Search+Up -> Prior (aka PageUp)
    183   //  * Search+Down -> Next (aka PageDown)
    184   //  * Search+Left -> Home
    185   //  * Search+Right -> End
    186   //  * Search+. -> Insert
    187   // Returns true when the |event| is rewritten.
    188   bool RewriteExtendedKeys(ui::KeyEvent* event);
    189 
    190   // When the Search key acts as a function key, it remaps Search+1
    191   // through Search+= to F1 through F12. Returns true when the |event| is
    192   // rewritten.
    193   bool RewriteFunctionKeys(ui::KeyEvent* event);
    194 
    195   // Rewrites the located |event|.
    196   void RewriteLocatedEvent(ui::LocatedEvent* event);
    197 
    198   // Overwrites |event| with the keycodes and flags.
    199   void OverwriteEvent(ui::KeyEvent* event,
    200                       unsigned int new_native_keycode,
    201                       unsigned int new_native_state,
    202                       ui::KeyboardCode new_keycode,
    203                       int new_flags);
    204 
    205   // Checks the type of the |device_name|, and inserts a new entry to
    206   // |device_id_to_type_|.
    207   DeviceType DeviceAddedInternal(int device_id, const std::string& device_name);
    208 
    209   // Returns true if |last_device_id_| is Apple's.
    210   bool IsAppleKeyboard() const;
    211 
    212   // Remaps |original_flags| to |remapped_flags| and |original_native_modifiers|
    213   // to |remapped_native_modifiers| following the current user prefs.
    214   void GetRemappedModifierMasks(int original_flags,
    215                                 unsigned int original_native_modifiers,
    216                                 int* remapped_flags,
    217                                 unsigned int* remapped_native_modifiers) const;
    218 
    219   std::map<int, DeviceType> device_id_to_type_;
    220   int last_device_id_;
    221 
    222 #if defined(OS_CHROMEOS)
    223   // A mapping from X11 KeySym keys to KeyCode values.
    224   base::hash_map<unsigned long, unsigned long> keysym_to_keycode_map_;
    225 
    226   chromeos::input_method::XKeyboard* xkeyboard_for_testing_;
    227 
    228   scoped_ptr<chromeos::KeyboardDrivenEventRewriter>
    229       keyboard_driven_event_rewriter_;
    230 #endif
    231 
    232   const PrefService* pref_service_for_testing_;
    233 
    234   DISALLOW_COPY_AND_ASSIGN(EventRewriter);
    235 };
    236 
    237 #endif  // CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_
    238