event_rewriter_chromeos.h 17 KB

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