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