event_rewriter.h revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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#ifndef CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
6#define CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
7
8#include <map>
9#include <set>
10#include <string>
11
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 "chrome/browser/chromeos/device_hierarchy_observer.h"
17#include "chromeos/ime/ime_keyboard.h"
18#include "ui/events/keycodes/keyboard_codes.h"
19#include "ui/events/platform/platform_event_observer.h"
20
21class PrefService;
22typedef union _XEvent XEvent;
23
24namespace chromeos {
25namespace input_method {
26class ImeKeyboard;
27}
28
29class EventRewriter : public DeviceHierarchyObserver,
30                      public ui::PlatformEventObserver {
31 public:
32  enum DeviceType {
33    kDeviceUnknown = 0,
34    kDeviceAppleKeyboard,
35  };
36
37  EventRewriter();
38  virtual ~EventRewriter();
39
40  // Calls DeviceAddedInternal.
41  DeviceType DeviceAddedForTesting(int device_id,
42                                   const std::string& device_name);
43  // Calls Rewrite.
44  void RewriteForTesting(XEvent* event);
45
46  const std::map<int, DeviceType>& device_id_to_type_for_testing() const {
47    return device_id_to_type_;
48  }
49  void set_last_device_id_for_testing(int device_id) {
50    last_device_id_ = device_id;
51  }
52  void set_pref_service_for_testing(const PrefService* pref_service) {
53    pref_service_for_testing_ = pref_service;
54  }
55  void set_keyboard_for_testing(input_method::ImeKeyboard* keyboard) {
56    keyboard_for_testing_ = keyboard;
57  }
58
59  // Gets DeviceType from the |device_name|.
60  static DeviceType GetDeviceType(const std::string& device_name);
61
62 private:
63  friend class EventRewriterAshTest;
64  friend class EventRewriterTest;
65
66  void DeviceKeyPressedOrReleased(int device_id);
67
68  // ui::PlatformEventObserver:
69  virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
70  virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
71
72  // DeviceHierarchyObserver:
73  virtual void DeviceHierarchyChanged() OVERRIDE;
74  virtual void DeviceAdded(int device_id) OVERRIDE;
75  virtual void DeviceRemoved(int device_id) OVERRIDE;
76
77  // We don't want to include Xlib.h here since it has polluting macros, so
78  // define these locally.
79  typedef unsigned long KeySym;
80  typedef unsigned char KeyCode;
81
82  // Updates |*_xkeycode_| in response to a keyboard map change.
83  void RefreshKeycodes();
84  // Converts an X key symbol like XK_Control_L to a key code.
85  unsigned char NativeKeySymToNativeKeycode(KeySym keysym);
86
87  struct KeyboardRemapping {
88    KeySym input_keysym;
89    unsigned int input_native_mods;
90    KeySym output_keysym;
91    unsigned int output_native_mods;
92  };
93
94  // Returns true if the target for |event| would prefer to receive raw function
95  // keys instead of having them rewritten into back, forward, brightness,
96  // volume, etc. or if the user has specified that they desire top-row keys to
97  // be treated as function keys globally.
98  bool TopRowKeysAreFunctionKeys(XEvent* event) const;
99
100  // Given a set of KeyboardRemapping structs, it finds a matching struct
101  // if possible, and updates the remapped event values. Returns true if a
102  // remapping was found and remapped values were updated.
103  bool RewriteWithKeyboardRemappingsByKeySym(
104      const KeyboardRemapping* remappings,
105      size_t num_remappings,
106      KeySym keysym,
107      unsigned int native_mods,
108      KeySym* remapped_native_keysym,
109      unsigned int* remapped_native_mods);
110
111  // Given a set of KeyboardRemapping structs, it finds a matching struct
112  // if possible, and updates the remapped event values. This function converts
113  // the KeySym in the KeyboardRemapping struct into the KeyCode before matching
114  // to allow any KeyCode on the same physical key as the given KeySym to match.
115  // Returns true if a remapping was found and remapped values were updated.
116  bool RewriteWithKeyboardRemappingsByKeyCode(
117      const KeyboardRemapping* remappings,
118      size_t num_remappings,
119      KeyCode keycode,
120      unsigned int native_mods,
121      KeySym* remapped_native_keysym,
122      unsigned int* remapped_native_mods);
123
124  // Returns the PrefService that should be used.
125  const PrefService* GetPrefService() const;
126
127  // Rewrites the |event| by applying all RewriteXXX functions as needed.
128  void Rewrite(XEvent* event);
129
130  // Rewrites a modifier key press/release following the current user
131  // preferences.
132  bool RewriteModifiers(XEvent* event);
133
134  // Rewrites Fn key press/release to Control. In some cases, Fn key is not
135  // intercepted by the EC, but generates a key event like "XK_F15 + Mod3Mask"
136  // as shown in crosbug.com/p/14339.
137  bool RewriteFnKey(XEvent* event);
138
139  // Rewrites a NumPad key press/release without Num Lock to a corresponding key
140  // press/release with the lock.  Returns true when |event| is rewritten.
141  bool RewriteNumPadKeys(XEvent* event);
142
143  // Rewrites Backspace and Arrow keys following the Chrome OS keyboard spec.
144  //  * Alt+Backspace -> Delete
145  //  * Alt+Up -> Prior (aka PageUp)
146  //  * Alt+Down -> Next (aka PageDown)
147  //  * Ctrl+Alt+Up -> Home
148  //  * Ctrl+Alt+Down -> End
149  // When the Search key acts as a function key, it instead maps:
150  //  * Search+Backspace -> Delete
151  //  * Search+Up -> Prior (aka PageUp)
152  //  * Search+Down -> Next (aka PageDown)
153  //  * Search+Left -> Home
154  //  * Search+Right -> End
155  //  * Search+. -> Insert
156  // Returns true when the |event| is rewritten.
157  bool RewriteExtendedKeys(XEvent* event);
158
159  // When the Search key acts as a function key, it remaps Search+1
160  // through Search+= to F1 through F12. Returns true when the |event| is
161  // rewritten.
162  bool RewriteFunctionKeys(XEvent* event);
163
164  // Rewrites the located |event|.
165  void RewriteLocatedEvent(XEvent* event);
166
167  // Overwrites |event| with the keycodes and flags.
168  void OverwriteEvent(XEvent* event,
169                      unsigned int new_native_keycode,
170                      unsigned int new_native_state);
171
172  // Checks the type of the |device_name|, and inserts a new entry to
173  // |device_id_to_type_|.
174  DeviceType DeviceAddedInternal(int device_id, const std::string& device_name);
175
176  // Returns true if |last_device_id_| is Apple's.
177  bool IsAppleKeyboard() const;
178
179  // Remaps |original_native_modifiers| to |remapped_native_modifiers| following
180  // the current user prefs.
181  void GetRemappedModifierMasks(unsigned int original_native_modifiers,
182                                unsigned int* remapped_native_modifiers) const;
183
184  std::map<int, DeviceType> device_id_to_type_;
185  int last_device_id_;
186
187  // A mapping from X11 KeySym keys to KeyCode values.
188  base::hash_map<unsigned long, unsigned long> keysym_to_keycode_map_;
189
190  // A set of device IDs whose press event has been rewritten.
191  std::set<int> pressed_device_ids_;
192
193  input_method::ImeKeyboard* keyboard_for_testing_;
194
195  const PrefService* pref_service_for_testing_;
196
197  DISALLOW_COPY_AND_ASSIGN(EventRewriter);
198};
199
200}  // namespace chromeos
201
202#endif  // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
203