OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/sticky_keys/sticky_keys_controller.h" | 5 #include "ash/sticky_keys/sticky_keys_controller.h" |
6 | 6 |
| 7 #if defined(USE_X11) |
| 8 #include <X11/extensions/XInput2.h> |
| 9 #include <X11/Xlib.h> |
| 10 #undef RootWindow |
| 11 #endif |
| 12 |
7 #include "ash/sticky_keys/sticky_keys_overlay.h" | 13 #include "ash/sticky_keys/sticky_keys_overlay.h" |
8 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
9 #include "base/debug/stack_trace.h" | 15 #include "base/debug/stack_trace.h" |
10 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
11 #include "ui/aura/window_tracker.h" | 17 #include "ui/aura/window_tracker.h" |
12 #include "ui/aura/window_tree_host.h" | 18 #include "ui/aura/window_tree_host.h" |
13 #include "ui/events/event.h" | 19 #include "ui/events/event.h" |
14 #include "ui/events/event_processor.h" | 20 #include "ui/events/event_processor.h" |
15 #include "ui/events/keycodes/keyboard_code_conversion.h" | 21 #include "ui/events/keycodes/keyboard_code_conversion.h" |
16 | 22 |
17 namespace ash { | 23 namespace ash { |
18 | 24 |
19 namespace { | 25 namespace { |
20 | 26 |
21 // Returns true if the type of mouse event should be modified by sticky keys. | 27 // Returns true if the type of mouse event should be modified by sticky keys. |
22 bool ShouldModifyMouseEvent(const ui::MouseEvent& event) { | 28 bool ShouldModifyMouseEvent(ui::MouseEvent* event) { |
23 ui::EventType type = event.type(); | 29 ui::EventType type = event->type(); |
24 return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || | 30 return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || |
25 type == ui::ET_MOUSEWHEEL; | 31 type == ui::ET_MOUSEWHEEL; |
26 } | 32 } |
27 | 33 |
28 // Handle the common tail of event rewriting. | 34 // An implementation of StickyKeysHandler::StickyKeysHandlerDelegate. |
29 ui::EventRewriteStatus RewriteUpdate(bool consumed, | 35 class StickyKeysHandlerDelegateImpl : |
30 bool released, | 36 public StickyKeysHandler::StickyKeysHandlerDelegate { |
31 int mod_down_flags, | 37 public: |
32 int* flags) { | 38 StickyKeysHandlerDelegateImpl(); |
33 int changed_down_flags = mod_down_flags & ~*flags; | 39 virtual ~StickyKeysHandlerDelegateImpl(); |
34 *flags |= mod_down_flags; | 40 |
35 if (consumed) | 41 // StickyKeysHandlerDelegate overrides. |
36 return ui::EVENT_REWRITE_DISCARD; | 42 virtual void DispatchKeyEvent(ui::KeyEvent* event, |
37 if (released) | 43 aura::Window* target) OVERRIDE; |
38 return ui::EVENT_REWRITE_DISPATCH_ANOTHER; | 44 |
39 if (changed_down_flags) | 45 virtual void DispatchMouseEvent(ui::MouseEvent* event, |
40 return ui::EVENT_REWRITE_REWRITTEN; | 46 aura::Window* target) OVERRIDE; |
41 return ui::EVENT_REWRITE_CONTINUE; | 47 |
| 48 virtual void DispatchScrollEvent(ui::ScrollEvent* event, |
| 49 aura::Window* target) OVERRIDE; |
| 50 private: |
| 51 void DispatchEvent(ui::Event* event, aura::Window* target); |
| 52 |
| 53 DISALLOW_COPY_AND_ASSIGN(StickyKeysHandlerDelegateImpl); |
| 54 }; |
| 55 |
| 56 StickyKeysHandlerDelegateImpl::StickyKeysHandlerDelegateImpl() { |
| 57 } |
| 58 |
| 59 StickyKeysHandlerDelegateImpl::~StickyKeysHandlerDelegateImpl() { |
| 60 } |
| 61 |
| 62 void StickyKeysHandlerDelegateImpl::DispatchKeyEvent(ui::KeyEvent* event, |
| 63 aura::Window* target) { |
| 64 DispatchEvent(event, target); |
| 65 } |
| 66 |
| 67 void StickyKeysHandlerDelegateImpl::DispatchMouseEvent(ui::MouseEvent* event, |
| 68 aura::Window* target) { |
| 69 DCHECK(target); |
| 70 // We need to send a new, untransformed mouse event to the host. |
| 71 if (event->IsMouseWheelEvent()) { |
| 72 aura::Window* source = static_cast<aura::Window*>(event->target()); |
| 73 ui::MouseWheelEvent new_event(*static_cast<ui::MouseWheelEvent*>(event), |
| 74 source, |
| 75 source->GetRootWindow()); |
| 76 // Transform the location back to host coordinates before dispatching. |
| 77 new_event.UpdateForRootTransform(source->GetHost()->GetRootTransform()); |
| 78 DispatchEvent(&new_event, target); |
| 79 } else { |
| 80 aura::Window* source = static_cast<aura::Window*>(event->target()); |
| 81 ui::MouseEvent new_event(*event, source, source->GetRootWindow()); |
| 82 // Transform the location back to host coordinates before dispatching. |
| 83 new_event.UpdateForRootTransform(source->GetHost()->GetRootTransform()); |
| 84 DispatchEvent(&new_event, target); |
| 85 } |
| 86 } |
| 87 |
| 88 void StickyKeysHandlerDelegateImpl::DispatchScrollEvent( |
| 89 ui::ScrollEvent* event, |
| 90 aura::Window* target) { |
| 91 DispatchEvent(event, target); |
| 92 } |
| 93 |
| 94 void StickyKeysHandlerDelegateImpl::DispatchEvent(ui::Event* event, |
| 95 aura::Window* target) { |
| 96 DCHECK(target); |
| 97 ui::EventDispatchDetails details = |
| 98 target->GetHost()->event_processor()->OnEventFromSource(event); |
| 99 if (details.dispatcher_destroyed) |
| 100 return; |
42 } | 101 } |
43 | 102 |
44 } // namespace | 103 } // namespace |
45 | 104 |
46 /////////////////////////////////////////////////////////////////////////////// | 105 /////////////////////////////////////////////////////////////////////////////// |
47 // StickyKeys | 106 // StickyKeys |
48 StickyKeysController::StickyKeysController() | 107 StickyKeysController::StickyKeysController() |
49 : enabled_(false), | 108 : enabled_(false), |
50 mod3_enabled_(false), | 109 mod3_enabled_(false), |
51 altgr_enabled_(false) { | 110 altgr_enabled_(false) { |
52 } | 111 } |
53 | 112 |
54 StickyKeysController::~StickyKeysController() { | 113 StickyKeysController::~StickyKeysController() { |
55 } | 114 } |
56 | 115 |
57 void StickyKeysController::Enable(bool enabled) { | 116 void StickyKeysController::Enable(bool enabled) { |
58 if (enabled_ != enabled) { | 117 if (enabled_ != enabled) { |
59 enabled_ = enabled; | 118 enabled_ = enabled; |
60 | 119 |
61 // Reset key handlers when activating sticky keys to ensure all | 120 // Reset key handlers when activating sticky keys to ensure all |
62 // the handlers' states are reset. | 121 // the handlers' states are reset. |
63 if (enabled_) { | 122 if (enabled_) { |
64 shift_sticky_key_.reset(new StickyKeysHandler(ui::EF_SHIFT_DOWN)); | 123 shift_sticky_key_.reset( |
65 alt_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALT_DOWN)); | 124 new StickyKeysHandler(ui::EF_SHIFT_DOWN, |
66 altgr_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALTGR_DOWN)); | 125 new StickyKeysHandlerDelegateImpl())); |
67 ctrl_sticky_key_.reset(new StickyKeysHandler(ui::EF_CONTROL_DOWN)); | 126 alt_sticky_key_.reset( |
68 mod3_sticky_key_.reset(new StickyKeysHandler(ui::EF_MOD3_DOWN)); | 127 new StickyKeysHandler(ui::EF_ALT_DOWN, |
| 128 new StickyKeysHandlerDelegateImpl())); |
| 129 altgr_sticky_key_.reset( |
| 130 new StickyKeysHandler(ui::EF_ALTGR_DOWN, |
| 131 new StickyKeysHandlerDelegateImpl())); |
| 132 ctrl_sticky_key_.reset( |
| 133 new StickyKeysHandler(ui::EF_CONTROL_DOWN, |
| 134 new StickyKeysHandlerDelegateImpl())); |
| 135 mod3_sticky_key_.reset( |
| 136 new StickyKeysHandler(ui::EF_MOD3_DOWN, |
| 137 new StickyKeysHandlerDelegateImpl())); |
69 | 138 |
70 overlay_.reset(new StickyKeysOverlay()); | 139 overlay_.reset(new StickyKeysOverlay()); |
71 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); | 140 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); |
72 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); | 141 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); |
73 } else if (overlay_) { | 142 } else if (overlay_) { |
74 overlay_->Show(false); | 143 overlay_->Show(false); |
75 } | 144 } |
76 } | 145 } |
77 } | 146 } |
78 | 147 |
79 void StickyKeysController::SetModifiersEnabled(bool mod3_enabled, | 148 void StickyKeysController::SetModifiersEnabled(bool mod3_enabled, |
80 bool altgr_enabled) { | 149 bool altgr_enabled) { |
81 mod3_enabled_ = mod3_enabled; | 150 mod3_enabled_ = mod3_enabled; |
82 altgr_enabled_ = altgr_enabled; | 151 altgr_enabled_ = altgr_enabled; |
83 if (overlay_) { | 152 if (overlay_) { |
84 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); | 153 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); |
85 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); | 154 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); |
86 } | 155 } |
87 } | 156 } |
88 | 157 |
89 bool StickyKeysController::HandleKeyEvent(const ui::KeyEvent& event, | 158 bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) { |
90 ui::KeyboardCode key_code, | 159 return shift_sticky_key_->HandleKeyEvent(event) || |
91 int* mod_down_flags, | 160 alt_sticky_key_->HandleKeyEvent(event) || |
92 bool* released) { | 161 altgr_sticky_key_->HandleKeyEvent(event) || |
93 return shift_sticky_key_->HandleKeyEvent( | 162 ctrl_sticky_key_->HandleKeyEvent(event) || |
94 event, key_code, mod_down_flags, released) || | 163 mod3_sticky_key_->HandleKeyEvent(event); |
95 alt_sticky_key_->HandleKeyEvent( | |
96 event, key_code, mod_down_flags, released) || | |
97 altgr_sticky_key_->HandleKeyEvent( | |
98 event, key_code, mod_down_flags, released) || | |
99 ctrl_sticky_key_->HandleKeyEvent( | |
100 event, key_code, mod_down_flags, released) || | |
101 mod3_sticky_key_->HandleKeyEvent( | |
102 event, key_code, mod_down_flags, released); | |
103 } | 164 } |
104 | 165 |
105 bool StickyKeysController::HandleMouseEvent(const ui::MouseEvent& event, | 166 bool StickyKeysController::HandleMouseEvent(ui::MouseEvent* event) { |
106 int* mod_down_flags, | 167 return shift_sticky_key_->HandleMouseEvent(event) || |
107 bool* released) { | 168 alt_sticky_key_->HandleMouseEvent(event) || |
108 return shift_sticky_key_->HandleMouseEvent( | 169 altgr_sticky_key_->HandleMouseEvent(event) || |
109 event, mod_down_flags, released) || | 170 ctrl_sticky_key_->HandleMouseEvent(event) || |
110 alt_sticky_key_->HandleMouseEvent( | 171 mod3_sticky_key_->HandleMouseEvent(event); |
111 event, mod_down_flags, released) || | |
112 altgr_sticky_key_->HandleMouseEvent( | |
113 event, mod_down_flags, released) || | |
114 ctrl_sticky_key_->HandleMouseEvent( | |
115 event, mod_down_flags, released) || | |
116 mod3_sticky_key_->HandleMouseEvent( | |
117 event, mod_down_flags, released); | |
118 } | 172 } |
119 | 173 |
120 bool StickyKeysController::HandleScrollEvent(const ui::ScrollEvent& event, | 174 bool StickyKeysController::HandleScrollEvent(ui::ScrollEvent* event) { |
121 int* mod_down_flags, | 175 return shift_sticky_key_->HandleScrollEvent(event) || |
122 bool* released) { | 176 alt_sticky_key_->HandleScrollEvent(event) || |
123 return shift_sticky_key_->HandleScrollEvent( | 177 altgr_sticky_key_->HandleScrollEvent(event) || |
124 event, mod_down_flags, released) || | 178 ctrl_sticky_key_->HandleScrollEvent(event) || |
125 alt_sticky_key_->HandleScrollEvent( | 179 mod3_sticky_key_->HandleScrollEvent(event); |
126 event, mod_down_flags, released) || | |
127 altgr_sticky_key_->HandleScrollEvent( | |
128 event, mod_down_flags, released) || | |
129 ctrl_sticky_key_->HandleScrollEvent( | |
130 event, mod_down_flags, released) || | |
131 mod3_sticky_key_->HandleScrollEvent( | |
132 event, mod_down_flags, released); | |
133 } | 180 } |
134 | 181 |
135 ui::EventRewriteStatus StickyKeysController::RewriteKeyEvent( | 182 void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) { |
136 const ui::KeyEvent& event, | 183 // Do not consume a translated key event which is generated by an IME. |
137 ui::KeyboardCode key_code, | 184 if (event->IsTranslated()) |
138 int* flags) { | 185 return; |
139 if (!enabled_) | 186 |
140 return ui::EVENT_REWRITE_CONTINUE; | 187 if (enabled_) { |
141 int mod_down_flags = 0; | 188 if (HandleKeyEvent(event)) |
142 bool released = false; | 189 event->StopPropagation(); |
143 bool consumed = HandleKeyEvent(event, key_code, &mod_down_flags, &released); | 190 UpdateOverlay(); |
144 UpdateOverlay(); | 191 } |
145 return RewriteUpdate(consumed, released, mod_down_flags, flags); | |
146 } | 192 } |
147 | 193 |
148 ui::EventRewriteStatus StickyKeysController::RewriteMouseEvent( | 194 void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) { |
149 const ui::MouseEvent& event, | 195 if (enabled_) { |
150 int* flags) { | 196 if (HandleMouseEvent(event)) |
151 if (!enabled_) | 197 event->StopPropagation(); |
152 return ui::EVENT_REWRITE_CONTINUE; | 198 UpdateOverlay(); |
153 int mod_down_flags = 0; | 199 } |
154 bool released = false; | |
155 bool consumed = HandleMouseEvent(event, &mod_down_flags, &released); | |
156 UpdateOverlay(); | |
157 return RewriteUpdate(consumed, released, mod_down_flags, flags); | |
158 } | 200 } |
159 | 201 |
160 ui::EventRewriteStatus StickyKeysController::RewriteScrollEvent( | 202 void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) { |
161 const ui::ScrollEvent& event, | 203 if (enabled_) { |
162 int* flags) { | 204 if (HandleScrollEvent(event)) |
163 if (!enabled_) | 205 event->StopPropagation(); |
164 return ui::EVENT_REWRITE_CONTINUE; | 206 UpdateOverlay(); |
165 int mod_down_flags = 0; | 207 } |
166 bool released = false; | |
167 bool consumed = HandleScrollEvent(event, &mod_down_flags, &released); | |
168 UpdateOverlay(); | |
169 return RewriteUpdate(consumed, released, mod_down_flags, flags); | |
170 } | |
171 | |
172 ui::EventRewriteStatus StickyKeysController::NextDispatchEvent( | |
173 scoped_ptr<ui::Event>* new_event) { | |
174 DCHECK(new_event); | |
175 new_event->reset(); | |
176 int remaining = shift_sticky_key_->GetModifierUpEvent(new_event) + | |
177 alt_sticky_key_->GetModifierUpEvent(new_event) + | |
178 altgr_sticky_key_->GetModifierUpEvent(new_event) + | |
179 ctrl_sticky_key_->GetModifierUpEvent(new_event) + | |
180 mod3_sticky_key_->GetModifierUpEvent(new_event); | |
181 if (!new_event) | |
182 return ui::EVENT_REWRITE_CONTINUE; | |
183 if (remaining) | |
184 return ui::EVENT_REWRITE_DISPATCH_ANOTHER; | |
185 return ui::EVENT_REWRITE_REWRITTEN; | |
186 } | 208 } |
187 | 209 |
188 void StickyKeysController::UpdateOverlay() { | 210 void StickyKeysController::UpdateOverlay() { |
189 overlay_->SetModifierKeyState( | 211 overlay_->SetModifierKeyState( |
190 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state()); | 212 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state()); |
191 overlay_->SetModifierKeyState( | 213 overlay_->SetModifierKeyState( |
192 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state()); | 214 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state()); |
193 overlay_->SetModifierKeyState( | 215 overlay_->SetModifierKeyState( |
194 ui::EF_ALT_DOWN, alt_sticky_key_->current_state()); | 216 ui::EF_ALT_DOWN, alt_sticky_key_->current_state()); |
195 overlay_->SetModifierKeyState( | 217 overlay_->SetModifierKeyState( |
(...skipping 10 matching lines...) Expand all Loading... |
206 | 228 |
207 overlay_->Show(enabled_ && key_in_use); | 229 overlay_->Show(enabled_ && key_in_use); |
208 } | 230 } |
209 | 231 |
210 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() { | 232 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() { |
211 return overlay_.get(); | 233 return overlay_.get(); |
212 } | 234 } |
213 | 235 |
214 /////////////////////////////////////////////////////////////////////////////// | 236 /////////////////////////////////////////////////////////////////////////////// |
215 // StickyKeysHandler | 237 // StickyKeysHandler |
216 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag) | 238 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag, |
| 239 StickyKeysHandlerDelegate* delegate) |
217 : modifier_flag_(modifier_flag), | 240 : modifier_flag_(modifier_flag), |
218 current_state_(STICKY_KEY_STATE_DISABLED), | 241 current_state_(STICKY_KEY_STATE_DISABLED), |
| 242 event_from_myself_(false), |
219 preparing_to_enable_(false), | 243 preparing_to_enable_(false), |
220 scroll_delta_(0) { | 244 scroll_delta_(0), |
| 245 delegate_(delegate) { |
221 } | 246 } |
222 | 247 |
223 StickyKeysHandler::~StickyKeysHandler() { | 248 StickyKeysHandler::~StickyKeysHandler() { |
224 } | 249 } |
225 | 250 |
226 bool StickyKeysHandler::HandleKeyEvent(const ui::KeyEvent& event, | 251 StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { |
227 ui::KeyboardCode key_code, | 252 } |
228 int* mod_down_flags, | 253 |
229 bool* released) { | 254 StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { |
| 255 } |
| 256 |
| 257 bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) { |
| 258 if (event_from_myself_) |
| 259 return false; // Do not handle self-generated key event. |
230 switch (current_state_) { | 260 switch (current_state_) { |
231 case STICKY_KEY_STATE_DISABLED: | 261 case STICKY_KEY_STATE_DISABLED: |
232 return HandleDisabledState(event, key_code); | 262 return HandleDisabledState(event); |
233 case STICKY_KEY_STATE_ENABLED: | 263 case STICKY_KEY_STATE_ENABLED: |
234 return HandleEnabledState(event, key_code, mod_down_flags, released); | 264 return HandleEnabledState(event); |
235 case STICKY_KEY_STATE_LOCKED: | 265 case STICKY_KEY_STATE_LOCKED: |
236 return HandleLockedState(event, key_code, mod_down_flags, released); | 266 return HandleLockedState(event); |
237 } | 267 } |
238 NOTREACHED(); | 268 NOTREACHED(); |
239 return false; | 269 return false; |
240 } | 270 } |
241 | 271 |
242 bool StickyKeysHandler::HandleMouseEvent( | 272 bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { |
243 const ui::MouseEvent& event, | |
244 int* mod_down_flags, | |
245 bool* released) { | |
246 if (ShouldModifyMouseEvent(event)) | 273 if (ShouldModifyMouseEvent(event)) |
247 preparing_to_enable_ = false; | 274 preparing_to_enable_ = false; |
248 | 275 |
249 if (current_state_ == STICKY_KEY_STATE_DISABLED || | 276 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED |
250 !ShouldModifyMouseEvent(event)) { | 277 || !ShouldModifyMouseEvent(event)) { |
251 return false; | 278 return false; |
252 } | 279 } |
253 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || | 280 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
254 current_state_ == STICKY_KEY_STATE_LOCKED); | 281 current_state_ == STICKY_KEY_STATE_LOCKED); |
255 | 282 |
256 *mod_down_flags |= modifier_flag_; | 283 AppendModifier(event); |
257 // Only disable on the mouse released event in normal, non-locked mode. | 284 // Only disable on the mouse released event in normal, non-locked mode. |
258 if (current_state_ == STICKY_KEY_STATE_ENABLED && | 285 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
259 event.type() != ui::ET_MOUSE_PRESSED) { | 286 event->type() != ui::ET_MOUSE_PRESSED) { |
260 current_state_ = STICKY_KEY_STATE_DISABLED; | 287 current_state_ = STICKY_KEY_STATE_DISABLED; |
261 *released = true; | 288 DispatchEventAndReleaseModifier(event); |
262 return false; | 289 return true; |
263 } | 290 } |
264 | 291 |
265 return false; | 292 return false; |
266 } | 293 } |
267 | 294 |
268 bool StickyKeysHandler::HandleScrollEvent( | 295 bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { |
269 const ui::ScrollEvent& event, | |
270 int* mod_down_flags, | |
271 bool* released) { | |
272 preparing_to_enable_ = false; | 296 preparing_to_enable_ = false; |
273 if (current_state_ == STICKY_KEY_STATE_DISABLED) | 297 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED) |
274 return false; | 298 return false; |
275 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || | 299 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
276 current_state_ == STICKY_KEY_STATE_LOCKED); | 300 current_state_ == STICKY_KEY_STATE_LOCKED); |
277 | 301 |
278 // We detect a direction change if the current |scroll_delta_| is assigned | 302 // We detect a direction change if the current |scroll_delta_| is assigned |
279 // and the offset of the current scroll event has the opposing sign. | 303 // and the offset of the current scroll event has the opposing sign. |
280 bool direction_changed = false; | 304 bool direction_changed = false; |
281 if (current_state_ == STICKY_KEY_STATE_ENABLED && | 305 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
282 event.type() == ui::ET_SCROLL) { | 306 event->type() == ui::ET_SCROLL) { |
283 int offset = event.y_offset(); | 307 int offset = event->y_offset(); |
284 if (scroll_delta_) | 308 if (scroll_delta_) |
285 direction_changed = offset * scroll_delta_ <= 0; | 309 direction_changed = offset * scroll_delta_ <= 0; |
286 scroll_delta_ = offset; | 310 scroll_delta_ = offset; |
287 } | 311 } |
288 | 312 |
289 if (!direction_changed) | 313 if (!direction_changed) |
290 *mod_down_flags |= modifier_flag_; | 314 AppendModifier(event); |
291 | 315 |
292 // We want to modify all the scroll events in the scroll sequence, which ends | 316 // We want to modify all the scroll events in the scroll sequence, which ends |
293 // with a fling start event. We also stop when the scroll sequence changes | 317 // with a fling start event. We also stop when the scroll sequence changes |
294 // direction. | 318 // direction. |
295 if (current_state_ == STICKY_KEY_STATE_ENABLED && | 319 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
296 (event.type() == ui::ET_SCROLL_FLING_START || direction_changed)) { | 320 (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { |
297 current_state_ = STICKY_KEY_STATE_DISABLED; | 321 current_state_ = STICKY_KEY_STATE_DISABLED; |
298 scroll_delta_ = 0; | 322 scroll_delta_ = 0; |
299 *released = true; | 323 DispatchEventAndReleaseModifier(event); |
300 return false; | 324 return true; |
301 } | 325 } |
302 | 326 |
303 return false; | 327 return false; |
304 } | 328 } |
305 | 329 |
306 int StickyKeysHandler::GetModifierUpEvent(scoped_ptr<ui::Event>* new_event) { | 330 StickyKeysHandler::KeyEventType |
307 if (current_state_ != STICKY_KEY_STATE_DISABLED || !modifier_up_event_) | 331 StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { |
308 return 0; | |
309 DCHECK(new_event); | |
310 if (*new_event) | |
311 return 1; | |
312 new_event->reset(modifier_up_event_.release()); | |
313 return 0; | |
314 } | |
315 | |
316 StickyKeysHandler::KeyEventType StickyKeysHandler::TranslateKeyEvent( | |
317 ui::EventType type, | |
318 ui::KeyboardCode key_code) { | |
319 bool is_target_key = false; | 332 bool is_target_key = false; |
320 if (key_code == ui::VKEY_SHIFT || | 333 if (event->key_code() == ui::VKEY_SHIFT || |
321 key_code == ui::VKEY_LSHIFT || | 334 event->key_code() == ui::VKEY_LSHIFT || |
322 key_code == ui::VKEY_RSHIFT) { | 335 event->key_code() == ui::VKEY_RSHIFT) { |
323 is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); | 336 is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); |
324 } else if (key_code == ui::VKEY_CONTROL || | 337 } else if (event->key_code() == ui::VKEY_CONTROL || |
325 key_code == ui::VKEY_LCONTROL || | 338 event->key_code() == ui::VKEY_LCONTROL || |
326 key_code == ui::VKEY_RCONTROL) { | 339 event->key_code() == ui::VKEY_RCONTROL) { |
327 is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); | 340 is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); |
328 } else if (key_code == ui::VKEY_MENU || | 341 } else if (event->key_code() == ui::VKEY_MENU || |
329 key_code == ui::VKEY_LMENU || | 342 event->key_code() == ui::VKEY_LMENU || |
330 key_code == ui::VKEY_RMENU) { | 343 event->key_code() == ui::VKEY_RMENU) { |
331 is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); | 344 is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); |
332 } else if (key_code == ui::VKEY_ALTGR) { | 345 } else if (event->key_code() == ui::VKEY_ALTGR) { |
333 is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN); | 346 is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN); |
334 } else if (key_code == ui::VKEY_OEM_8) { | 347 } else if (event->key_code() == ui::VKEY_OEM_8) { |
335 is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN); | 348 is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN); |
336 } else { | 349 } else { |
337 return type == ui::ET_KEY_PRESSED ? | 350 return event->type() == ui::ET_KEY_PRESSED ? |
338 NORMAL_KEY_DOWN : NORMAL_KEY_UP; | 351 NORMAL_KEY_DOWN : NORMAL_KEY_UP; |
339 } | 352 } |
340 | 353 |
341 if (is_target_key) { | 354 if (is_target_key) { |
342 return type == ui::ET_KEY_PRESSED ? | 355 return event->type() == ui::ET_KEY_PRESSED ? |
343 TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; | 356 TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; |
344 } | 357 } |
345 return type == ui::ET_KEY_PRESSED ? | 358 return event->type() == ui::ET_KEY_PRESSED ? |
346 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; | 359 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; |
347 } | 360 } |
348 | 361 |
349 bool StickyKeysHandler::HandleDisabledState(const ui::KeyEvent& event, | 362 bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { |
350 ui::KeyboardCode key_code) { | 363 switch (TranslateKeyEvent(event)) { |
351 switch (TranslateKeyEvent(event.type(), key_code)) { | |
352 case TARGET_MODIFIER_UP: | 364 case TARGET_MODIFIER_UP: |
353 if (preparing_to_enable_) { | 365 if (preparing_to_enable_) { |
354 preparing_to_enable_ = false; | 366 preparing_to_enable_ = false; |
355 scroll_delta_ = 0; | 367 scroll_delta_ = 0; |
356 current_state_ = STICKY_KEY_STATE_ENABLED; | 368 current_state_ = STICKY_KEY_STATE_ENABLED; |
357 modifier_up_event_.reset(new ui::KeyEvent(event)); | 369 modifier_up_event_.reset(new ui::KeyEvent(*event)); |
358 return true; | 370 return true; |
359 } | 371 } |
360 return false; | 372 return false; |
361 case TARGET_MODIFIER_DOWN: | 373 case TARGET_MODIFIER_DOWN: |
362 preparing_to_enable_ = true; | 374 preparing_to_enable_ = true; |
363 return false; | 375 return false; |
364 case NORMAL_KEY_DOWN: | 376 case NORMAL_KEY_DOWN: |
365 preparing_to_enable_ = false; | 377 preparing_to_enable_ = false; |
366 return false; | 378 return false; |
367 case NORMAL_KEY_UP: | 379 case NORMAL_KEY_UP: |
368 case OTHER_MODIFIER_DOWN: | 380 case OTHER_MODIFIER_DOWN: |
369 case OTHER_MODIFIER_UP: | 381 case OTHER_MODIFIER_UP: |
370 return false; | 382 return false; |
371 } | 383 } |
372 NOTREACHED(); | 384 NOTREACHED(); |
373 return false; | 385 return false; |
374 } | 386 } |
375 | 387 |
376 bool StickyKeysHandler::HandleEnabledState(const ui::KeyEvent& event, | 388 bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { |
377 ui::KeyboardCode key_code, | 389 switch (TranslateKeyEvent(event)) { |
378 int* mod_down_flags, | |
379 bool* released) { | |
380 switch (TranslateKeyEvent(event.type(), key_code)) { | |
381 case NORMAL_KEY_UP: | 390 case NORMAL_KEY_UP: |
382 case TARGET_MODIFIER_DOWN: | 391 case TARGET_MODIFIER_DOWN: |
383 return false; | 392 return true; |
384 case TARGET_MODIFIER_UP: | 393 case TARGET_MODIFIER_UP: |
385 current_state_ = STICKY_KEY_STATE_LOCKED; | 394 current_state_ = STICKY_KEY_STATE_LOCKED; |
386 modifier_up_event_.reset(); | 395 modifier_up_event_.reset(); |
387 return true; | 396 return true; |
388 case NORMAL_KEY_DOWN: { | 397 case NORMAL_KEY_DOWN: { |
389 current_state_ = STICKY_KEY_STATE_DISABLED; | 398 current_state_ = STICKY_KEY_STATE_DISABLED; |
390 *mod_down_flags |= modifier_flag_; | 399 AppendModifier(event); |
391 *released = true; | 400 DispatchEventAndReleaseModifier(event); |
392 return false; | 401 return true; |
393 } | 402 } |
394 case OTHER_MODIFIER_DOWN: | 403 case OTHER_MODIFIER_DOWN: |
395 case OTHER_MODIFIER_UP: | 404 case OTHER_MODIFIER_UP: |
396 return false; | 405 return false; |
397 } | 406 } |
398 NOTREACHED(); | 407 NOTREACHED(); |
399 return false; | 408 return false; |
400 } | 409 } |
401 | 410 |
402 bool StickyKeysHandler::HandleLockedState(const ui::KeyEvent& event, | 411 bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { |
403 ui::KeyboardCode key_code, | 412 switch (TranslateKeyEvent(event)) { |
404 int* mod_down_flags, | |
405 bool* released) { | |
406 switch (TranslateKeyEvent(event.type(), key_code)) { | |
407 case TARGET_MODIFIER_DOWN: | 413 case TARGET_MODIFIER_DOWN: |
408 return true; | 414 return true; |
409 case TARGET_MODIFIER_UP: | 415 case TARGET_MODIFIER_UP: |
410 current_state_ = STICKY_KEY_STATE_DISABLED; | 416 current_state_ = STICKY_KEY_STATE_DISABLED; |
411 return false; | 417 return false; |
412 case NORMAL_KEY_DOWN: | 418 case NORMAL_KEY_DOWN: |
413 case NORMAL_KEY_UP: | 419 case NORMAL_KEY_UP: |
414 *mod_down_flags |= modifier_flag_; | 420 AppendModifier(event); |
415 return false; | 421 return false; |
416 case OTHER_MODIFIER_DOWN: | 422 case OTHER_MODIFIER_DOWN: |
417 case OTHER_MODIFIER_UP: | 423 case OTHER_MODIFIER_UP: |
418 return false; | 424 return false; |
419 } | 425 } |
420 NOTREACHED(); | 426 NOTREACHED(); |
421 return false; | 427 return false; |
422 } | 428 } |
423 | 429 |
| 430 void StickyKeysHandler::DispatchEventAndReleaseModifier(ui::Event* event) { |
| 431 DCHECK(event->IsKeyEvent() || |
| 432 event->IsMouseEvent() || |
| 433 event->IsScrollEvent()); |
| 434 DCHECK(modifier_up_event_.get()); |
| 435 aura::Window* target = static_cast<aura::Window*>(event->target()); |
| 436 DCHECK(target); |
| 437 aura::Window* root_window = target->GetRootWindow(); |
| 438 DCHECK(root_window); |
| 439 |
| 440 aura::WindowTracker window_tracker; |
| 441 window_tracker.Add(target); |
| 442 |
| 443 event_from_myself_ = true; |
| 444 if (event->IsKeyEvent()) { |
| 445 delegate_->DispatchKeyEvent(static_cast<ui::KeyEvent*>(event), target); |
| 446 } else if (event->IsMouseEvent()) { |
| 447 delegate_->DispatchMouseEvent(static_cast<ui::MouseEvent*>(event), target); |
| 448 } else { |
| 449 delegate_->DispatchScrollEvent( |
| 450 static_cast<ui::ScrollEvent*>(event), target); |
| 451 } |
| 452 |
| 453 // The action triggered above may have destroyed the event target, in which |
| 454 // case we will dispatch the modifier up event to the root window instead. |
| 455 aura::Window* modifier_up_target = |
| 456 window_tracker.Contains(target) ? target : root_window; |
| 457 delegate_->DispatchKeyEvent(modifier_up_event_.get(), modifier_up_target); |
| 458 event_from_myself_ = false; |
| 459 } |
| 460 |
| 461 void StickyKeysHandler::AppendNativeEventMask(unsigned int* state) { |
| 462 #if defined(USE_X11) |
| 463 unsigned int& state_ref = *state; |
| 464 switch (modifier_flag_) { |
| 465 case ui::EF_CONTROL_DOWN: |
| 466 state_ref |= ControlMask; |
| 467 break; |
| 468 case ui::EF_ALT_DOWN: |
| 469 state_ref |= Mod1Mask; |
| 470 break; |
| 471 case ui::EF_ALTGR_DOWN: |
| 472 state_ref |= Mod5Mask; |
| 473 break; |
| 474 case ui::EF_SHIFT_DOWN: |
| 475 state_ref |= ShiftMask; |
| 476 break; |
| 477 case ui::EF_MOD3_DOWN: |
| 478 state_ref |= Mod3Mask; |
| 479 break; |
| 480 default: |
| 481 NOTREACHED(); |
| 482 } |
| 483 #endif |
| 484 } |
| 485 |
| 486 void StickyKeysHandler::AppendModifier(ui::KeyEvent* event) { |
| 487 #if defined(USE_X11) |
| 488 XEvent* xev = event->native_event(); |
| 489 if (xev) { |
| 490 XKeyEvent* xkey = &(xev->xkey); |
| 491 AppendNativeEventMask(&xkey->state); |
| 492 } |
| 493 #elif defined(USE_OZONE) |
| 494 NOTIMPLEMENTED() << "Modifier key is not handled"; |
| 495 #endif |
| 496 event->set_flags(event->flags() | modifier_flag_); |
| 497 event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), |
| 498 event->flags())); |
| 499 event->NormalizeFlags(); |
| 500 } |
| 501 |
| 502 void StickyKeysHandler::AppendModifier(ui::MouseEvent* event) { |
| 503 #if defined(USE_X11) |
| 504 // The native mouse event can either be a classic X button event or an |
| 505 // XInput2 button event. |
| 506 XEvent* xev = event->native_event(); |
| 507 if (xev) { |
| 508 switch (xev->type) { |
| 509 case ButtonPress: |
| 510 case ButtonRelease: { |
| 511 XButtonEvent* xkey = &(xev->xbutton); |
| 512 AppendNativeEventMask(&xkey->state); |
| 513 break; |
| 514 } |
| 515 case GenericEvent: { |
| 516 XIDeviceEvent* xievent = |
| 517 static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| 518 CHECK(xievent->evtype == XI_ButtonPress || |
| 519 xievent->evtype == XI_ButtonRelease); |
| 520 AppendNativeEventMask( |
| 521 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
| 522 break; |
| 523 } |
| 524 default: |
| 525 NOTREACHED(); |
| 526 } |
| 527 } |
| 528 #elif defined(USE_OZONE) |
| 529 NOTIMPLEMENTED() << "Modifier key is not handled"; |
| 530 #endif |
| 531 event->set_flags(event->flags() | modifier_flag_); |
| 532 } |
| 533 |
| 534 void StickyKeysHandler::AppendModifier(ui::ScrollEvent* event) { |
| 535 #if defined(USE_X11) |
| 536 XEvent* xev = event->native_event(); |
| 537 if (xev) { |
| 538 XIDeviceEvent* xievent = |
| 539 static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| 540 if (xievent) { |
| 541 AppendNativeEventMask(reinterpret_cast<unsigned int*>( |
| 542 &xievent->mods.effective)); |
| 543 } |
| 544 } |
| 545 #elif defined(USE_OZONE) |
| 546 NOTIMPLEMENTED() << "Modifier key is not handled"; |
| 547 #endif |
| 548 event->set_flags(event->flags() | modifier_flag_); |
| 549 } |
| 550 |
424 } // namespace ash | 551 } // namespace ash |
OLD | NEW |