event_rewriter.h revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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 { 25namespace input_method { 26class ImeKeyboard; 27} 28 29class EventRewriter : public DeviceHierarchyObserver, 30 public ui::PlatformEventObserver { 31 public: 32 enum DeviceType { 33 kDeviceUnknown = 0, 34 kDeviceAppleKeyboard, 35 }; 36 37 EventRewriter(); 38 virtual ~EventRewriter(); 39 40 // Calls DeviceAddedInternal. 41 DeviceType DeviceAddedForTesting(int device_id, 42 const std::string& device_name); 43 // Calls Rewrite. 44 void RewriteForTesting(XEvent* event); 45 46 const std::map<int, DeviceType>& device_id_to_type_for_testing() const { 47 return device_id_to_type_; 48 } 49 void set_last_device_id_for_testing(int device_id) { 50 last_device_id_ = device_id; 51 } 52 void set_pref_service_for_testing(const PrefService* pref_service) { 53 pref_service_for_testing_ = pref_service; 54 } 55 void set_keyboard_for_testing(input_method::ImeKeyboard* keyboard) { 56 keyboard_for_testing_ = keyboard; 57 } 58 59 // Gets DeviceType from the |device_name|. 60 static DeviceType GetDeviceType(const std::string& device_name); 61 62 private: 63 friend class EventRewriterAshTest; 64 friend class EventRewriterTest; 65 66 void DeviceKeyPressedOrReleased(int device_id); 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 }; 93 94 // Returns true if the target for |event| would prefer to receive raw function 95 // keys instead of having them rewritten into back, forward, brightness, 96 // volume, etc. or if the user has specified that they desire top-row keys to 97 // be treated as function keys globally. 98 bool TopRowKeysAreFunctionKeys(XEvent* event) const; 99 100 // Given a set of KeyboardRemapping structs, it finds a matching struct 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 124 // Returns the PrefService that should be used. 125 const PrefService* GetPrefService() const; 126 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 173 // |device_id_to_type_|. 174 DeviceType DeviceAddedInternal(int device_id, const std::string& device_name); 175 176 // Returns true if |last_device_id_| is Apple's. 177 bool IsAppleKeyboard() const; 178 179 // Remaps |original_native_modifiers| to |remapped_native_modifiers| following 180 // the current user prefs. 181 void GetRemappedModifierMasks(unsigned int original_native_modifiers, 182 unsigned int* remapped_native_modifiers) const; 183 184 std::map<int, DeviceType> device_id_to_type_; 185 int last_device_id_; 186 187 // A mapping from X11 KeySym keys to KeyCode values. 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_; 196 197 DISALLOW_COPY_AND_ASSIGN(EventRewriter); 198}; 199 200} // namespace chromeos 201 202#endif // CHROME_BROWSER_CHROMEOS_EVENTS_EVENT_REWRITER_H_ 203