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" | 12 #include "ui/events/event.h" |
13 #include "base/compiler_specific.h" | 13 #include "ui/events/event_rewriter.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 | 14 |
21 class PrefService; | 15 class PrefService; |
22 typedef union _XEvent XEvent; | |
23 | 16 |
24 namespace chromeos { | 17 namespace chromeos { |
18 | |
25 namespace input_method { | 19 namespace input_method { |
26 class ImeKeyboard; | 20 class ImeKeyboard; |
27 } | 21 } |
28 | 22 |
29 class EventRewriter : public DeviceHierarchyObserver, | 23 // EventRewriter makes various changes to keyboard-related events, |
30 public ui::PlatformEventObserver { | 24 // including KeyEvents and some other events with keyboard modifier flags: |
25 // - maps modifiers keys (Control, Alt, Search, Caps, Diamond) according | |
26 // to user preferences; | |
27 // - maps Command to Control on Apple keyboards; | |
28 // - converts numeric pad editing keys to their numeric forms; | |
29 // - converts top-row function keys to special keys where necessary; | |
30 // - handles various key combinations like Search+Backspace -> Delete | |
31 // and Search+number to Fnumber; | |
32 // - handles key/pointer combinations like Alt+Button1 -> Button3. | |
33 class EventRewriter : public ui::EventRewriter { | |
31 public: | 34 public: |
32 enum DeviceType { | 35 enum DeviceType { |
33 kDeviceUnknown = 0, | 36 kDeviceUnknown = 0, |
34 kDeviceAppleKeyboard, | 37 kDeviceAppleKeyboard, |
35 }; | 38 }; |
36 | 39 |
37 EventRewriter(); | 40 EventRewriter(); |
38 virtual ~EventRewriter(); | 41 virtual ~EventRewriter(); |
39 | 42 |
40 // Calls DeviceAddedInternal. | 43 // Calls DeviceAddedInternal. |
41 DeviceType DeviceAddedForTesting(int device_id, | 44 DeviceType DeviceAddedForTesting(int device_id, |
42 const std::string& device_name); | 45 const std::string& device_name); |
43 // Calls Rewrite. | |
44 void RewriteForTesting(XEvent* event); | |
45 | 46 |
46 const std::map<int, DeviceType>& device_id_to_type_for_testing() const { | 47 // Calls RewriteLocatedEvent(). |
47 return device_id_to_type_; | 48 void RewriteLocatedEventForTesting(const ui::Event& event, int* flags); |
48 } | 49 |
49 void set_last_device_id_for_testing(int device_id) { | 50 void set_last_device_id_for_testing(int device_id) { |
50 last_device_id_ = device_id; | 51 last_device_id_ = device_id; |
51 } | 52 } |
52 void set_pref_service_for_testing(const PrefService* pref_service) { | 53 void set_pref_service_for_testing(const PrefService* pref_service) { |
53 pref_service_for_testing_ = pref_service; | 54 pref_service_for_testing_ = pref_service; |
54 } | 55 } |
55 void set_keyboard_for_testing(input_method::ImeKeyboard* keyboard) { | 56 void set_ime_keyboard_for_testing( |
56 keyboard_for_testing_ = keyboard; | 57 chromeos::input_method::ImeKeyboard* ime_keyboard) { |
58 ime_keyboard_for_testing_ = ime_keyboard; | |
57 } | 59 } |
58 | 60 |
59 // Gets DeviceType from the |device_name|. | 61 // EventRewriter overrides: |
60 static DeviceType GetDeviceType(const std::string& device_name); | 62 virtual ui::EventRewriteStatus RewriteEvent( |
63 const ui::Event& event, | |
64 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; | |
65 virtual ui::EventRewriteStatus NextDispatchEvent( | |
66 const ui::Event& last_event, | |
67 scoped_ptr<ui::Event>* new_event) OVERRIDE; | |
61 | 68 |
62 private: | 69 private: |
63 friend class EventRewriterAshTest; | 70 // Things that internal rewriter phases can change about an Event. |
64 friend class EventRewriterTest; | 71 struct MutableKeyState { |
65 | 72 int flags; |
66 void DeviceKeyPressedOrReleased(int device_id); | 73 ui::KeyboardCode key_code; |
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 }; | 74 }; |
93 | 75 |
94 // Returns true if the target for |event| would prefer to receive raw function | 76 // Tables of direct remappings for |RewriteWithKeyboardRemappingsByKeyCode()|. |
95 // keys instead of having them rewritten into back, forward, brightness, | 77 struct KeyboardRemapping { |
96 // volume, etc. or if the user has specified that they desire top-row keys to | 78 ui::KeyboardCode input_key_code; |
97 // be treated as function keys globally. | 79 int input_flags; |
98 bool TopRowKeysAreFunctionKeys(XEvent* event) const; | 80 ui::KeyboardCode output_key_code; |
99 | 81 int output_flags; |
100 // Given a set of KeyboardRemapping structs, it finds a matching struct | 82 }; |
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 | 83 |
124 // Returns the PrefService that should be used. | 84 // Returns the PrefService that should be used. |
125 const PrefService* GetPrefService() const; | 85 const PrefService* GetPrefService() const; |
126 | 86 |
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 | 87 // Checks the type of the |device_name|, and inserts a new entry to |
173 // |device_id_to_type_|. | 88 // |device_id_to_type_|. |
174 DeviceType DeviceAddedInternal(int device_id, const std::string& device_name); | 89 DeviceType DeviceAddedInternal(int device_id, const std::string& device_name); |
175 | 90 |
176 // Returns true if |last_device_id_| is Apple's. | 91 // Returns true if |last_device_id_| is Apple's. |
177 bool IsAppleKeyboard() const; | 92 bool IsAppleKeyboard(const ui::Event& event) const; |
178 | 93 |
179 // Remaps |original_native_modifiers| to |remapped_native_modifiers| following | 94 // Returns true if the event comes from an Chrome keyboard with a Diamond key. |
180 // the current user prefs. | 95 bool HasDiamondKey(const ui::Event& event) const; |
181 void GetRemappedModifierMasks(unsigned int original_native_modifiers, | 96 |
182 unsigned int* remapped_native_modifiers) const; | 97 // Returns true if the target for |event| would prefer to receive raw function |
98 // keys instead of having them rewritten into back, forward, brightness, | |
99 // volume, etc. or if the user has specified that they desire top-row keys to | |
100 // be treated as function keys globally. | |
101 bool TopRowKeysAreFunctionKeys(const ui::Event& event) const; | |
102 | |
103 int GetRemappedModifierMasks(const PrefService& pref_service, | |
Daniel Erat
2014/04/22 23:58:36
nit: add a comment describing this method
kpschoedel
2014/04/23 15:46:22
Done.
| |
104 const ui::Event& event, | |
105 int original_flags) const; | |
106 | |
107 // Given a set of KeyboardRemapping structs, it finds a matching struct | |
108 // if possible, and updates the remapped event values. Returns true if a | |
109 // remapping was found and remapped values were updated. | |
110 bool RewriteWithKeyboardRemappingsByKeyCode( | |
111 const KeyboardRemapping* remappings, | |
112 size_t num_remappings, | |
113 const MutableKeyState& input, | |
114 MutableKeyState* remapped); | |
Daniel Erat
2014/04/22 23:58:36
nit: maybe rename this to |remapped_state| so it's
kpschoedel
2014/04/23 15:46:22
Done.
| |
115 | |
116 // Rewriter phases. These can inspect the original |event|, but operate using | |
117 // the current |state|, which may have been modified by previous phases. | |
118 void RewriteModifierKeys(const ui::KeyEvent& event, MutableKeyState* state); | |
119 void RewriteNumPadKeys(const ui::KeyEvent& event, MutableKeyState* state); | |
120 void RewriteExtendedKeys(const ui::KeyEvent& event, MutableKeyState* state); | |
121 void RewriteFunctionKeys(const ui::KeyEvent& event, MutableKeyState* state); | |
122 void RewriteLocatedEvent(const ui::Event& event, MutableKeyState* state); | |
123 | |
124 // A set of device IDs whose press event has been rewritten. | |
125 std::set<int> pressed_device_ids_; | |
183 | 126 |
184 std::map<int, DeviceType> device_id_to_type_; | 127 std::map<int, DeviceType> device_id_to_type_; |
185 int last_device_id_; | 128 int last_device_id_; |
186 | 129 |
187 // A mapping from X11 KeySym keys to KeyCode values. | 130 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_; | 131 const PrefService* pref_service_for_testing_; |
196 | 132 |
197 DISALLOW_COPY_AND_ASSIGN(EventRewriter); | 133 DISALLOW_COPY_AND_ASSIGN(EventRewriter); |
198 }; | 134 }; |
199 | 135 |
200 } // namespace chromeos | 136 } // namespace chromeos |
201 | 137 |
202 #endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ | 138 #endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ |
OLD | NEW |