OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ | 5 #ifndef CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ |
6 #define CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ | 6 #define CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ |
7 | 7 |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/basictypes.h" | |
13 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
14 #include "base/containers/hash_tables.h" | 13 #include "base/containers/hash_tables.h" |
15 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 15 #include "ui/events/event.h" |
| 16 #include "ui/events/event_rewriter.h" |
| 17 |
| 18 #if defined(USE_X11) |
16 #include "chrome/browser/chromeos/device_hierarchy_observer.h" | 19 #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 #include "ui/events/platform/platform_event_observer.h" |
| 21 typedef union _XEvent XEvent; |
| 22 #endif |
20 | 23 |
21 class PrefService; | 24 class PrefService; |
22 typedef union _XEvent XEvent; | |
23 | 25 |
24 namespace chromeos { | 26 namespace chromeos { |
25 namespace input_method { | 27 namespace input_method { |
26 class ImeKeyboard; | 28 class ImeKeyboard; |
27 } | 29 } |
28 | 30 |
29 class EventRewriter : public DeviceHierarchyObserver, | 31 // EventRewriter makes various changes to keyboard-related events, |
30 public ui::PlatformEventObserver { | 32 // including KeyEvents and some other events with keyboard modifier flags: |
| 33 // - maps modifiers keys (Control, Alt, Search, Caps, Diamond) according |
| 34 // to user preferences; |
| 35 // - maps Command to Control on Apple keyboards; |
| 36 // - converts numeric pad editing keys to their numeric forms; |
| 37 // - converts top-row function keys to special keys where necessary; |
| 38 // - handles various key combinations like Search+Backspace -> Delete |
| 39 // and Search+number to Fnumber; |
| 40 // - handles key/pointer combinations like Alt+Button1 -> Button3. |
| 41 class EventRewriter |
| 42 : |
| 43 #if defined(USE_X11) |
| 44 public DeviceHierarchyObserver, |
| 45 public ui::PlatformEventObserver, |
| 46 #endif |
| 47 public ui::EventRewriter { |
31 public: | 48 public: |
32 enum DeviceType { | 49 enum DeviceType { |
33 kDeviceUnknown = 0, | 50 kDeviceUnknown = 0, |
34 kDeviceAppleKeyboard, | 51 kDeviceAppleKeyboard, |
35 }; | 52 }; |
36 | 53 |
37 EventRewriter(); | 54 EventRewriter(); |
38 virtual ~EventRewriter(); | 55 virtual ~EventRewriter(); |
39 | 56 |
40 // Calls DeviceAddedInternal. | 57 // Calls DeviceAddedInternal. |
41 DeviceType DeviceAddedForTesting(int device_id, | 58 DeviceType DeviceAddedForTesting(int device_id, |
42 const std::string& device_name); | 59 const std::string& device_name); |
43 // Calls Rewrite. | |
44 void RewriteForTesting(XEvent* event); | |
45 | 60 |
| 61 // Calls RewriteLocatedEvent(). |
| 62 void RewriteLocatedEventForTesting(const ui::Event& event, int* flags); |
| 63 |
| 64 #if defined(USE_X11) |
46 const std::map<int, DeviceType>& device_id_to_type_for_testing() const { | 65 const std::map<int, DeviceType>& device_id_to_type_for_testing() const { |
47 return device_id_to_type_; | 66 return device_id_to_type_; |
48 } | 67 } |
| 68 #endif |
| 69 |
49 void set_last_device_id_for_testing(int device_id) { | 70 void set_last_device_id_for_testing(int device_id) { |
50 last_device_id_ = device_id; | 71 last_device_id_ = device_id; |
51 } | 72 } |
52 void set_pref_service_for_testing(const PrefService* pref_service) { | 73 void set_pref_service_for_testing(const PrefService* pref_service) { |
53 pref_service_for_testing_ = pref_service; | 74 pref_service_for_testing_ = pref_service; |
54 } | 75 } |
55 void set_keyboard_for_testing(input_method::ImeKeyboard* keyboard) { | 76 void set_ime_keyboard_for_testing( |
56 keyboard_for_testing_ = keyboard; | 77 chromeos::input_method::ImeKeyboard* ime_keyboard) { |
| 78 ime_keyboard_for_testing_ = ime_keyboard; |
57 } | 79 } |
58 | 80 |
59 // Gets DeviceType from the |device_name|. | 81 // EventRewriter overrides: |
60 static DeviceType GetDeviceType(const std::string& device_name); | 82 virtual ui::EventRewriteStatus RewriteEvent( |
| 83 const ui::Event& event, |
| 84 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; |
| 85 virtual ui::EventRewriteStatus NextDispatchEvent( |
| 86 const ui::Event& last_event, |
| 87 scoped_ptr<ui::Event>* new_event) OVERRIDE; |
61 | 88 |
62 private: | 89 #if defined(USE_X11) |
63 friend class EventRewriterAshTest; | |
64 friend class EventRewriterTest; | |
65 | |
66 void DeviceKeyPressedOrReleased(int device_id); | |
67 | |
68 // ui::PlatformEventObserver: | 90 // ui::PlatformEventObserver: |
69 virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE; | 91 virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE; |
70 virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE; | 92 virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE; |
71 | 93 |
72 // DeviceHierarchyObserver: | 94 // DeviceHierarchyObserver: |
73 virtual void DeviceHierarchyChanged() OVERRIDE; | 95 virtual void DeviceHierarchyChanged() OVERRIDE; |
74 virtual void DeviceAdded(int device_id) OVERRIDE; | 96 virtual void DeviceAdded(int device_id) OVERRIDE; |
75 virtual void DeviceRemoved(int device_id) OVERRIDE; | 97 virtual void DeviceRemoved(int device_id) OVERRIDE; |
| 98 #endif |
76 | 99 |
77 // We don't want to include Xlib.h here since it has polluting macros, so | 100 private: |
78 // define these locally. | 101 // Things that internal rewriter phases can change about an Event. |
79 typedef unsigned long KeySym; | 102 struct MutableKeyState { |
80 typedef unsigned char KeyCode; | 103 int flags; |
81 | 104 ui::KeyboardCode key_code; |
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 }; | 105 }; |
93 | 106 |
94 // Returns true if the target for |event| would prefer to receive raw function | 107 // Tables of direct remappings for |RewriteWithKeyboardRemappingsByKeyCode()|. |
95 // keys instead of having them rewritten into back, forward, brightness, | 108 struct KeyboardRemapping { |
96 // volume, etc. or if the user has specified that they desire top-row keys to | 109 ui::KeyboardCode input_key_code; |
97 // be treated as function keys globally. | 110 int input_flags; |
98 bool TopRowKeysAreFunctionKeys(XEvent* event) const; | 111 ui::KeyboardCode output_key_code; |
| 112 int output_flags; |
| 113 }; |
99 | 114 |
100 // Given a set of KeyboardRemapping structs, it finds a matching struct | 115 #if defined(USE_X11) |
101 // if possible, and updates the remapped event values. Returns true if a | 116 void DeviceKeyPressedOrReleased(int device_id); |
102 // remapping was found and remapped values were updated. | 117 #endif |
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 | 118 |
124 // Returns the PrefService that should be used. | 119 // Returns the PrefService that should be used. |
125 const PrefService* GetPrefService() const; | 120 const PrefService* GetPrefService() const; |
126 | 121 |
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 | 122 // Checks the type of the |device_name|, and inserts a new entry to |
173 // |device_id_to_type_|. | 123 // |device_id_to_type_|. |
174 DeviceType DeviceAddedInternal(int device_id, const std::string& device_name); | 124 DeviceType DeviceAddedInternal(int device_id, const std::string& device_name); |
175 | 125 |
176 // Returns true if |last_device_id_| is Apple's. | 126 // Returns true if |last_device_id_| is Apple's. |
177 bool IsAppleKeyboard() const; | 127 bool IsAppleKeyboard() const; |
178 | 128 |
179 // Remaps |original_native_modifiers| to |remapped_native_modifiers| following | 129 // Returns true if the target for |event| would prefer to receive raw function |
180 // the current user prefs. | 130 // keys instead of having them rewritten into back, forward, brightness, |
181 void GetRemappedModifierMasks(unsigned int original_native_modifiers, | 131 // volume, etc. or if the user has specified that they desire top-row keys to |
182 unsigned int* remapped_native_modifiers) const; | 132 // be treated as function keys globally. |
| 133 bool TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const; |
| 134 |
| 135 // Given modifier flags |original_flags|, returns the remapped modifiers |
| 136 // according to user preferences and/or event properties. |
| 137 int GetRemappedModifierMasks(const PrefService& pref_service, |
| 138 const ui::Event& event, |
| 139 int original_flags) const; |
| 140 |
| 141 // Given a set of KeyboardRemapping structs, it finds a matching struct |
| 142 // if possible, and updates the remapped event values. Returns true if a |
| 143 // remapping was found and remapped values were updated. |
| 144 bool RewriteWithKeyboardRemappingsByKeyCode( |
| 145 const KeyboardRemapping* remappings, |
| 146 size_t num_remappings, |
| 147 const MutableKeyState& input, |
| 148 MutableKeyState* remapped_state); |
| 149 |
| 150 // Rewriter phases. These can inspect the original |event|, but operate using |
| 151 // the current |state|, which may have been modified by previous phases. |
| 152 void RewriteModifierKeys(const ui::KeyEvent& event, MutableKeyState* state); |
| 153 void RewriteNumPadKeys(const ui::KeyEvent& event, MutableKeyState* state); |
| 154 void RewriteExtendedKeys(const ui::KeyEvent& event, MutableKeyState* state); |
| 155 void RewriteFunctionKeys(const ui::KeyEvent& event, MutableKeyState* state); |
| 156 void RewriteLocatedEvent(const ui::Event& event, MutableKeyState* state); |
| 157 |
| 158 // A set of device IDs whose press event has been rewritten. |
| 159 std::set<int> pressed_device_ids_; |
183 | 160 |
184 std::map<int, DeviceType> device_id_to_type_; | 161 std::map<int, DeviceType> device_id_to_type_; |
185 int last_device_id_; | 162 int last_device_id_; |
186 | 163 |
187 // A mapping from X11 KeySym keys to KeyCode values. | 164 chromeos::input_method::ImeKeyboard* ime_keyboard_for_testing_; |
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_; | 165 const PrefService* pref_service_for_testing_; |
196 | 166 |
197 DISALLOW_COPY_AND_ASSIGN(EventRewriter); | 167 DISALLOW_COPY_AND_ASSIGN(EventRewriter); |
198 }; | 168 }; |
199 | 169 |
200 } // namespace chromeos | 170 } // namespace chromeos |
201 | 171 |
202 #endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ | 172 #endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ |
OLD | NEW |