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.
5 #ifndef CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_
6 #define CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_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 "base/message_loop/message_pump_observer.h"
17 #include "chrome/browser/chromeos/device_hierarchy_observer.h"
18 #include "ui/aura/root_window_observer.h"
19 #include "ui/events/keycodes/keyboard_codes.h"
22 typedef union _XEvent XEvent;
29 class KeyboardDrivenEventRewriter;
30 namespace input_method {
34 class EventRewriter : public aura::RootWindowObserver,
35 public DeviceHierarchyObserver,
36 public base::MessagePumpObserver {
44 virtual ~EventRewriter();
46 // Calls DeviceAddedInternal.
47 DeviceType DeviceAddedForTesting(int device_id,
48 const std::string& device_name);
50 void RewriteForTesting(XEvent* event);
52 const std::map<int, DeviceType>& device_id_to_type_for_testing() const {
53 return device_id_to_type_;
55 void set_last_device_id_for_testing(int device_id) {
56 last_device_id_ = device_id;
58 void set_pref_service_for_testing(const PrefService* pref_service) {
59 pref_service_for_testing_ = pref_service;
61 void set_xkeyboard_for_testing(input_method::XKeyboard* xkeyboard) {
62 xkeyboard_for_testing_ = xkeyboard;
65 // Gets DeviceType from the |device_name|.
66 static DeviceType GetDeviceType(const std::string& device_name);
69 friend class EventRewriterAshTest;
70 friend class EventRewriterTest;
72 // aura::RootWindowObserver overrides:
73 virtual void OnKeyboardMappingChanged(const aura::RootWindow* root) OVERRIDE;
75 // base::MessagePumpObserver overrides:
76 virtual base::EventStatus WillProcessEvent(
77 const base::NativeEvent& event) OVERRIDE;
78 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
80 // DeviceHierarchyObserver overrides:
81 virtual void DeviceHierarchyChanged() OVERRIDE {}
82 virtual void DeviceAdded(int device_id) OVERRIDE;
83 virtual void DeviceRemoved(int device_id) OVERRIDE;
84 virtual void DeviceKeyPressedOrReleased(int device_id) OVERRIDE;
86 // We don't want to include Xlib.h here since it has polluting macros, so
87 // define these locally.
88 typedef unsigned long KeySym;
89 typedef unsigned char KeyCode;
91 // Updates |*_xkeycode_| in response to a keyboard map change.
92 void RefreshKeycodes();
93 // Converts an X key symbol like XK_Control_L to a key code.
94 unsigned char NativeKeySymToNativeKeycode(KeySym keysym);
96 struct KeyboardRemapping {
98 unsigned int input_native_mods;
100 unsigned int output_native_mods;
103 // Returns true if the target for |event| would prefer to receive raw function
104 // keys instead of having them rewritten into back, forward, brightness,
105 // volume, etc. or if the user has specified that they desire top-row keys to
106 // be treated as function keys globally.
107 bool TopRowKeysAreFunctionKeys(XEvent* event) const;
109 // Given a set of KeyboardRemapping structs, it finds a matching struct
110 // if possible, and updates the remapped event values. Returns true if a
111 // remapping was found and remapped values were updated.
112 bool RewriteWithKeyboardRemappingsByKeySym(
113 const KeyboardRemapping* remappings,
114 size_t num_remappings,
116 unsigned int native_mods,
117 KeySym* remapped_native_keysym,
118 unsigned int* remapped_native_mods);
120 // Given a set of KeyboardRemapping structs, it finds a matching struct
121 // if possible, and updates the remapped event values. This function converts
122 // the KeySym in the KeyboardRemapping struct into the KeyCode before matching
123 // to allow any KeyCode on the same physical key as the given KeySym to match.
124 // Returns true if a remapping was found and remapped values were updated.
125 bool RewriteWithKeyboardRemappingsByKeyCode(
126 const KeyboardRemapping* remappings,
127 size_t num_remappings,
129 unsigned int native_mods,
130 KeySym* remapped_native_keysym,
131 unsigned int* remapped_native_mods);
133 // Returns the PrefService that should be used.
134 const PrefService* GetPrefService() const;
136 // Rewrites the |event| by applying all RewriteXXX functions as needed.
137 void Rewrite(XEvent* event);
139 // Rewrites a modifier key press/release following the current user
141 bool RewriteModifiers(XEvent* event);
143 // Rewrites Fn key press/release to Control. In some cases, Fn key is not
144 // intercepted by the EC, but generates a key event like "XK_F15 + Mod3Mask"
145 // as shown in crosbug.com/p/14339.
146 bool RewriteFnKey(XEvent* event);
148 // Rewrites a NumPad key press/release without Num Lock to a corresponding key
149 // press/release with the lock. Returns true when |event| is rewritten.
150 bool RewriteNumPadKeys(XEvent* event);
152 // Rewrites Backspace and Arrow keys following the Chrome OS keyboard spec.
153 // * Alt+Backspace -> Delete
154 // * Alt+Up -> Prior (aka PageUp)
155 // * Alt+Down -> Next (aka PageDown)
156 // * Ctrl+Alt+Up -> Home
157 // * Ctrl+Alt+Down -> End
158 // When the Search key acts as a function key, it instead maps:
159 // * Search+Backspace -> Delete
160 // * Search+Up -> Prior (aka PageUp)
161 // * Search+Down -> Next (aka PageDown)
162 // * Search+Left -> Home
163 // * Search+Right -> End
164 // * Search+. -> Insert
165 // Returns true when the |event| is rewritten.
166 bool RewriteExtendedKeys(XEvent* event);
168 // When the Search key acts as a function key, it remaps Search+1
169 // through Search+= to F1 through F12. Returns true when the |event| is
171 bool RewriteFunctionKeys(XEvent* event);
173 // Rewrites the located |event|.
174 void RewriteLocatedEvent(XEvent* event);
176 // Overwrites |event| with the keycodes and flags.
177 void OverwriteEvent(XEvent* event,
178 unsigned int new_native_keycode,
179 unsigned int new_native_state);
181 // Checks the type of the |device_name|, and inserts a new entry to
182 // |device_id_to_type_|.
183 DeviceType DeviceAddedInternal(int device_id, const std::string& device_name);
185 // Returns true if |last_device_id_| is Apple's.
186 bool IsAppleKeyboard() const;
188 // Remaps |original_native_modifiers| to |remapped_native_modifiers| following
189 // the current user prefs.
190 void GetRemappedModifierMasks(unsigned int original_native_modifiers,
191 unsigned int* remapped_native_modifiers) const;
193 std::map<int, DeviceType> device_id_to_type_;
196 // A mapping from X11 KeySym keys to KeyCode values.
197 base::hash_map<unsigned long, unsigned long> keysym_to_keycode_map_;
199 // A set of device IDs whose press event has been rewritten.
200 std::set<int> pressed_device_ids_;
202 input_method::XKeyboard* xkeyboard_for_testing_;
204 scoped_ptr<KeyboardDrivenEventRewriter>
205 keyboard_driven_event_rewriter_;
207 const PrefService* pref_service_for_testing_;
209 DISALLOW_COPY_AND_ASSIGN(EventRewriter);
212 } // namespace chromeos
214 #endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_