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.
5 #ifndef CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_
6 #define CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_
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"
19 #if defined(OS_CHROMEOS)
20 #include "chrome/browser/chromeos/device_hierarchy_observer.h"
29 #if defined(OS_CHROMEOS)
32 class KeyboardDrivenEventRewriter
;
34 namespace input_method
{
40 class EventRewriter
: public ash::EventRewriterDelegate
,
41 public aura::RootWindowObserver
42 #if defined(OS_CHROMEOS)
43 , public chromeos::DeviceHierarchyObserver
53 virtual ~EventRewriter();
55 // Calls DeviceAddedInternal.
56 DeviceType
DeviceAddedForTesting(int device_id
,
57 const std::string
& device_name
);
59 void RewriteForTesting(ui::KeyEvent
* event
);
61 const std::map
<int, DeviceType
>& device_id_to_type_for_testing() const {
62 return device_id_to_type_
;
64 void set_last_device_id_for_testing(int device_id
) {
65 last_device_id_
= device_id
;
67 void set_pref_service_for_testing(const PrefService
* pref_service
) {
68 pref_service_for_testing_
= pref_service
;
70 #if defined(OS_CHROMEOS)
71 void set_xkeyboard_for_testing(chromeos::input_method::XKeyboard
* xkeyboard
) {
72 xkeyboard_for_testing_
= xkeyboard
;
76 // Gets DeviceType from the |device_name|.
77 static DeviceType
GetDeviceType(const std::string
& device_name
);
80 friend class EventRewriterAshTest
;
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
;
88 // aura::RootWindowObserver overrides:
89 virtual void OnKeyboardMappingChanged(const aura::RootWindow
* root
) OVERRIDE
;
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
;
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
;
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
);
108 struct KeyboardRemapping
{
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
;
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;
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
,
131 unsigned int native_mods
,
133 KeySym
* remapped_native_keysym
,
134 unsigned int* remapped_native_mods
,
135 ui::KeyboardCode
* remapped_keycode
,
136 unsigned int* remapped_mods
);
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
,
147 unsigned int native_mods
,
149 KeySym
* remapped_native_keysym
,
150 unsigned int* remapped_native_mods
,
151 ui::KeyboardCode
* remapped_keycode
,
152 unsigned int* remapped_mods
);
155 // Returns the PrefService that should be used.
156 const PrefService
* GetPrefService() const;
158 // Rewrites the |event| by applying all RewriteXXX functions as needed.
159 void Rewrite(ui::KeyEvent
* event
);
161 // Rewrites a modifier key press/release following the current user
163 bool RewriteModifiers(ui::KeyEvent
* event
);
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
);
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
);
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
);
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
193 bool RewriteFunctionKeys(ui::KeyEvent
* event
);
195 // Rewrites the located |event|.
196 void RewriteLocatedEvent(ui::LocatedEvent
* event
);
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
,
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
);
209 // Returns true if |last_device_id_| is Apple's.
210 bool IsAppleKeyboard() const;
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
,
217 unsigned int* remapped_native_modifiers
) const;
219 std::map
<int, DeviceType
> device_id_to_type_
;
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_
;
226 chromeos::input_method::XKeyboard
* xkeyboard_for_testing_
;
228 scoped_ptr
<chromeos::KeyboardDrivenEventRewriter
>
229 keyboard_driven_event_rewriter_
;
232 const PrefService
* pref_service_for_testing_
;
234 DISALLOW_COPY_AND_ASSIGN(EventRewriter
);
237 #endif // CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_