Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(770)

Side by Side Diff: ash/sticky_keys/sticky_keys_controller.cc

Issue 255033003: Convert sticky keys to a chromeos::EventRewriter phase. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@x354034-er
Patch Set: address review comments from sadrul Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
13 #include "ash/sticky_keys/sticky_keys_overlay.h" 7 #include "ash/sticky_keys/sticky_keys_overlay.h"
14 #include "base/basictypes.h" 8 #include "base/basictypes.h"
15 #include "base/debug/stack_trace.h" 9 #include "base/debug/stack_trace.h"
16 #include "ui/aura/window.h" 10 #include "ui/aura/window.h"
17 #include "ui/aura/window_tracker.h" 11 #include "ui/aura/window_tracker.h"
18 #include "ui/aura/window_tree_host.h" 12 #include "ui/aura/window_tree_host.h"
19 #include "ui/events/event.h" 13 #include "ui/events/event.h"
20 #include "ui/events/event_processor.h" 14 #include "ui/events/event_processor.h"
21 #include "ui/events/keycodes/keyboard_code_conversion.h" 15 #include "ui/events/keycodes/keyboard_code_conversion.h"
22 16
23 namespace ash { 17 namespace ash {
24 18
25 namespace { 19 namespace {
26 20
27 // Returns true if the type of mouse event should be modified by sticky keys. 21 // Returns true if the type of mouse event should be modified by sticky keys.
28 bool ShouldModifyMouseEvent(ui::MouseEvent* event) { 22 bool ShouldModifyMouseEvent(const ui::MouseEvent& event) {
29 ui::EventType type = event->type(); 23 ui::EventType type = event.type();
30 return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || 24 return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED ||
31 type == ui::ET_MOUSEWHEEL; 25 type == ui::ET_MOUSEWHEEL;
32 } 26 }
33 27
34 // An implementation of StickyKeysHandler::StickyKeysHandlerDelegate. 28 // Handle the common tail of event rewriting.
35 class StickyKeysHandlerDelegateImpl : 29 ui::EventRewriteStatus RewriteUpdate(bool consumed,
36 public StickyKeysHandler::StickyKeysHandlerDelegate { 30 int mod_up_flags,
37 public: 31 int mod_down_flags,
38 StickyKeysHandlerDelegateImpl(); 32 int* flags) {
39 virtual ~StickyKeysHandlerDelegateImpl(); 33 int changed_down_flags = mod_down_flags & ~*flags;
40 34 *flags |= mod_down_flags;
41 // StickyKeysHandlerDelegate overrides. 35 if (consumed)
42 virtual void DispatchKeyEvent(ui::KeyEvent* event, 36 return ui::EVENT_REWRITE_DISCARD;
43 aura::Window* target) OVERRIDE; 37 if (mod_up_flags)
Tim Song 2014/06/16 18:32:23 It seems that |mod_up_flags| is only being used he
kpschoedel 2014/06/16 21:09:08 In an earlier iteration the union of 'unstuck' mod
44 38 return ui::EVENT_REWRITE_DISPATCH_ANOTHER;
45 virtual void DispatchMouseEvent(ui::MouseEvent* event, 39 if (changed_down_flags)
46 aura::Window* target) OVERRIDE; 40 return ui::EVENT_REWRITE_REWRITTEN;
47 41 return ui::EVENT_REWRITE_CONTINUE;
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;
101 } 42 }
102 43
103 } // namespace 44 } // namespace
104 45
105 /////////////////////////////////////////////////////////////////////////////// 46 ///////////////////////////////////////////////////////////////////////////////
106 // StickyKeys 47 // StickyKeys
107 StickyKeysController::StickyKeysController() 48 StickyKeysController::StickyKeysController()
108 : enabled_(false), 49 : enabled_(false),
109 mod3_enabled_(false), 50 mod3_enabled_(false),
110 altgr_enabled_(false) { 51 altgr_enabled_(false) {
111 } 52 }
112 53
113 StickyKeysController::~StickyKeysController() { 54 StickyKeysController::~StickyKeysController() {
114 } 55 }
115 56
116 void StickyKeysController::Enable(bool enabled) { 57 void StickyKeysController::Enable(bool enabled) {
117 if (enabled_ != enabled) { 58 if (enabled_ != enabled) {
118 enabled_ = enabled; 59 enabled_ = enabled;
119 60
120 // Reset key handlers when activating sticky keys to ensure all 61 // Reset key handlers when activating sticky keys to ensure all
121 // the handlers' states are reset. 62 // the handlers' states are reset.
122 if (enabled_) { 63 if (enabled_) {
123 shift_sticky_key_.reset( 64 shift_sticky_key_.reset(new StickyKeysHandler(ui::EF_SHIFT_DOWN));
124 new StickyKeysHandler(ui::EF_SHIFT_DOWN, 65 alt_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALT_DOWN));
125 new StickyKeysHandlerDelegateImpl())); 66 altgr_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALTGR_DOWN));
126 alt_sticky_key_.reset( 67 ctrl_sticky_key_.reset(new StickyKeysHandler(ui::EF_CONTROL_DOWN));
127 new StickyKeysHandler(ui::EF_ALT_DOWN, 68 mod3_sticky_key_.reset(new StickyKeysHandler(ui::EF_MOD3_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()));
138 69
139 overlay_.reset(new StickyKeysOverlay()); 70 overlay_.reset(new StickyKeysOverlay());
140 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); 71 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_);
141 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); 72 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_);
142 } else if (overlay_) { 73 } else if (overlay_) {
143 overlay_->Show(false); 74 overlay_->Show(false);
144 } 75 }
145 } 76 }
146 } 77 }
147 78
148 void StickyKeysController::SetModifiersEnabled(bool mod3_enabled, 79 void StickyKeysController::SetModifiersEnabled(bool mod3_enabled,
149 bool altgr_enabled) { 80 bool altgr_enabled) {
150 mod3_enabled_ = mod3_enabled; 81 mod3_enabled_ = mod3_enabled;
151 altgr_enabled_ = altgr_enabled; 82 altgr_enabled_ = altgr_enabled;
152 if (overlay_) { 83 if (overlay_) {
153 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); 84 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_);
154 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); 85 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_);
155 } 86 }
156 } 87 }
157 88
158 bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) { 89 bool StickyKeysController::HandleKeyEvent(const ui::KeyEvent& event,
159 return shift_sticky_key_->HandleKeyEvent(event) || 90 ui::KeyboardCode key_code,
160 alt_sticky_key_->HandleKeyEvent(event) || 91 int* mod_down_flags,
161 altgr_sticky_key_->HandleKeyEvent(event) || 92 int* mod_up_flags) {
162 ctrl_sticky_key_->HandleKeyEvent(event) || 93 return shift_sticky_key_->HandleKeyEvent(
163 mod3_sticky_key_->HandleKeyEvent(event); 94 event, key_code, mod_down_flags, mod_up_flags) ||
95 alt_sticky_key_->HandleKeyEvent(
96 event, key_code, mod_down_flags, mod_up_flags) ||
97 altgr_sticky_key_->HandleKeyEvent(
98 event, key_code, mod_down_flags, mod_up_flags) ||
99 ctrl_sticky_key_->HandleKeyEvent(
100 event, key_code, mod_down_flags, mod_up_flags) ||
101 mod3_sticky_key_->HandleKeyEvent(
102 event, key_code, mod_down_flags, mod_up_flags);
164 } 103 }
165 104
166 bool StickyKeysController::HandleMouseEvent(ui::MouseEvent* event) { 105 bool StickyKeysController::HandleMouseEvent(const ui::MouseEvent& event,
167 return shift_sticky_key_->HandleMouseEvent(event) || 106 int* mod_down_flags,
168 alt_sticky_key_->HandleMouseEvent(event) || 107 int* mod_up_flags) {
169 altgr_sticky_key_->HandleMouseEvent(event) || 108 return shift_sticky_key_->HandleMouseEvent(
170 ctrl_sticky_key_->HandleMouseEvent(event) || 109 event, mod_down_flags, mod_up_flags) ||
171 mod3_sticky_key_->HandleMouseEvent(event); 110 alt_sticky_key_->HandleMouseEvent(
111 event, mod_down_flags, mod_up_flags) ||
112 altgr_sticky_key_->HandleMouseEvent(
113 event, mod_down_flags, mod_up_flags) ||
114 ctrl_sticky_key_->HandleMouseEvent(
115 event, mod_down_flags, mod_up_flags) ||
116 mod3_sticky_key_->HandleMouseEvent(
117 event, mod_down_flags, mod_up_flags);
172 } 118 }
173 119
174 bool StickyKeysController::HandleScrollEvent(ui::ScrollEvent* event) { 120 bool StickyKeysController::HandleScrollEvent(const ui::ScrollEvent& event,
175 return shift_sticky_key_->HandleScrollEvent(event) || 121 int* mod_down_flags,
176 alt_sticky_key_->HandleScrollEvent(event) || 122 int* mod_up_flags) {
177 altgr_sticky_key_->HandleScrollEvent(event) || 123 return shift_sticky_key_->HandleScrollEvent(
178 ctrl_sticky_key_->HandleScrollEvent(event) || 124 event, mod_down_flags, mod_up_flags) ||
179 mod3_sticky_key_->HandleScrollEvent(event); 125 alt_sticky_key_->HandleScrollEvent(
126 event, mod_down_flags, mod_up_flags) ||
127 altgr_sticky_key_->HandleScrollEvent(
128 event, mod_down_flags, mod_up_flags) ||
129 ctrl_sticky_key_->HandleScrollEvent(
130 event, mod_down_flags, mod_up_flags) ||
131 mod3_sticky_key_->HandleScrollEvent(
132 event, mod_down_flags, mod_up_flags);
180 } 133 }
181 134
182 void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) { 135 ui::EventRewriteStatus StickyKeysController::RewriteKeyEvent(
183 // Do not consume a translated key event which is generated by an IME. 136 const ui::KeyEvent& event,
184 if (event->IsTranslated()) 137 ui::KeyboardCode key_code,
185 return; 138 int* flags) {
186 139 if (!enabled_)
187 if (enabled_) { 140 return ui::EVENT_REWRITE_CONTINUE;
188 if (HandleKeyEvent(event)) 141 int mod_down_flags = 0;
189 event->StopPropagation(); 142 int mod_up_flags = 0;
190 UpdateOverlay(); 143 bool consumed =
191 } 144 HandleKeyEvent(event, key_code, &mod_down_flags, &mod_up_flags);
145 UpdateOverlay();
146 return RewriteUpdate(consumed, mod_up_flags, mod_down_flags, flags);
192 } 147 }
193 148
194 void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) { 149 ui::EventRewriteStatus StickyKeysController::RewriteMouseEvent(
195 if (enabled_) { 150 const ui::MouseEvent& event,
196 if (HandleMouseEvent(event)) 151 int* flags) {
197 event->StopPropagation(); 152 if (!enabled_)
198 UpdateOverlay(); 153 return ui::EVENT_REWRITE_CONTINUE;
199 } 154 int mod_down_flags = 0;
155 int mod_up_flags = 0;
156 bool consumed = HandleMouseEvent(event, &mod_down_flags, &mod_up_flags);
157 UpdateOverlay();
158 return RewriteUpdate(consumed, mod_up_flags, mod_down_flags, flags);
200 } 159 }
201 160
202 void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) { 161 ui::EventRewriteStatus StickyKeysController::RewriteScrollEvent(
203 if (enabled_) { 162 const ui::ScrollEvent& event,
204 if (HandleScrollEvent(event)) 163 int* flags) {
205 event->StopPropagation(); 164 if (!enabled_)
206 UpdateOverlay(); 165 return ui::EVENT_REWRITE_CONTINUE;
207 } 166 int mod_down_flags = 0;
167 int mod_up_flags = 0;
168 bool consumed = HandleScrollEvent(event, &mod_down_flags, &mod_up_flags);
169 UpdateOverlay();
170 return RewriteUpdate(consumed, mod_up_flags, mod_down_flags, flags);
171 }
172
173 ui::EventRewriteStatus StickyKeysController::NextDispatchEvent(
174 scoped_ptr<ui::Event>* 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 return remaining ? ui::EVENT_REWRITE_DISPATCH_ANOTHER
Tim Song 2014/06/16 18:32:23 In the comments for this function in the header, i
kpschoedel 2014/06/16 21:09:08 Done.
182 : ui::EVENT_REWRITE_REWRITTEN;
208 } 183 }
209 184
210 void StickyKeysController::UpdateOverlay() { 185 void StickyKeysController::UpdateOverlay() {
211 overlay_->SetModifierKeyState( 186 overlay_->SetModifierKeyState(
212 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state()); 187 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state());
213 overlay_->SetModifierKeyState( 188 overlay_->SetModifierKeyState(
214 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state()); 189 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state());
215 overlay_->SetModifierKeyState( 190 overlay_->SetModifierKeyState(
216 ui::EF_ALT_DOWN, alt_sticky_key_->current_state()); 191 ui::EF_ALT_DOWN, alt_sticky_key_->current_state());
217 overlay_->SetModifierKeyState( 192 overlay_->SetModifierKeyState(
(...skipping 10 matching lines...) Expand all
228 203
229 overlay_->Show(enabled_ && key_in_use); 204 overlay_->Show(enabled_ && key_in_use);
230 } 205 }
231 206
232 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() { 207 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() {
233 return overlay_.get(); 208 return overlay_.get();
234 } 209 }
235 210
236 /////////////////////////////////////////////////////////////////////////////// 211 ///////////////////////////////////////////////////////////////////////////////
237 // StickyKeysHandler 212 // StickyKeysHandler
238 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag, 213 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag)
239 StickyKeysHandlerDelegate* delegate)
240 : modifier_flag_(modifier_flag), 214 : modifier_flag_(modifier_flag),
241 current_state_(STICKY_KEY_STATE_DISABLED), 215 current_state_(STICKY_KEY_STATE_DISABLED),
242 event_from_myself_(false),
243 preparing_to_enable_(false), 216 preparing_to_enable_(false),
244 scroll_delta_(0), 217 scroll_delta_(0) {
245 delegate_(delegate) {
246 } 218 }
247 219
248 StickyKeysHandler::~StickyKeysHandler() { 220 StickyKeysHandler::~StickyKeysHandler() {
249 } 221 }
250 222
251 StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { 223 bool StickyKeysHandler::HandleKeyEvent(const ui::KeyEvent& event,
252 } 224 ui::KeyboardCode key_code,
253 225 int* mod_down_flags,
254 StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { 226 int* mod_up_flags) {
255 }
256
257 bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) {
258 if (event_from_myself_)
259 return false; // Do not handle self-generated key event.
260 switch (current_state_) { 227 switch (current_state_) {
261 case STICKY_KEY_STATE_DISABLED: 228 case STICKY_KEY_STATE_DISABLED:
262 return HandleDisabledState(event); 229 return HandleDisabledState(event, key_code);
263 case STICKY_KEY_STATE_ENABLED: 230 case STICKY_KEY_STATE_ENABLED:
264 return HandleEnabledState(event); 231 return HandleEnabledState(event, key_code, mod_down_flags, mod_up_flags);
265 case STICKY_KEY_STATE_LOCKED: 232 case STICKY_KEY_STATE_LOCKED:
266 return HandleLockedState(event); 233 return HandleLockedState(event, key_code, mod_down_flags, mod_up_flags);
267 } 234 }
268 NOTREACHED(); 235 NOTREACHED();
269 return false; 236 return false;
270 } 237 }
271 238
272 bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { 239 bool StickyKeysHandler::HandleMouseEvent(
240 const ui::MouseEvent& event,
241 int* mod_down_flags,
242 int* mod_up_flags) {
273 if (ShouldModifyMouseEvent(event)) 243 if (ShouldModifyMouseEvent(event))
274 preparing_to_enable_ = false; 244 preparing_to_enable_ = false;
275 245
276 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED 246 if (current_state_ == STICKY_KEY_STATE_DISABLED ||
277 || !ShouldModifyMouseEvent(event)) { 247 !ShouldModifyMouseEvent(event)) {
278 return false; 248 return false;
279 } 249 }
280 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || 250 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED ||
281 current_state_ == STICKY_KEY_STATE_LOCKED); 251 current_state_ == STICKY_KEY_STATE_LOCKED);
282 252
283 AppendModifier(event); 253 *mod_down_flags |= modifier_flag_;
284 // Only disable on the mouse released event in normal, non-locked mode. 254 // Only disable on the mouse released event in normal, non-locked mode.
285 if (current_state_ == STICKY_KEY_STATE_ENABLED && 255 if (current_state_ == STICKY_KEY_STATE_ENABLED &&
286 event->type() != ui::ET_MOUSE_PRESSED) { 256 event.type() != ui::ET_MOUSE_PRESSED) {
287 current_state_ = STICKY_KEY_STATE_DISABLED; 257 current_state_ = STICKY_KEY_STATE_DISABLED;
288 DispatchEventAndReleaseModifier(event); 258 *mod_up_flags |= modifier_flag_;
289 return true; 259 return false;
290 } 260 }
291 261
292 return false; 262 return false;
293 } 263 }
294 264
295 bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { 265 bool StickyKeysHandler::HandleScrollEvent(
266 const ui::ScrollEvent& event,
267 int* mod_down_flags,
268 int* mod_up_flags) {
296 preparing_to_enable_ = false; 269 preparing_to_enable_ = false;
297 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED) 270 if (current_state_ == STICKY_KEY_STATE_DISABLED)
298 return false; 271 return false;
299 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || 272 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED ||
300 current_state_ == STICKY_KEY_STATE_LOCKED); 273 current_state_ == STICKY_KEY_STATE_LOCKED);
301 274
302 // We detect a direction change if the current |scroll_delta_| is assigned 275 // We detect a direction change if the current |scroll_delta_| is assigned
303 // and the offset of the current scroll event has the opposing sign. 276 // and the offset of the current scroll event has the opposing sign.
304 bool direction_changed = false; 277 bool direction_changed = false;
305 if (current_state_ == STICKY_KEY_STATE_ENABLED && 278 if (current_state_ == STICKY_KEY_STATE_ENABLED &&
306 event->type() == ui::ET_SCROLL) { 279 event.type() == ui::ET_SCROLL) {
307 int offset = event->y_offset(); 280 int offset = event.y_offset();
308 if (scroll_delta_) 281 if (scroll_delta_)
309 direction_changed = offset * scroll_delta_ <= 0; 282 direction_changed = offset * scroll_delta_ <= 0;
310 scroll_delta_ = offset; 283 scroll_delta_ = offset;
311 } 284 }
312 285
313 if (!direction_changed) 286 if (!direction_changed)
314 AppendModifier(event); 287 *mod_down_flags |= modifier_flag_;
315 288
316 // We want to modify all the scroll events in the scroll sequence, which ends 289 // We want to modify all the scroll events in the scroll sequence, which ends
317 // with a fling start event. We also stop when the scroll sequence changes 290 // with a fling start event. We also stop when the scroll sequence changes
318 // direction. 291 // direction.
319 if (current_state_ == STICKY_KEY_STATE_ENABLED && 292 if (current_state_ == STICKY_KEY_STATE_ENABLED &&
320 (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { 293 (event.type() == ui::ET_SCROLL_FLING_START || direction_changed)) {
321 current_state_ = STICKY_KEY_STATE_DISABLED; 294 current_state_ = STICKY_KEY_STATE_DISABLED;
322 scroll_delta_ = 0; 295 scroll_delta_ = 0;
323 DispatchEventAndReleaseModifier(event); 296 *mod_up_flags |= modifier_flag_;
324 return true; 297 return false;
325 } 298 }
326 299
327 return false; 300 return false;
328 } 301 }
329 302
330 StickyKeysHandler::KeyEventType 303 int StickyKeysHandler::GetModifierUpEvent(scoped_ptr<ui::Event>* new_event) {
331 StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { 304 if (current_state_ != STICKY_KEY_STATE_DISABLED || !modifier_up_event_)
305 return 0;
306 DCHECK(new_event);
307 if (*new_event)
308 return 1;
309 new_event->reset(modifier_up_event_.release());
310 return 0;
311 }
312
313 StickyKeysHandler::KeyEventType StickyKeysHandler::TranslateKeyEvent(
314 ui::EventType type,
315 ui::KeyboardCode key_code) {
332 bool is_target_key = false; 316 bool is_target_key = false;
333 if (event->key_code() == ui::VKEY_SHIFT || 317 if (key_code == ui::VKEY_SHIFT ||
334 event->key_code() == ui::VKEY_LSHIFT || 318 key_code == ui::VKEY_LSHIFT ||
335 event->key_code() == ui::VKEY_RSHIFT) { 319 key_code == ui::VKEY_RSHIFT) {
336 is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); 320 is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN);
337 } else if (event->key_code() == ui::VKEY_CONTROL || 321 } else if (key_code == ui::VKEY_CONTROL ||
338 event->key_code() == ui::VKEY_LCONTROL || 322 key_code == ui::VKEY_LCONTROL ||
339 event->key_code() == ui::VKEY_RCONTROL) { 323 key_code == ui::VKEY_RCONTROL) {
340 is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); 324 is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN);
341 } else if (event->key_code() == ui::VKEY_MENU || 325 } else if (key_code == ui::VKEY_MENU ||
342 event->key_code() == ui::VKEY_LMENU || 326 key_code == ui::VKEY_LMENU ||
343 event->key_code() == ui::VKEY_RMENU) { 327 key_code == ui::VKEY_RMENU) {
344 is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); 328 is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN);
345 } else if (event->key_code() == ui::VKEY_ALTGR) { 329 } else if (key_code == ui::VKEY_ALTGR) {
346 is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN); 330 is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN);
347 } else if (event->key_code() == ui::VKEY_OEM_8) { 331 } else if (key_code == ui::VKEY_OEM_8) {
348 is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN); 332 is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN);
349 } else { 333 } else {
350 return event->type() == ui::ET_KEY_PRESSED ? 334 return type == ui::ET_KEY_PRESSED ?
351 NORMAL_KEY_DOWN : NORMAL_KEY_UP; 335 NORMAL_KEY_DOWN : NORMAL_KEY_UP;
352 } 336 }
353 337
354 if (is_target_key) { 338 if (is_target_key) {
355 return event->type() == ui::ET_KEY_PRESSED ? 339 return type == ui::ET_KEY_PRESSED ?
356 TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; 340 TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP;
357 } 341 }
358 return event->type() == ui::ET_KEY_PRESSED ? 342 return type == ui::ET_KEY_PRESSED ?
359 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; 343 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP;
360 } 344 }
361 345
362 bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { 346 bool StickyKeysHandler::HandleDisabledState(const ui::KeyEvent& event,
363 switch (TranslateKeyEvent(event)) { 347 ui::KeyboardCode key_code) {
348 switch (TranslateKeyEvent(event.type(), key_code)) {
364 case TARGET_MODIFIER_UP: 349 case TARGET_MODIFIER_UP:
365 if (preparing_to_enable_) { 350 if (preparing_to_enable_) {
366 preparing_to_enable_ = false; 351 preparing_to_enable_ = false;
367 scroll_delta_ = 0; 352 scroll_delta_ = 0;
368 current_state_ = STICKY_KEY_STATE_ENABLED; 353 current_state_ = STICKY_KEY_STATE_ENABLED;
369 modifier_up_event_.reset(new ui::KeyEvent(*event)); 354 modifier_up_event_.reset(new ui::KeyEvent(event));
370 return true; 355 return true;
371 } 356 }
372 return false; 357 return false;
373 case TARGET_MODIFIER_DOWN: 358 case TARGET_MODIFIER_DOWN:
374 preparing_to_enable_ = true; 359 preparing_to_enable_ = true;
375 return false; 360 return false;
376 case NORMAL_KEY_DOWN: 361 case NORMAL_KEY_DOWN:
377 preparing_to_enable_ = false; 362 preparing_to_enable_ = false;
378 return false; 363 return false;
379 case NORMAL_KEY_UP: 364 case NORMAL_KEY_UP:
380 case OTHER_MODIFIER_DOWN: 365 case OTHER_MODIFIER_DOWN:
381 case OTHER_MODIFIER_UP: 366 case OTHER_MODIFIER_UP:
382 return false; 367 return false;
383 } 368 }
384 NOTREACHED(); 369 NOTREACHED();
385 return false; 370 return false;
386 } 371 }
387 372
388 bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { 373 bool StickyKeysHandler::HandleEnabledState(const ui::KeyEvent& event,
389 switch (TranslateKeyEvent(event)) { 374 ui::KeyboardCode key_code,
375 int* mod_down_flags,
376 int* mod_up_flags) {
377 switch (TranslateKeyEvent(event.type(), key_code)) {
390 case NORMAL_KEY_UP: 378 case NORMAL_KEY_UP:
391 case TARGET_MODIFIER_DOWN: 379 case TARGET_MODIFIER_DOWN:
392 return true; 380 return false;
393 case TARGET_MODIFIER_UP: 381 case TARGET_MODIFIER_UP:
394 current_state_ = STICKY_KEY_STATE_LOCKED; 382 current_state_ = STICKY_KEY_STATE_LOCKED;
395 modifier_up_event_.reset(); 383 modifier_up_event_.reset();
396 return true; 384 return true;
397 case NORMAL_KEY_DOWN: { 385 case NORMAL_KEY_DOWN: {
398 current_state_ = STICKY_KEY_STATE_DISABLED; 386 current_state_ = STICKY_KEY_STATE_DISABLED;
399 AppendModifier(event); 387 *mod_down_flags |= modifier_flag_;
400 DispatchEventAndReleaseModifier(event); 388 *mod_up_flags |= modifier_flag_;
401 return true; 389 return false;
402 } 390 }
403 case OTHER_MODIFIER_DOWN: 391 case OTHER_MODIFIER_DOWN:
404 case OTHER_MODIFIER_UP: 392 case OTHER_MODIFIER_UP:
405 return false; 393 return false;
406 } 394 }
407 NOTREACHED(); 395 NOTREACHED();
408 return false; 396 return false;
409 } 397 }
410 398
411 bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { 399 bool StickyKeysHandler::HandleLockedState(const ui::KeyEvent& event,
412 switch (TranslateKeyEvent(event)) { 400 ui::KeyboardCode key_code,
401 int* mod_down_flags,
402 int* mod_up_flags) {
403 switch (TranslateKeyEvent(event.type(), key_code)) {
413 case TARGET_MODIFIER_DOWN: 404 case TARGET_MODIFIER_DOWN:
414 return true; 405 return true;
415 case TARGET_MODIFIER_UP: 406 case TARGET_MODIFIER_UP:
416 current_state_ = STICKY_KEY_STATE_DISABLED; 407 current_state_ = STICKY_KEY_STATE_DISABLED;
417 return false; 408 return false;
418 case NORMAL_KEY_DOWN: 409 case NORMAL_KEY_DOWN:
419 case NORMAL_KEY_UP: 410 case NORMAL_KEY_UP:
420 AppendModifier(event); 411 *mod_down_flags |= modifier_flag_;
421 return false; 412 return false;
422 case OTHER_MODIFIER_DOWN: 413 case OTHER_MODIFIER_DOWN:
423 case OTHER_MODIFIER_UP: 414 case OTHER_MODIFIER_UP:
424 return false; 415 return false;
425 } 416 }
426 NOTREACHED(); 417 NOTREACHED();
427 return false; 418 return false;
428 } 419 }
429 420
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
551 } // namespace ash 421 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698