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