1ebe1d854975edbfdb5900f38b4ed7282f8643c5
[platform/framework/web/crosswalk.git] / src / ash / sticky_keys / sticky_keys_controller.h
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_STICKY_KEYS_STICKY_KEYS_CONTROLLER_H_
6 #define ASH_STICKY_KEYS_STICKY_KEYS_CONTROLLER_H_
7
8 #include "ash/ash_export.h"
9 #include "ash/sticky_keys/sticky_keys_state.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "ui/events/event_constants.h"
12 #include "ui/events/event_handler.h"
13 #include "ui/events/event_rewriter.h"
14 #include "ui/events/keycodes/keyboard_codes.h"
15
16 namespace ui {
17 class Event;
18 class KeyEvent;
19 class MouseEvent;
20 }  // namespace ui
21
22 namespace aura {
23 class Window;
24 }  // namespace aura
25
26 namespace ash {
27
28 class StickyKeysOverlay;
29 class StickyKeysHandler;
30
31 // StickyKeysController is an accessibility feature for users to be able to
32 // compose key and mouse event with modifier keys without simultaneous key
33 // press event. Instead they can compose events separately pressing each of the
34 // modifier keys involved.
35 // e.g. Composing Ctrl + T
36 //       User Action   : The KeyEvent widget will receives
37 // ----------------------------------------------------------
38 // 1. Press Ctrl key   : Ctrl Keydown.
39 // 2. Release Ctrl key : No event
40 // 3. Press T key      : T keydown event with ctrl modifier.
41 // 4.                  : Ctrl Keyup
42 // 5. Release T key    : T keyup without ctrl modifier (Windows behavior)
43 //
44 // By typing same modifier keys twice, users can generate bunch of modified key
45 // events.
46 // e.g. To focus tabs consistently by Ctrl + 1, Ctrl + 2 ...
47 //       User Action   : The KeyEvent widget will receives
48 // ----------------------------------------------------------
49 // 1. Press Ctrl key   : Ctrl Keydown
50 // 2. Release Ctrl key : No event
51 // 3. Press Ctrl key   : No event
52 // 4. Release Ctrl key : No event
53 // 5. Press 1 key      : 1 Keydown event with Ctrl modifier.
54 // 6. Release 1 key    : 1 Keyup event with Ctrl modifier.
55 // 7. Press 2 key      : 2 Keydown event with Ctrl modifier.
56 // 8. Release 2 key    : 2 Keyup event with Ctrl modifier.
57 // 9. Press Ctrl key   : No event
58 // 10. Release Ctrl key: Ctrl Keyup
59 //
60 // In the case of Chrome OS, StickyKeysController supports Shift,Alt,Ctrl
61 // modifiers. Each handling or state is performed independently.
62 //
63 // StickyKeysController is disabled by default.
64 class ASH_EXPORT StickyKeysController {
65  public:
66   StickyKeysController();
67   virtual ~StickyKeysController();
68
69   // Activate sticky keys to intercept and modify incoming events.
70   void Enable(bool enabled);
71
72   void SetModifiersEnabled(bool mod3_enabled, bool altgr_enabled);
73
74   // Returns the StickyKeyOverlay used by the controller. Ownership is not
75   // passed.
76   StickyKeysOverlay* GetOverlayForTest();
77
78   // Handles keyboard event. Returns an |EventRewriteStatus|, and may
79   // modify |flags|:
80   // - Returns ui::EVENT_REWRITE_DISCARD, and leaves |flags| untouched,
81   //   if the event is consumed (i.e. a sticky modifier press or release);
82   // - Returns ui::EVENT_REWRITE_REWRITTEN if the event needs to be modified
83   //   according to the returned |flags| (i.e. a sticky-modified key);
84   // - Returns ui::EVENT_REWRITE_DISPATCH_ANOTHER if the event needs to be
85   //   modified according to the returned |flags|, and there are delayed
86   //   modifier-up   events now to be retrieved using |NextDispatchEvent()|
87   //   (i.e. a sticky-modified key that ends a sticky state);
88   // - Otherwise returns ui::EVENT_REWRITE_CONTINUE and leaves |flags|
89   //   unchanged.
90   ui::EventRewriteStatus RewriteKeyEvent(const ui::KeyEvent& event,
91                                          ui::KeyboardCode key_code,
92                                          int* flags);
93
94   // Handles mouse event.
95   ui::EventRewriteStatus RewriteMouseEvent(const ui::MouseEvent& event,
96                                            int* flags);
97
98   // Handles scroll event.
99   ui::EventRewriteStatus RewriteScrollEvent(const ui::ScrollEvent& event,
100                                             int* flags);
101
102   // Obtains a pending modifier-up event. If the immediately previous
103   // call to |Rewrite...Event()| or |NextDispatchEvent()| returned
104   // ui::EVENT_REWRITE_DISPATCH_ANOTHER, this sets |new_event| and returns:
105   // - ui::EVENT_REWRITE_DISPATCH_ANOTHER if there is at least one more
106   //   pending modifier-up event;
107   // - ui::EVENT_REWRITE_REWRITE if this is the last or only modifier-up event;
108   // Otherwise, there is no pending modifier-up event, and this function
109   // returns ui::EVENT_REWRITE_CONTINUE and sets |new_event| to NULL.
110   ui::EventRewriteStatus NextDispatchEvent(scoped_ptr<ui::Event>* new_event);
111
112  private:
113   // Handles keyboard event. Returns true if Sticky key consumes keyboard event.
114   // Adds to |mod_down_flags| any flag to be added to the key event.
115   // Sets |released| if any modifier is to be released after the key event.
116   bool HandleKeyEvent(const ui::KeyEvent& event,
117                       ui::KeyboardCode key_code,
118                       int* mod_down_flags,
119                       bool* released);
120
121   // Handles mouse event. Returns true if Sticky key consumes keyboard event.
122   // Sets |released| if any modifier is to be released after the key event.
123   bool HandleMouseEvent(const ui::MouseEvent& event,
124                         int* mod_down_flags,
125                         bool* released);
126
127   // Handles scroll event. Returns true if Sticky key consumes keyboard event.
128   // Sets |released| if any modifier is to be released after the key event.
129   bool HandleScrollEvent(const ui::ScrollEvent& event,
130                          int* mod_down_flags,
131                          bool* released);
132
133   // Updates the overlay UI with the current state of the sticky keys.
134   void UpdateOverlay();
135
136   // Whether sticky keys is activated and modifying events.
137   bool enabled_;
138
139   // Whether the current layout has a mod3 key.
140   bool mod3_enabled_;
141
142   // Whether the current layout has an altgr key.
143   bool altgr_enabled_;
144
145   // Sticky key handlers.
146   scoped_ptr<StickyKeysHandler> shift_sticky_key_;
147   scoped_ptr<StickyKeysHandler> alt_sticky_key_;
148   scoped_ptr<StickyKeysHandler> altgr_sticky_key_;
149   scoped_ptr<StickyKeysHandler> ctrl_sticky_key_;
150   scoped_ptr<StickyKeysHandler> mod3_sticky_key_;
151   scoped_ptr<StickyKeysHandler> search_sticky_key_;
152
153   scoped_ptr<StickyKeysOverlay> overlay_;
154
155   DISALLOW_COPY_AND_ASSIGN(StickyKeysController);
156 };
157
158 // StickyKeysHandler handles key event and controls sticky keysfor specific
159 // modifier keys. If monitored keyboard events are recieved, StickyKeysHandler
160 // changes internal state. If non modifier keyboard events or mouse events are
161 // received, StickyKeysHandler will append modifier based on internal state.
162 // For other events, StickyKeysHandler does nothing.
163 //
164 // The DISABLED state is default state and any incoming non modifier keyboard
165 // events will not be modified. The ENABLED state is one shot modification
166 // state. Only next keyboard event will be modified. After that, internal state
167 // will be back to DISABLED state with sending modifier keyup event. In the case
168 // of LOCKED state, all incomming keyboard events will be modified. The LOCKED
169 // state will be back to DISABLED state by next monitoring modifier key.
170 //
171 // The detailed state flow as follows:
172 //                                     Current state
173 //                  |   DISABLED    |    ENABLED     |    LOCKED   |
174 // ----------------------------------------------------------------|
175 // Modifier KeyDown |   noop        |    noop(*)     |    noop(*)  |
176 // Modifier KeyUp   | To ENABLED(*) | To LOCKED(*)   | To DISABLED |
177 // Normal KeyDown   |   noop        | To DISABLED(#) |    noop(#)  |
178 // Normal KeyUp     |   noop        |    noop        |    noop(#)  |
179 // Other KeyUp/Down |   noop        |    noop        |    noop     |
180 // Mouse Press      |   noop        |    noop(#)     |    noop(#)  |
181 // Mouse Release    |   noop        | To DISABLED(#) |    noop(#)  |
182 // Mouse Wheel      |   noop        | To DISABLED(#) |    noop(#)  |
183 // Other Mouse Event|   noop        |    noop        |    noop     |
184 //
185 // Here, (*) means key event will be consumed by StickyKeys, and (#) means event
186 // is modified.
187 class ASH_EXPORT StickyKeysHandler {
188  public:
189   explicit StickyKeysHandler(ui::EventFlags modifier_flag);
190   ~StickyKeysHandler();
191
192   // Handles keyboard event. Returns true if Sticky key consumes keyboard event.
193   // Sets its own modifier flag in |mod_down_flags| if it is active and needs
194   // to be added to the event, and sets |released| if releasing it.
195   bool HandleKeyEvent(const ui::KeyEvent& event,
196                       ui::KeyboardCode key_code,
197                       int* mod_down_flags,
198                       bool* released);
199
200   // Handles mouse event. Returns true if sticky key consumes mouse event.
201   // Sets its own modifier flag in |mod_down_flags| if it is active and needs
202   // to be added to the event, and sets |released| if releasing it.
203   bool HandleMouseEvent(const ui::MouseEvent& event,
204                         int* mod_down_flags,
205                         bool* released);
206
207   // Handles scroll event. Returns true if sticky key consumes scroll event.
208   // Sets its own modifier flag in |mod_down_flags| if it is active and needs
209   // to be added to the event, and sets |released| if releasing it.
210   bool HandleScrollEvent(const ui::ScrollEvent& event,
211                          int* mod_down_flags,
212                          bool* released);
213
214   // Fetches a pending modifier-up event if one exists and the return
215   // parameter |new_event| is available (i.e. not set). Returns the number
216   // of pending events still remaining to be returned.
217   int GetModifierUpEvent(scoped_ptr<ui::Event>* new_event);
218
219   // Returns current internal state.
220   StickyKeyState current_state() const { return current_state_; }
221
222  private:
223   // Represents event type in Sticky Key context.
224   enum KeyEventType {
225     TARGET_MODIFIER_DOWN,  // The monitoring modifier key is down.
226     TARGET_MODIFIER_UP,  // The monitoring modifier key is up.
227     NORMAL_KEY_DOWN,  // The non modifier key is down.
228     NORMAL_KEY_UP,  // The non modifier key is up.
229     OTHER_MODIFIER_DOWN,  // The modifier key but not monitored key is down.
230     OTHER_MODIFIER_UP,  // The modifier key but not monitored key is up.
231   };
232
233   // Translates event type and key code to sticky keys event type.
234   KeyEventType TranslateKeyEvent(ui::EventType type, ui::KeyboardCode key_code);
235
236   // Handles key event in DISABLED state. Returns true if sticky keys
237   // consumes the keyboard event.
238   bool HandleDisabledState(const ui::KeyEvent& event,
239                            ui::KeyboardCode key_code);
240
241   // Handles key event in ENABLED state. Returns true if sticky keys
242   // consumes the keyboard event.
243   bool HandleEnabledState(const ui::KeyEvent& event,
244                           ui::KeyboardCode key_code,
245                           int* mod_down_flags,
246                           bool* released);
247
248   // Handles key event in LOCKED state. Returns true if sticky keys
249   // consumes the keyboard event.
250   bool HandleLockedState(const ui::KeyEvent& event,
251                          ui::KeyboardCode key_code,
252                          int* mod_down_flags,
253                          bool* released);
254
255   // The modifier flag to be monitored and appended to events.
256   const ui::EventFlags modifier_flag_;
257
258   // The current sticky key status.
259   StickyKeyState current_state_;
260
261   // True if we received the TARGET_MODIFIER_DOWN event while in the DISABLED
262   // state but before we receive the TARGET_MODIFIER_UP event. Normal
263   // shortcuts (eg. ctrl + t) during this time will prevent a transition to
264   // the ENABLED state.
265   bool preparing_to_enable_;
266
267   // Tracks the scroll direction of the current scroll sequence. Sticky keys
268   // stops modifying the scroll events of the sequence when the direction
269   // changes. If no sequence is tracked, the value is 0.
270   int scroll_delta_;
271
272   // The modifier up key event to be sent on non modifier key on ENABLED state.
273   scoped_ptr<ui::KeyEvent> modifier_up_event_;
274
275   DISALLOW_COPY_AND_ASSIGN(StickyKeysHandler);
276 };
277
278 }  // namespace ash
279
280 #endif  // ASH_STICKY_KEYS_STICKY_KEYS_CONTROLLER_H_