| 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 |