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 UI_CHROMEOS_EVENTS_EVENT_REWRITER_CHROMEOS_H_ 6 #define UI_CHROMEOS_EVENTS_EVENT_REWRITER_CHROMEOS_H_ 7 8 #include <list> 9 #include <map> 10 #include <memory> 11 #include <set> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 16 #include "base/macros.h" 17 #include "ui/events/devices/input_device.h" 18 #include "ui/events/event.h" 19 #include "ui/events/event_rewriter.h" 20 #include "ui/events/keycodes/dom/dom_key.h" 21 22 namespace chromeos { 23 namespace input_method { 24 class ImeKeyboard; 25 } // namespace input_method 26 } // namespace chromeos 27 28 namespace ui { 29 30 enum class DomCode; 31 32 // EventRewriterChromeOS makes various changes to keyboard-related events, 33 // including KeyEvents and some other events with keyboard modifier flags: 34 // - maps certain non-character keys according to user preferences 35 // (Control, Alt, Search, Caps Lock, Escape, Backspace, Diamond); 36 // - maps Command to Control on Apple keyboards; 37 // - converts numeric pad editing keys to their numeric forms; 38 // - converts top-row function keys to special keys where necessary; 39 // - handles various key combinations like Search+Backspace -> Delete 40 // and Search+number to Fnumber; 41 // - handles key/pointer combinations like Alt+Button1 -> Button3. 42 class EventRewriterChromeOS : public EventRewriter { 43 public: 44 enum DeviceType { 45 kDeviceUnknown = 0, 46 kDeviceInternalKeyboard, 47 kDeviceExternalAppleKeyboard, 48 kDeviceExternalChromeOsKeyboard, 49 kDeviceExternalGenericKeyboard, 50 kDeviceExternalUnknown, 51 kDeviceHotrodRemote, 52 kDeviceVirtualCoreKeyboard, // X-server generated events. 53 }; 54 55 enum KeyboardTopRowLayout { 56 // The original Chrome OS Layout: 57 // Browser Back, Browser Forward, Refresh, Full Screen, Overview, 58 // Brightness Down, Brightness Up, Mute, Volume Down, Volume Up. 59 kKbdTopRowLayout1 = 1, 60 kKbdTopRowLayoutDefault = kKbdTopRowLayout1, 61 kKbdTopRowLayoutMin = kKbdTopRowLayout1, 62 // 2017 keyboard layout: Browser Forward is gone and Play/Pause 63 // key is added between Brightness Up and Mute. 64 kKbdTopRowLayout2 = 2, 65 // Keyboard layout and handling for Wilco. 66 kKbdTopRowLayoutWilco = 3, 67 kKbdTopRowLayoutDrallion = 4, 68 69 // Handling for all keyboards that support supplying a custom layout 70 // via sysfs attribute (aka Vivaldi). See crbug.com/1076241 71 kKbdTopRowLayoutCustom = 5, 72 kKbdTopRowLayoutMax = kKbdTopRowLayoutCustom 73 }; 74 75 // Things that keyboard-related rewriter phases can change about an Event. 76 struct MutableKeyState { 77 MutableKeyState(); 78 explicit MutableKeyState(const KeyEvent* key_event); 79 MutableKeyState(int input_flags, 80 DomCode input_code, 81 DomKey::Base input_key, 82 KeyboardCode input_key_code); 83 84 int flags; 85 DomCode code; 86 DomKey::Base key; 87 KeyboardCode key_code; 88 }; 89 90 class Delegate { 91 public: Delegate()92 Delegate() {} ~Delegate()93 virtual ~Delegate() {} 94 95 // Returns true if we want to rewrite modifier keys. 96 virtual bool RewriteModifierKeys() = 0; 97 98 // Returns true if get keyboard remapped preference value successfully and 99 // the value will be stored in |value|. 100 virtual bool GetKeyboardRemappedPrefValue(const std::string& pref_name, 101 int* value) const = 0; 102 103 // Returns true if the target would prefer to receive raw 104 // function keys instead of having them rewritten into back, forward, 105 // brightness, volume, etc. or if the user has specified that they desire 106 // top-row keys to be treated as function keys globally. 107 virtual bool TopRowKeysAreFunctionKeys() const = 0; 108 109 // Returns true if the |key_code| and |flags| have been resgistered for 110 // extensions and EventRewriterChromeOS will not rewrite the event. 111 virtual bool IsExtensionCommandRegistered(KeyboardCode key_code, 112 int flags) const = 0; 113 114 // Returns true if search key accelerator is reserved for current active 115 // window and EventRewriterChromeOS will not rewrite the event. 116 virtual bool IsSearchKeyAcceleratorReserved() const = 0; 117 118 private: 119 DISALLOW_COPY_AND_ASSIGN(Delegate); 120 }; 121 122 // Does not take ownership of the |sticky_keys_controller|, which may also be 123 // nullptr (for testing without ash), in which case sticky key operations 124 // don't happen. 125 EventRewriterChromeOS(Delegate* delegate, 126 EventRewriter* sticky_keys_controller, 127 bool privacy_screen_supported); 128 ~EventRewriterChromeOS() override; 129 130 // Calls KeyboardDeviceAdded. 131 void KeyboardDeviceAddedForTesting(int device_id); 132 133 // Reset the internal rewriter state so that next set of tests can be ran on 134 // the same rewriter, if needed. 135 void ResetStateForTesting(); 136 137 // Calls RewriteMouseEvent(). 138 void RewriteMouseButtonEventForTesting(const MouseEvent& event, 139 const Continuation continuation); 140 set_last_keyboard_device_id_for_testing(int device_id)141 void set_last_keyboard_device_id_for_testing(int device_id) { 142 last_keyboard_device_id_ = device_id; 143 } set_ime_keyboard_for_testing(::chromeos::input_method::ImeKeyboard * ime_keyboard)144 void set_ime_keyboard_for_testing( 145 ::chromeos::input_method::ImeKeyboard* ime_keyboard) { 146 ime_keyboard_for_testing_ = ime_keyboard; 147 } 148 set_privacy_screen_for_testing(bool supported)149 void set_privacy_screen_for_testing(bool supported) { 150 privacy_screen_supported_ = supported; 151 } 152 153 // EventRewriter overrides: 154 EventDispatchDetails RewriteEvent(const Event& event, 155 const Continuation continuation) override; 156 157 // Generate a new key event from an original key event and the replacement 158 // state determined by a key rewriter. 159 static void BuildRewrittenKeyEvent(const KeyEvent& key_event, 160 const MutableKeyState& state, 161 std::unique_ptr<Event>* rewritten_event); 162 163 // Given a keyboard device, returns its type. 164 static DeviceType GetDeviceType(const InputDevice& keyboard_device); 165 166 // Given a keyboard device, returns its top row layout. Will return default 167 // kKbdTopRowLayoutDefault if the device is not tagged with a specific 168 // layout, or when failing to retrieve device layout from udev. 169 static KeyboardTopRowLayout GetKeyboardTopRowLayout( 170 const InputDevice& keyboard_device); 171 172 // Given a keyboard device, returns true if we get back the Assistant key 173 // property without getting an error. Property value is stored in 174 // |has_assistant_key|. 175 static bool HasAssistantKeyOnKeyboard(const InputDevice& keyboard_device, 176 bool* has_assistant_key); 177 178 // Part of rewrite phases below. These methods are public only so that 179 // SpokenFeedbackRewriter can ask for rewritten modifier and function keys. 180 181 // Returns true when the input |state| has key |DomKey::ALT_GRAPH_LATCH| and 182 // is remapped. 183 bool RewriteModifierKeys(const KeyEvent& event, MutableKeyState* state); 184 void RewriteFunctionKeys(const KeyEvent& event, MutableKeyState* state); 185 186 private: 187 struct DeviceInfo { 188 DeviceType type; 189 KeyboardTopRowLayout top_row_layout; 190 }; 191 192 void DeviceKeyPressedOrReleased(int device_id); 193 194 // By default the top row (F1-F12) keys are system keys for back, forward, 195 // brightness, volume, etc. However, windows for v2 apps can optionally 196 // request raw function keys for these keys. 197 bool ForceTopRowAsFunctionKeys() const; 198 199 // Adds a device to |device_id_to_info_| only if no failure occurs in 200 // identifying the keyboard, and returns the device type of this keyboard 201 // even if it wasn't stored in |device_id_to_info_|. 202 DeviceType KeyboardDeviceAdded(int device_id); 203 204 // Returns true if |last_keyboard_device_id_| is Hotrod remote. 205 bool IsHotrodRemote() const; 206 // Returns true if |last_keyboard_device_id_| is of given |device_type|. 207 bool IsLastKeyboardOfType(DeviceType device_type) const; 208 // Returns the device type of |last_keyboard_device_id_|. 209 DeviceType GetLastKeyboardType() const; 210 211 // Given modifier flags |original_flags|, returns the remapped modifiers 212 // according to user preferences and/or event properties. 213 int GetRemappedModifierMasks(const Event& event, int original_flags) const; 214 215 // Returns true if this event should be remapped to a right-click. 216 // |matched_mask| will be set to the variant (Alt+Click or Search+Click) 217 // that was used to match based on flag/feature settings. |matched_mask| 218 // only has a valid value when returning true. 219 bool ShouldRemapToRightClick(const MouseEvent& mouse_event, 220 int flags, 221 int* matched_mask) const; 222 223 // Rewrite a particular kind of event. 224 EventRewriteStatus RewriteKeyEvent(const KeyEvent& key_event, 225 std::unique_ptr<Event>* rewritten_event); 226 EventDispatchDetails RewriteMouseButtonEvent(const MouseEvent& mouse_event, 227 const Continuation continuation); 228 EventDispatchDetails RewriteMouseWheelEvent( 229 const MouseWheelEvent& mouse_event, 230 const Continuation continuation); 231 EventDispatchDetails RewriteTouchEvent(const TouchEvent& touch_event, 232 const Continuation continuation); 233 EventDispatchDetails RewriteScrollEvent(const ScrollEvent& scroll_event, 234 const Continuation continuation); 235 236 // Rewriter phases. These can inspect the original |event|, but operate using 237 // the current |state|, which may have been modified by previous phases. 238 void RewriteNumPadKeys(const KeyEvent& event, MutableKeyState* state); 239 void RewriteExtendedKeys(const KeyEvent& event, MutableKeyState* state); 240 int RewriteLocatedEvent(const Event& event); 241 int RewriteModifierClick(const MouseEvent& event, int* flags); 242 243 // Reads the keyboard mapping for new CrOS keyboards that support 244 // supplying a custom layout via sysfs and stores it mapped to 245 // |keyboard_device| in |top_row_scan_code_map_|. 246 bool StoreCustomTopRowMapping(const ui::InputDevice& keyboard_device); 247 248 // Handle Function <-> Action key remapping for new CrOS keyboards that 249 // support supplying a custom layout via sysfs. 250 bool RewriteTopRowKeysForCustomLayout( 251 int device_id, 252 const ui::KeyEvent& key_event, 253 bool search_is_pressed, 254 ui::EventRewriterChromeOS::MutableKeyState* state); 255 256 // Handle Fn/Action key remapping for Wilco keyboard layout. 257 bool RewriteTopRowKeysForLayoutWilco(const KeyEvent& key_event, 258 bool search_is_pressed, 259 MutableKeyState* state, 260 KeyboardTopRowLayout layout); 261 262 // Take the keys being pressed into consideration, in contrast to 263 // RewriteKeyEvent which computes the rewritten event and event rewrite 264 // status in stateless way. 265 EventDispatchDetails RewriteKeyEventInContext( 266 const KeyEvent& event, 267 std::unique_ptr<Event> rewritten_event, 268 EventRewriteStatus status, 269 const Continuation continuation); 270 271 EventDispatchDetails SendStickyKeysReleaseEvents( 272 std::unique_ptr<Event> rewritten_event, 273 const Continuation continuation); 274 275 // A set of device IDs whose press event has been rewritten. 276 // This is to ensure that press and release events are rewritten consistently. 277 std::set<int> pressed_device_ids_; 278 279 std::map<int, DeviceInfo> device_id_to_info_; 280 281 // Maps a device ID to a mapping of scan_code to MutableKeyState on keyboards 282 // that supply it via a sysfs attribute. 283 // eg. map<device_id, Map<scan_code, MutableKeyState>>. 284 base::flat_map<int, base::flat_map<uint32_t, MutableKeyState>> 285 top_row_scan_code_map_; 286 287 // The |source_device_id()| of the most recent keyboard event, 288 // used to interpret modifiers on pointer events. 289 int last_keyboard_device_id_; 290 291 ::chromeos::input_method::ImeKeyboard* ime_keyboard_for_testing_; 292 293 Delegate* const delegate_; 294 295 // For each pair, the first element is the rewritten key state and the second 296 // one is the original key state. If no key event rewriting happens, the first 297 // element and the second element are identical. 298 std::list<std::pair<MutableKeyState, MutableKeyState>> pressed_key_states_; 299 300 // The sticky keys controller is not owned here; 301 // at time of writing it is a singleton in ash::Shell. 302 EventRewriter* const sticky_keys_controller_; 303 304 // Some drallion devices have digital privacy screens and a corresponding 305 // privacy screen toggle key in the top row. 306 bool privacy_screen_supported_; 307 308 // Some keyboard layouts have 'latching' keys, which either apply 309 // a modifier while held down (like normal modifiers), or, if no 310 // non-modifier is pressed while the latching key is down, apply the 311 // modifier to the next non-modifier keypress. Under Ozone the stateless 312 // layout model requires this to be handled explicitly. See crbug.com/518237 313 // Pragmatically this, like the Diamond key, is handled here in 314 // EventRewriterChromeOS, but modifier state management is scattered between 315 // here, sticky keys, and the system layer (Ozone), and could do with 316 // refactoring. 317 // - |pressed_modifier_latches_| records the latching keys currently pressed. 318 // It also records the active modifier flags for non-modifier keys that are 319 // remapped to modifiers, e.g. Diamond/F15. 320 // - |latched_modifier_latches_| records the latching keys just released, 321 // to be applied to the next non-modifier key. 322 // - |used_modifier_latches_| records the latching keys applied to a non- 323 // modifier while pressed, so that they do not get applied after release. 324 int pressed_modifier_latches_; 325 int latched_modifier_latches_; 326 int used_modifier_latches_; 327 328 DISALLOW_COPY_AND_ASSIGN(EventRewriterChromeOS); 329 }; 330 331 } // namespace ui 332 333 #endif // UI_CHROMEOS_EVENTS_EVENT_REWRITER_CHROMEOS_H_ 334