OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 ASH_WM_STICKY_KEYS_H_ | |
6 #define ASH_WM_STICKY_KEYS_H_ | |
7 | |
8 #include "ash/ash_export.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "ui/events/event_constants.h" | |
11 #include "ui/events/event_handler.h" | |
12 | |
13 namespace ui { | |
14 class Event; | |
15 class KeyEvent; | |
16 class MouseEvent; | |
17 } // namespace ui | |
18 | |
19 namespace aura { | |
20 class Window; | |
21 } // namespace aura | |
22 | |
23 namespace ash { | |
24 | |
25 class StickyKeysHandler; | |
26 | |
27 // StickyKeys is an accessibility feature for users to be able to compose key | |
28 // and mouse event with modifier keys without simultaneous key press event. | |
29 // Instead they can compose events separately pressing each of the modifier | |
30 // keys involved. | |
31 // e.g. Composing Ctrl + T | |
32 // User Action : The KeyEvent widget will receives | |
33 // ---------------------------------------------------------- | |
34 // 1. Press Ctrl key : Ctrl Keydown. | |
35 // 2. Release Ctrl key : No event | |
36 // 3. Press T key : T keydown event with ctrl modifier. | |
37 // 4. : Ctrl Keyup | |
38 // 5. Release T key : T keyup without ctrl modifier (Windows behavior) | |
39 // | |
40 // By typing same modifier keys twice, users can generate bunch of modified key | |
41 // events. | |
42 // e.g. To focus tabs consistently by Ctrl + 1, Ctrl + 2 ... | |
43 // User Action : The KeyEvent widget will receives | |
44 // ---------------------------------------------------------- | |
45 // 1. Press Ctrl key : Ctrl Keydown | |
46 // 2. Release Ctrl key : No event | |
47 // 3. Press Ctrl key : No event | |
48 // 4. Release Ctrl key : No event | |
49 // 5. Press 1 key : 1 Keydown event with Ctrl modifier. | |
50 // 6. Release 1 key : 1 Keyup event with Ctrl modifier. | |
51 // 7. Press 2 key : 2 Keydown event with Ctrl modifier. | |
52 // 8. Release 2 key : 2 Keyup event with Ctrl modifier. | |
53 // 9. Press Ctrl key : No event | |
54 // 10. Release Ctrl key: Ctrl Keyup | |
55 // | |
56 // In the case of Chrome OS, StickyKeys supports Shift,Alt,Ctrl modifiers. Each | |
57 // handling or state is performed independently. | |
58 // | |
59 // StickyKeys is disabled by default. | |
60 class ASH_EXPORT StickyKeys : public ui::EventHandler { | |
61 public: | |
62 StickyKeys(); | |
63 virtual ~StickyKeys(); | |
64 | |
65 // Activate sticky keys to intercept and modify incoming events. | |
66 void Enable(bool enabled); | |
67 | |
68 private: | |
69 // Handles keyboard event. Returns true if Sticky key consumes keyboard event. | |
70 bool HandleKeyEvent(ui::KeyEvent* event); | |
71 | |
72 // Handles mouse event. Returns true if sticky key consumes mouse event. | |
73 bool HandleMouseEvent(ui::MouseEvent* event); | |
74 | |
75 // Handles scroll event. Returns true if sticky key consumes scroll event. | |
76 bool HandleScrollEvent(ui::ScrollEvent* event); | |
77 | |
78 // Overridden from ui::EventHandler: | |
79 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; | |
80 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; | |
81 virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; | |
82 | |
83 // Whether sticky keys is activated and modifying events. | |
84 bool enabled_; | |
85 | |
86 // Sticky key handlers. | |
87 scoped_ptr<StickyKeysHandler> shift_sticky_key_; | |
88 scoped_ptr<StickyKeysHandler> alt_sticky_key_; | |
89 scoped_ptr<StickyKeysHandler> ctrl_sticky_key_; | |
90 | |
91 DISALLOW_COPY_AND_ASSIGN(StickyKeys); | |
92 }; | |
93 | |
94 // StickyKeysHandler handles key event and performs StickyKeys for specific | |
95 // modifier keys. If monitored keyboard events are recieved, StickyKeysHandler | |
96 // changes internal state. If non modifier keyboard events or mouse events are | |
97 // received, StickyKeysHandler will append modifier based on internal state. | |
98 // For other events, StickyKeysHandler does nothing. | |
99 // | |
100 // The DISABLED state is default state and any incoming non modifier keyboard | |
101 // events will not be modified. The ENABLED state is one shot modification | |
102 // state. Only next keyboard event will be modified. After that, internal state | |
103 // will be back to DISABLED state with sending modifier keyup event. In the case | |
104 // of LOCKED state, all incomming keyboard events will be modified. The LOCKED | |
105 // state will be back to DISABLED state by next monitoring modifier key. | |
106 // | |
107 // The detailed state flow as follows: | |
108 // Current state | |
109 // | DISABLED | ENABLED | LOCKED | | |
110 // ----------------------------------------------------------------| | |
111 // Modifier KeyDown | noop | noop(*) | noop(*) | | |
112 // Modifier KeyUp | To ENABLED(*) | To LOCKED(*) | To DISABLED | | |
113 // Normal KeyDown | noop | To DISABLED(#) | noop(#) | | |
114 // Normal KeyUp | noop | noop | noop(#) | | |
115 // Other KeyUp/Down | noop | noop | noop | | |
116 // Mouse Press | noop | noop(#) | noop(#) | | |
117 // Mouse Release | noop | To DISABLED(#) | noop(#) | | |
118 // Mouse Wheel | noop | To DISABLED(#) | noop(#) | | |
119 // Other Mouse Event| noop | noop | noop | | |
120 // | |
121 // Here, (*) means key event will be consumed by StickyKeys, and (#) means event | |
122 // is modified. | |
123 class ASH_EXPORT StickyKeysHandler { | |
124 public: | |
125 class StickyKeysHandlerDelegate { | |
126 public: | |
127 StickyKeysHandlerDelegate(); | |
128 virtual ~StickyKeysHandlerDelegate(); | |
129 | |
130 // Dispatches keyboard event synchronously. | |
131 virtual void DispatchKeyEvent(ui::KeyEvent* event, | |
132 aura::Window* target) = 0; | |
133 | |
134 // Dispatches mouse event synchronously. | |
135 virtual void DispatchMouseEvent(ui::MouseEvent* event, | |
136 aura::Window* target) = 0; | |
137 | |
138 // Dispatches scroll event synchronously. | |
139 virtual void DispatchScrollEvent(ui::ScrollEvent* event, | |
140 aura::Window* target) = 0; | |
141 }; | |
142 // Represents Sticky Key state. | |
143 enum StickyKeyState { | |
144 // The sticky key is disabled. Incomming non modifier key events are not | |
145 // affected. | |
146 DISABLED, | |
147 // The sticky key is enabled. Incomming non modifier key down events are | |
148 // modified with |modifier_flag_|. After that, sticky key state become | |
149 // DISABLED. | |
150 ENABLED, | |
151 // The sticky key is locked. Incomming non modifier key down events are | |
152 // modified with |modifier_flag_|. | |
153 LOCKED, | |
154 }; | |
155 | |
156 // This class takes an ownership of |delegate|. | |
157 StickyKeysHandler(ui::EventFlags modifier_flag, | |
158 StickyKeysHandlerDelegate* delegate); | |
159 ~StickyKeysHandler(); | |
160 | |
161 // Handles key event. Returns true if key is consumed. | |
162 bool HandleKeyEvent(ui::KeyEvent* event); | |
163 | |
164 // Handles a mouse event. Returns true if mouse event is consumed. | |
165 bool HandleMouseEvent(ui::MouseEvent* event); | |
166 | |
167 // Handles a scroll event. Returns true if scroll event is consumed. | |
168 bool HandleScrollEvent(ui::ScrollEvent* event); | |
169 | |
170 // Returns current internal state. | |
171 StickyKeyState current_state() const { return current_state_; } | |
172 | |
173 private: | |
174 // Represents event type in Sticky Key context. | |
175 enum KeyEventType { | |
176 TARGET_MODIFIER_DOWN, // The monitoring modifier key is down. | |
177 TARGET_MODIFIER_UP, // The monitoring modifier key is up. | |
178 NORMAL_KEY_DOWN, // The non modifier key is down. | |
179 NORMAL_KEY_UP, // The non modifier key is up. | |
180 OTHER_MODIFIER_DOWN, // The modifier key but not monitored key is down. | |
181 OTHER_MODIFIER_UP, // The modifier key but not monitored key is up. | |
182 }; | |
183 | |
184 // Translates |event| to sticky keys event type. | |
185 KeyEventType TranslateKeyEvent(ui::KeyEvent* event); | |
186 | |
187 // Handles key event in DISABLED state. | |
188 bool HandleDisabledState(ui::KeyEvent* event); | |
189 | |
190 // Handles key event in ENABLED state. | |
191 bool HandleEnabledState(ui::KeyEvent* event); | |
192 | |
193 // Handles key event in LOCKED state. | |
194 bool HandleLockedState(ui::KeyEvent* event); | |
195 | |
196 // Dispatches |event| to its target and then dispatch a key released event | |
197 // for the modifier key. This function is required to ensure that the events | |
198 // are sent in the correct order when disabling sticky key after a key/mouse | |
199 // button press. | |
200 void DispatchEventAndReleaseModifier(ui::Event* event); | |
201 | |
202 // Adds |modifier_flags_| to a native X11 event state mask. | |
203 void AppendNativeEventMask(unsigned int* state); | |
204 | |
205 // Adds |modifier_flags_| into |event|. | |
206 void AppendModifier(ui::KeyEvent* event); | |
207 void AppendModifier(ui::MouseEvent* event); | |
208 void AppendModifier(ui::ScrollEvent* event); | |
209 | |
210 // The modifier flag to be monitored and appended. | |
211 const ui::EventFlags modifier_flag_; | |
212 | |
213 // The current sticky key status. | |
214 StickyKeyState current_state_; | |
215 | |
216 // True if the received key event is sent by StickyKeyHandler. | |
217 bool event_from_myself_; | |
218 | |
219 // True if we received the TARGET_MODIFIER_DOWN event while in the DISABLED | |
220 // state but before we receive the TARGET_MODIFIER_UP event. Normal | |
221 // shortcuts (eg. ctrl + t) during this time will prevent a transition to | |
222 // the ENABLED state. | |
223 bool preparing_to_enable_; | |
224 | |
225 // Tracks the scroll direction of the current scroll sequence. Sticky keys | |
226 // stops modifying the scroll events of the sequence when the direction | |
227 // changes. If no sequence is tracked, the value is 0. | |
228 int scroll_delta_; | |
229 | |
230 // The modifier up key event to be sent on non modifier key on ENABLED state. | |
231 scoped_ptr<ui::KeyEvent> modifier_up_event_; | |
232 | |
233 scoped_ptr<StickyKeysHandlerDelegate> delegate_; | |
234 | |
235 DISALLOW_COPY_AND_ASSIGN(StickyKeysHandler); | |
236 }; | |
237 | |
238 } // namespace ash | |
239 | |
240 #endif // ASH_WM_STICKY_KEYS_H_ | |
OLD | NEW |