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

Side by Side Diff: ash/sticky_keys/sticky_keys_unittest.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: Convert sticky keys to a chromeos::EventRewriter phase. 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 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #undef None 8 #undef None
9 #undef Bool 9 #undef Bool
10 #undef RootWindow 10 #undef RootWindow
11 11
12 #include "ash/shell.h" 12 #include "ash/shell.h"
13 #include "ash/test/ash_test_base.h" 13 #include "ash/test/ash_test_base.h"
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/callback.h" 15 #include "base/callback.h"
16 #include "base/memory/scoped_vector.h" 16 #include "base/memory/scoped_vector.h"
17 #include "ui/aura/window.h" 17 #include "ui/aura/window.h"
18 #include "ui/aura/window_tree_host.h" 18 #include "ui/aura/window_tree_host.h"
19 #include "ui/events/event_handler.h" 19 #include "ui/events/event_source.h"
20 #include "ui/events/event_processor.h"
21 #include "ui/events/test/events_test_utils_x11.h" 20 #include "ui/events/test/events_test_utils_x11.h"
22 #include "ui/events/x/device_data_manager.h" 21 #include "ui/events/x/device_data_manager.h"
23 22
24 namespace ash { 23 namespace ash {
25 24
26 namespace { 25 namespace {
27 26
28 // The device id of the test touchpad device. 27 // The device id of the test touchpad device.
29 const unsigned int kTouchPadDeviceId = 1; 28 const unsigned int kTouchPadDeviceId = 1;
30 29
31 } // namespace 30 } // namespace
32 31
33 // Keeps a buffer of handled events. 32 class StickyKeysTest : public test::AshTestBase {
34 class EventBuffer : public ui::EventHandler {
35 public:
36 EventBuffer() {}
37 virtual ~EventBuffer() {}
38
39 void PopEvents(ScopedVector<ui::Event>* events) {
40 events->clear();
41 events->swap(events_);
42 }
43
44 private:
45 // ui::EventHandler overrides:
46 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
47 events_.push_back(new ui::KeyEvent(*event));
48 }
49
50 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
51 if (event->IsMouseWheelEvent()) {
52 events_.push_back(
53 new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event)));
54 } else {
55 events_.push_back(new ui::MouseEvent(*event));
56 }
57 }
58
59 ScopedVector<ui::Event> events_;
60
61 DISALLOW_COPY_AND_ASSIGN(EventBuffer);
62 };
63
64 // A testable and StickyKeysHandler.
65 class MockStickyKeysHandlerDelegate :
66 public StickyKeysHandler::StickyKeysHandlerDelegate {
67 public:
68 class Delegate {
69 public:
70 virtual aura::Window* GetExpectedTarget() = 0;
71 virtual void OnShortcutPressed() = 0;
72
73 protected:
74 virtual ~Delegate() {}
75 };
76
77 MockStickyKeysHandlerDelegate(Delegate* delegate) : delegate_(delegate) {}
78
79 virtual ~MockStickyKeysHandlerDelegate() {}
80
81 // StickyKeysHandler override.
82 virtual void DispatchKeyEvent(ui::KeyEvent* event,
83 aura::Window* target) OVERRIDE {
84 ASSERT_EQ(delegate_->GetExpectedTarget(), target);
85
86 // Detect a special shortcut when it is dispatched. This shortcut will
87 // not be hit in the LOCKED state as this case does not involve the
88 // delegate.
89 if (event->type() == ui::ET_KEY_PRESSED &&
90 event->key_code() == ui::VKEY_J &&
91 event->flags() | ui::EF_CONTROL_DOWN) {
92 delegate_->OnShortcutPressed();
93 }
94
95 events_.push_back(new ui::KeyEvent(*event));
96 }
97
98 virtual void DispatchMouseEvent(ui::MouseEvent* event,
99 aura::Window* target) OVERRIDE {
100 ASSERT_EQ(delegate_->GetExpectedTarget(), target);
101 events_.push_back(
102 new ui::MouseEvent(*event, target, target->GetRootWindow()));
103 }
104
105 virtual void DispatchScrollEvent(ui::ScrollEvent* event,
106 aura::Window* target) OVERRIDE {
107 events_.push_back(new ui::ScrollEvent(event->native_event()));
108 }
109
110 // Returns the count of dispatched events.
111 size_t GetEventCount() const {
112 return events_.size();
113 }
114
115 // Returns the |index|-th dispatched event.
116 const ui::Event* GetEvent(size_t index) const {
117 return events_[index];
118 }
119
120 // Clears all previously dispatched events.
121 void ClearEvents() {
122 events_.clear();
123 }
124
125 private:
126 ScopedVector<ui::Event> events_;
127 Delegate* delegate_;
128
129 DISALLOW_COPY_AND_ASSIGN(MockStickyKeysHandlerDelegate);
130 };
131
132 class StickyKeysTest : public test::AshTestBase,
133 public MockStickyKeysHandlerDelegate::Delegate {
134 protected: 33 protected:
135 StickyKeysTest() 34 StickyKeysTest()
136 : target_(NULL), 35 : target_(NULL),
137 root_window_(NULL) {} 36 root_window_(NULL) {}
138 37
139 virtual void SetUp() OVERRIDE { 38 virtual void SetUp() OVERRIDE {
140 test::AshTestBase::SetUp(); 39 test::AshTestBase::SetUp();
141 40
142 // |target_| owned by root window of shell. It is still safe to delete 41 // |target_| owned by root window of shell. It is still safe to delete
143 // it ourselves. 42 // it ourselves.
144 target_ = CreateTestWindowInShellWithId(0); 43 target_ = CreateTestWindowInShellWithId(0);
145 root_window_ = target_->GetRootWindow(); 44 root_window_ = target_->GetRootWindow();
146 45
147 ui::SetUpTouchPadForTest(kTouchPadDeviceId); 46 ui::SetUpTouchPadForTest(kTouchPadDeviceId);
148 } 47 }
149 48
150 virtual void TearDown() OVERRIDE { 49 virtual void TearDown() OVERRIDE {
151 test::AshTestBase::TearDown(); 50 test::AshTestBase::TearDown();
152 } 51 }
153 52
154 // Overridden from MockStickyKeysHandlerDelegate::Delegate:
155 virtual aura::Window* GetExpectedTarget() OVERRIDE {
156 return target_ ? target_ : root_window_;
157 }
158
159 virtual void OnShortcutPressed() OVERRIDE { 53 virtual void OnShortcutPressed() OVERRIDE {
160 if (target_) { 54 if (target_) {
161 delete target_; 55 delete target_;
162 target_ = NULL; 56 target_ = NULL;
163 } 57 }
164 } 58 }
165 59
166 ui::KeyEvent* GenerateKey(bool is_key_press, ui::KeyboardCode code) { 60 ui::KeyEvent* GenerateKey(ui::EventType type, ui::KeyboardCode code) {
167 scoped_xevent_.InitKeyEvent( 61 scoped_xevent_.InitKeyEvent(type, code, 0);
168 is_key_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, 62 ui::KeyEvent* event = new ui::KeyEvent(scoped_xevent_, false);
169 code,
170 0);
171 ui::KeyEvent* event = new ui::KeyEvent(scoped_xevent_, false);
172 ui::Event::DispatcherApi dispatcher(event);
173 dispatcher.set_target(target_);
174 return event; 63 return event;
175 } 64 }
176 65
177 // Creates a mouse event backed by a native XInput2 generic button event. 66 // Creates a mouse event backed by a native XInput2 generic button event.
178 // This is the standard native event on Chromebooks. 67 // This is the standard native event on Chromebooks.
179 ui::MouseEvent* GenerateMouseEvent(bool is_button_press) { 68 ui::MouseEvent* GenerateMouseEvent(ui::EventType type) {
180 return GenerateMouseEventAt(is_button_press, gfx::Point()); 69 return GenerateMouseEventAt(type, gfx::Point());
181 } 70 }
182 71
183 // Creates a mouse event backed by a native XInput2 generic button event. 72 // Creates a mouse event backed by a native XInput2 generic button event.
184 // The |location| should be in physical pixels. 73 // The |location| should be in physical pixels.
185 ui::MouseEvent* GenerateMouseEventAt(bool is_button_press, 74 ui::MouseEvent* GenerateMouseEventAt(ui::EventType type,
186 const gfx::Point& location) { 75 const gfx::Point& location) {
187 scoped_xevent_.InitGenericButtonEvent( 76 scoped_xevent_.InitGenericButtonEvent(
188 kTouchPadDeviceId, 77 kTouchPadDeviceId,
189 is_button_press ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, 78 type,
190 location, 79 location,
191 0); 80 0);
192 ui::MouseEvent* event = new ui::MouseEvent(scoped_xevent_); 81 ui::MouseEvent* event = new ui::MouseEvent(scoped_xevent_);
193 ui::Event::DispatcherApi dispatcher(event);
194 dispatcher.set_target(target_);
195 return event; 82 return event;
196 } 83 }
197 84
198 ui::MouseWheelEvent* GenerateMouseWheelEvent(int wheel_delta) { 85 ui::MouseWheelEvent* GenerateMouseWheelEvent(int wheel_delta) {
199 EXPECT_NE(0, wheel_delta); 86 EXPECT_NE(0, wheel_delta);
200 scoped_xevent_.InitGenericMouseWheelEvent( 87 scoped_xevent_.InitGenericMouseWheelEvent(
201 kTouchPadDeviceId, wheel_delta, 0); 88 kTouchPadDeviceId, wheel_delta, 0);
202 ui::MouseWheelEvent* event = new ui::MouseWheelEvent(scoped_xevent_); 89 ui::MouseWheelEvent* event = new ui::MouseWheelEvent(scoped_xevent_);
203 ui::Event::DispatcherApi dispatcher(event); 90 ui::Event::DispatcherApi dispatcher(event);
204 dispatcher.set_target(target_); 91 dispatcher.set_target(target_);
(...skipping 22 matching lines...) Expand all
227 0, // x_velocity_ordinal 114 0, // x_velocity_ordinal
228 fling_delta, // y_velocity_ordinal 115 fling_delta, // y_velocity_ordinal
229 is_cancel); // is_cancel 116 is_cancel); // is_cancel
230 ui::ScrollEvent* event = new ui::ScrollEvent(scoped_xevent_); 117 ui::ScrollEvent* event = new ui::ScrollEvent(scoped_xevent_);
231 ui::Event::DispatcherApi dispatcher(event); 118 ui::Event::DispatcherApi dispatcher(event);
232 dispatcher.set_target(target_); 119 dispatcher.set_target(target_);
233 return event; 120 return event;
234 } 121 }
235 122
236 // Creates a synthesized KeyEvent that is not backed by a native event. 123 // Creates a synthesized KeyEvent that is not backed by a native event.
237 ui::KeyEvent* GenerateSynthesizedKeyEvent( 124 ui::KeyEvent* GenerateSynthesizedKeyEvent(ui::EventType type,
238 bool is_key_press, ui::KeyboardCode code) { 125 ui::KeyboardCode code) {
239 ui::KeyEvent* event = new ui::KeyEvent( 126 ui::KeyEvent* event = new ui::KeyEvent(type, code, 0, true);
Daniel Erat 2014/06/05 23:16:10 nit: just return this directly instead of assignin
kpschoedel 2014/06/06 17:53:23 Done.
240 is_key_press ? ui::ET_KEY_PRESSED : ui::ET_MOUSE_RELEASED,
241 code, 0, true);
242 ui::Event::DispatcherApi dispatcher(event);
243 dispatcher.set_target(target_);
244 return event; 127 return event;
245 } 128 }
246 129
247 // Creates a synthesized MouseEvent that is not backed by a native event. 130 // Creates a synthesized MouseEvent that is not backed by a native event.
248 ui::MouseEvent* GenerateSynthesizedMouseEventAt(ui::EventType event_type, 131 ui::MouseEvent* GenerateSynthesizedMouseEventAt(ui::EventType event_type,
249 const gfx::Point& location) { 132 const gfx::Point& location) {
250 ui::MouseEvent* event = new ui::MouseEvent(event_type, 133 ui::MouseEvent* event = new ui::MouseEvent(event_type,
251 location, 134 location,
252 location, 135 location,
253 ui::EF_LEFT_MOUSE_BUTTON, 136 ui::EF_LEFT_MOUSE_BUTTON,
254 ui::EF_LEFT_MOUSE_BUTTON); 137 ui::EF_LEFT_MOUSE_BUTTON);
255 ui::Event::DispatcherApi dispatcher(event); 138 ui::Event::DispatcherApi dispatcher(event);
256 dispatcher.set_target(target_); 139 dispatcher.set_target(target_);
257 return event; 140 return event;
258 } 141 }
259 142
260 // Creates a synthesized mouse press or release event. 143 // Creates a synthesized mouse press or release event.
261 ui::MouseEvent* GenerateSynthesizedMouseClickEvent( 144 ui::MouseEvent* GenerateSynthesizedMouseClickEvent(ui::EventType type,
Daniel Erat 2014/06/05 23:16:10 nit: move first argument to its own line, indented
kpschoedel 2014/06/06 17:53:23 Done.
262 bool is_button_press,
263 const gfx::Point& location) { 145 const gfx::Point& location) {
264 return GenerateSynthesizedMouseEventAt( 146 return GenerateSynthesizedMouseEventAt(type, location);
265 is_button_press ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED,
266 location);
267 } 147 }
268 148
269 // Creates a synthesized ET_MOUSE_MOVED event. 149 // Creates a synthesized ET_MOUSE_MOVED event.
270 ui::MouseEvent* GenerateSynthesizedMouseMoveEvent( 150 ui::MouseEvent* GenerateSynthesizedMouseMoveEvent(
271 const gfx::Point& location) { 151 const gfx::Point& location) {
272 return GenerateSynthesizedMouseEventAt(ui::ET_MOUSE_MOVED, location); 152 return GenerateSynthesizedMouseEventAt(ui::ET_MOUSE_MOVED, location);
273 } 153 }
274 154
275 // Creates a synthesized MouseWHeel event. 155 // Creates a synthesized MouseWHeel event.
276 ui::MouseWheelEvent* GenerateSynthesizedMouseWheelEvent(int wheel_delta) { 156 ui::MouseWheelEvent* GenerateSynthesizedMouseWheelEvent(int wheel_delta) {
277 scoped_ptr<ui::MouseEvent> mev( 157 scoped_ptr<ui::MouseEvent> mev(
278 GenerateSynthesizedMouseEventAt(ui::ET_MOUSEWHEEL, gfx::Point(0, 0))); 158 GenerateSynthesizedMouseEventAt(ui::ET_MOUSEWHEEL, gfx::Point(0, 0)));
279 ui::MouseWheelEvent* event = new ui::MouseWheelEvent(*mev, 0, wheel_delta); 159 ui::MouseWheelEvent* event = new ui::MouseWheelEvent(*mev, 0, wheel_delta);
280 ui::Event::DispatcherApi dispatcher(event); 160 ui::Event::DispatcherApi dispatcher(event);
281 dispatcher.set_target(target_); 161 dispatcher.set_target(target_);
282 return event; 162 return event;
283 } 163 }
284 164
285 void SendActivateStickyKeyPattern(StickyKeysHandler* handler, 165 void SendActivateStickyKeyPattern(StickyKeysHandler* handler,
286 ui::KeyboardCode key_code) { 166 ui::KeyboardCode key_code) {
167 int up_flags = 0, down_flags = 0;
287 scoped_ptr<ui::KeyEvent> ev; 168 scoped_ptr<ui::KeyEvent> ev;
288 ev.reset(GenerateKey(true, key_code)); 169 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, key_code));
289 handler->HandleKeyEvent(ev.get()); 170 handler->HandleKeyEvent(*ev.get(), key_code, &down_flags, &up_flags);
290 ev.reset(GenerateKey(false, key_code)); 171 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, key_code));
291 handler->HandleKeyEvent(ev.get()); 172 handler->HandleKeyEvent(*ev.get(), key_code, &down_flags, &up_flags);
292 } 173 }
293 174
294 void SendActivateStickyKeyPattern(ui::EventProcessor* dispatcher, 175 bool HandleKeyEvent(const ui::KeyEvent& key_event,
295 ui::KeyboardCode key_code) { 176 StickyKeysHandler* handler,
296 scoped_ptr<ui::KeyEvent> ev; 177 int* down,
297 ev.reset(GenerateKey(true, key_code)); 178 int* up) {
298 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get()); 179 bool r = handler->HandleKeyEvent(key_event, key_event.key_code(), down, up);
Daniel Erat 2014/06/05 23:16:10 return this directly
kpschoedel 2014/06/06 17:53:23 Done.
299 CHECK(!details.dispatcher_destroyed); 180 return r;
300 ev.reset(GenerateKey(false, key_code)); 181 }
301 details = dispatcher->OnEventFromSource(ev.get()); 182
302 CHECK(!details.dispatcher_destroyed); 183 int HandleKeyEventForDownFlags(const ui::KeyEvent& key_event,
184 StickyKeysHandler* handler) {
185 int up = 0, down = 0;
186 handler->HandleKeyEvent(key_event, key_event.key_code(), &down, &up);
187 return down;
188 }
189
190 int HandleKeyEventForUpFlags(const ui::KeyEvent& key_event,
191 StickyKeysHandler* handler) {
192 int up = 0, down = 0;
193 handler->HandleKeyEvent(key_event, key_event.key_code(), &down, &up);
194 return up;
303 } 195 }
304 196
305 aura::Window* target() { return target_; } 197 aura::Window* target() { return target_; }
306 198
307 private: 199 private:
308 // Owned by root window of shell, but we can still delete |target_| safely. 200 // Owned by root window of shell, but we can still delete |target_| safely.
309 aura::Window* target_; 201 aura::Window* target_;
310 // The root window of |target_|. Not owned. 202 // The root window of |target_|. Not owned.
311 aura::Window* root_window_; 203 aura::Window* root_window_;
312 204
313 // Used to construct the various X events. 205 // Used to construct the various X events.
314 ui::ScopedXI2Event scoped_xevent_; 206 ui::ScopedXI2Event scoped_xevent_;
315 207
316 DISALLOW_COPY_AND_ASSIGN(StickyKeysTest); 208 DISALLOW_COPY_AND_ASSIGN(StickyKeysTest);
317 }; 209 };
318 210
319 TEST_F(StickyKeysTest, BasicOneshotScenarioTest) { 211 TEST_F(StickyKeysTest, BasicOneshotScenarioTest) {
320 scoped_ptr<ui::KeyEvent> ev; 212 scoped_ptr<ui::KeyEvent> ev;
321 MockStickyKeysHandlerDelegate* mock_delegate = 213 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN);
322 new MockStickyKeysHandlerDelegate(this);
323 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
324 214
325 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 215 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
326 216
327 // By typing Shift key, internal state become ENABLED. 217 // By typing Shift key, internal state become ENABLED.
328 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 218 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
329 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 219 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
330 220
331 ev.reset(GenerateKey(true, ui::VKEY_A)); 221 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A));
332 sticky_key.HandleKeyEvent(ev.get()); 222 int mod_up_flags = 0, mod_down_flags = 0;
223 HandleKeyEvent(*ev.get(), &sticky_key, &mod_down_flags, &mod_up_flags);
224 // Next keyboard event is shift modified.
225 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
226 // Modifier release notification happens.
227 EXPECT_TRUE(mod_up_flags & ui::EF_SHIFT_DOWN);
333 228
334 // Next keyboard event is shift modified. 229 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A));
335 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 230 mod_up_flags = mod_down_flags = 0;
336 231 HandleKeyEvent(*ev.get(), &sticky_key, &mod_down_flags, &mod_up_flags);
337 ev.reset(GenerateKey(false, ui::VKEY_A));
338 sticky_key.HandleKeyEvent(ev.get());
339 232
340 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 233 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
341 // Making sure Shift up keyboard event is dispatched. 234 // Making sure Shift up keyboard event is avaialble.
Daniel Erat 2014/06/05 23:16:10 nit: available
kpschoedel 2014/06/06 17:53:23 Done.
342 ASSERT_EQ(2U, mock_delegate->GetEventCount()); 235 scoped_ptr<ui::Event> up_event;
343 EXPECT_EQ(ui::ET_KEY_PRESSED, mock_delegate->GetEvent(0)->type()); 236 ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event));
344 EXPECT_EQ(ui::VKEY_A, 237 EXPECT_TRUE(up_event.get());
345 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(0)) 238 EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type());
346 ->key_code());
347 EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type());
348 EXPECT_EQ(ui::VKEY_SHIFT, 239 EXPECT_EQ(ui::VKEY_SHIFT,
349 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) 240 static_cast<const ui::KeyEvent*>(up_event.get())->key_code());
350 ->key_code());
351 241
352 // Enabled state is one shot, so next key event should not be shift modified. 242 // Enabled state is one shot, so next key event should not be shift modified.
353 ev.reset(GenerateKey(true, ui::VKEY_A)); 243 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A));
354 sticky_key.HandleKeyEvent(ev.get()); 244 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
355 EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); 245 EXPECT_FALSE(mod_down_flags & ui::EF_SHIFT_DOWN);
356 246
357 ev.reset(GenerateKey(false, ui::VKEY_A)); 247 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A));
358 sticky_key.HandleKeyEvent(ev.get()); 248 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
359 EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); 249 EXPECT_FALSE(mod_down_flags & ui::EF_SHIFT_DOWN);
360 } 250 }
361 251
362 TEST_F(StickyKeysTest, BasicLockedScenarioTest) { 252 TEST_F(StickyKeysTest, BasicLockedScenarioTest) {
363 scoped_ptr<ui::KeyEvent> ev; 253 scoped_ptr<ui::KeyEvent> ev;
364 MockStickyKeysHandlerDelegate* mock_delegate = 254 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN);
365 new MockStickyKeysHandlerDelegate(this);
366 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
367 255
368 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 256 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
369 257
370 // By typing shift key, internal state become ENABLED. 258 // By typing shift key, internal state become ENABLED.
371 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 259 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
372 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 260 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
373 261
374 // By typing shift key again, internal state become LOCKED. 262 // By typing shift key again, internal state become LOCKED.
375 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 263 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
376 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 264 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
377 265
378 // All keyboard events including keyUp become shift modified. 266 // All keyboard events including keyUp become shift modified.
379 ev.reset(GenerateKey(true, ui::VKEY_A)); 267 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A));
380 sticky_key.HandleKeyEvent(ev.get()); 268 int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
381 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 269 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
382 270
383 ev.reset(GenerateKey(false, ui::VKEY_A)); 271 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A));
384 sticky_key.HandleKeyEvent(ev.get()); 272 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
385 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 273 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
386 274
387 // Locked state keeps after normal keyboard event. 275 // Locked state keeps after normal keyboard event.
388 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 276 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
389 277
390 ev.reset(GenerateKey(true, ui::VKEY_B)); 278 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_B));
391 sticky_key.HandleKeyEvent(ev.get()); 279 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
392 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 280 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
393 281
394 ev.reset(GenerateKey(false, ui::VKEY_B)); 282 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_B));
395 sticky_key.HandleKeyEvent(ev.get()); 283 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
396 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 284 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
397 285
398 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 286 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
399 287
400 // By typing shift key again, internal state become back to DISABLED. 288 // By typing shift key again, internal state become back to DISABLED.
401 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 289 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
402 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 290 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
403 } 291 }
404 292
405 TEST_F(StickyKeysTest, NonTargetModifierTest) { 293 TEST_F(StickyKeysTest, NonTargetModifierTest) {
406 scoped_ptr<ui::KeyEvent> ev; 294 scoped_ptr<ui::KeyEvent> ev;
407 MockStickyKeysHandlerDelegate* mock_delegate = 295 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN);
408 new MockStickyKeysHandlerDelegate(this);
409 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
410 296
411 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 297 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
412 298
413 // Non target modifier key does not affect internal state 299 // Non target modifier key does not affect internal state
414 ev.reset(GenerateKey(true, ui::VKEY_MENU)); 300 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU));
415 sticky_key.HandleKeyEvent(ev.get()); 301 int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
416 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 302 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
303 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
417 304
418 ev.reset(GenerateKey(false, ui::VKEY_MENU)); 305 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU));
419 sticky_key.HandleKeyEvent(ev.get()); 306 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
420 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 307 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
308 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
421 309
422 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 310 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
423 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 311 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
424 312
425 // Non target modifier key does not affect internal state 313 // Non target modifier key does not affect internal state
426 ev.reset(GenerateKey(true, ui::VKEY_MENU)); 314 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU));
427 sticky_key.HandleKeyEvent(ev.get()); 315 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
428 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 316 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
317 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
429 318
430 ev.reset(GenerateKey(false, ui::VKEY_MENU)); 319 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU));
431 sticky_key.HandleKeyEvent(ev.get()); 320 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
432 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 321 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
322 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
433 323
434 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 324 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
435 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 325 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
436 326
437 // Non target modifier key does not affect internal state 327 // Non target modifier key does not affect internal state
438 ev.reset(GenerateKey(true, ui::VKEY_MENU)); 328 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU));
439 sticky_key.HandleKeyEvent(ev.get()); 329 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
440 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 330 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
331 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
441 332
442 ev.reset(GenerateKey(false, ui::VKEY_MENU)); 333 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU));
443 sticky_key.HandleKeyEvent(ev.get()); 334 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
444 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 335 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
336 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
445 } 337 }
446 338
447 TEST_F(StickyKeysTest, NormalShortcutTest) { 339 TEST_F(StickyKeysTest, NormalShortcutTest) {
448 // Sticky keys should not be enabled if we perform a normal shortcut. 340 // Sticky keys should not be enabled if we perform a normal shortcut.
449 scoped_ptr<ui::KeyEvent> ev; 341 scoped_ptr<ui::KeyEvent> ev;
450 MockStickyKeysHandlerDelegate* mock_delegate = 342 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
451 new MockStickyKeysHandlerDelegate(this);
452 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
453 343
454 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 344 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
455 345
456 // Perform ctrl+n shortcut. 346 // Perform ctrl+n shortcut.
457 ev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 347 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
458 sticky_key.HandleKeyEvent(ev.get()); 348 int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
459 ev.reset(GenerateKey(true, ui::VKEY_N)); 349 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N));
460 sticky_key.HandleKeyEvent(ev.get()); 350 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
461 ev.reset(GenerateKey(false, ui::VKEY_N)); 351 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_N));
462 sticky_key.HandleKeyEvent(ev.get()); 352 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
463 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 353 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
354 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
355 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
464 356
465 // Sticky keys should not be enabled afterwards. 357 // Sticky keys should not be enabled afterwards.
466 ev.reset(GenerateKey(false, ui::VKEY_CONTROL));
467 sticky_key.HandleKeyEvent(ev.get());
468 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 358 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
359 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
360
361 // Perform ctrl+n shortcut, releasing ctrl first.
362 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
363 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
364 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N));
365 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
366 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
367 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
368 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
369 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_N));
370 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
371
372 // Sticky keys should not be enabled afterwards.
373 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
374 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
469 } 375 }
470 376
471 TEST_F(StickyKeysTest, NormalModifiedClickTest) { 377 TEST_F(StickyKeysTest, NormalModifiedClickTest) {
472 scoped_ptr<ui::KeyEvent> kev; 378 scoped_ptr<ui::KeyEvent> kev;
473 scoped_ptr<ui::MouseEvent> mev; 379 scoped_ptr<ui::MouseEvent> mev;
474 MockStickyKeysHandlerDelegate* mock_delegate = 380 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
475 new MockStickyKeysHandlerDelegate(this);
476 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
477 381
478 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 382 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
479 383
480 // Perform ctrl+click. 384 // Perform ctrl+click.
481 kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 385 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
482 sticky_key.HandleKeyEvent(kev.get()); 386 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
483 mev.reset(GenerateMouseEvent(true)); 387 mev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
484 sticky_key.HandleMouseEvent(mev.get()); 388 int mod_up_flags = 0;
485 mev.reset(GenerateMouseEvent(false)); 389 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &mod_up_flags);
486 sticky_key.HandleMouseEvent(mev.get()); 390 mev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
391 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &mod_up_flags);
487 392
488 // Sticky keys should not be enabled afterwards. 393 // Sticky keys should not be enabled afterwards.
489 kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); 394 kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
490 sticky_key.HandleKeyEvent(kev.get()); 395 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
491 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 396 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
397 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
492 } 398 }
493 399
494 TEST_F(StickyKeysTest, MouseMovedModifierTest) { 400 TEST_F(StickyKeysTest, MouseMovedModifierTest) {
495 scoped_ptr<ui::KeyEvent> kev; 401 scoped_ptr<ui::KeyEvent> kev;
496 scoped_ptr<ui::MouseEvent> mev; 402 scoped_ptr<ui::MouseEvent> mev;
497 MockStickyKeysHandlerDelegate* mock_delegate = 403 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
498 new MockStickyKeysHandlerDelegate(this);
499 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
500 404
501 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 405 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
502 406
503 // Press ctrl and handle mouse move events. 407 // Press ctrl and handle mouse move events.
504 kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 408 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
505 sticky_key.HandleKeyEvent(kev.get()); 409 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
506 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(0, 0))); 410 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(0, 0)));
507 sticky_key.HandleMouseEvent(mev.get()); 411 int mod_up_flags = 0;
412 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &mod_up_flags);
508 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(100, 100))); 413 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(100, 100)));
509 sticky_key.HandleMouseEvent(mev.get()); 414 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &mod_up_flags);
510 415
511 // Sticky keys should be enabled afterwards. 416 // Sticky keys should be enabled afterwards.
512 kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); 417 kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
513 sticky_key.HandleKeyEvent(kev.get()); 418 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
514 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 419 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
420 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
515 } 421 }
516 422
517 TEST_F(StickyKeysTest, NormalModifiedScrollTest) { 423 TEST_F(StickyKeysTest, NormalModifiedScrollTest) {
518 scoped_ptr<ui::KeyEvent> kev; 424 scoped_ptr<ui::KeyEvent> kev;
519 scoped_ptr<ui::ScrollEvent> sev; 425 scoped_ptr<ui::ScrollEvent> sev;
520 MockStickyKeysHandlerDelegate* mock_delegate = 426 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
521 new MockStickyKeysHandlerDelegate(this);
522 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
523 427
524 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 428 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
525 429
526 // Perform ctrl+scroll. 430 // Perform ctrl+scroll.
527 kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 431 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
432 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
528 sev.reset(GenerateFlingScrollEvent(0, true)); 433 sev.reset(GenerateFlingScrollEvent(0, true));
529 sticky_key.HandleScrollEvent(sev.get()); 434 int mod_up_flags = 0;
435 sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &mod_up_flags);
530 sev.reset(GenerateScrollEvent(10)); 436 sev.reset(GenerateScrollEvent(10));
531 sticky_key.HandleScrollEvent(sev.get()); 437 sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &mod_up_flags);
532 sev.reset(GenerateFlingScrollEvent(10, false)); 438 sev.reset(GenerateFlingScrollEvent(10, false));
533 sticky_key.HandleScrollEvent(sev.get()); 439 sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &mod_up_flags);
534 440
535 // Sticky keys should not be enabled afterwards. 441 // Sticky keys should not be enabled afterwards.
536 kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); 442 kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
537 sticky_key.HandleKeyEvent(kev.get()); 443 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
538 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 444 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
445 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
539 } 446 }
540 447
541 TEST_F(StickyKeysTest, MouseEventOneshot) { 448 TEST_F(StickyKeysTest, MouseEventOneshot) {
542 scoped_ptr<ui::MouseEvent> ev; 449 scoped_ptr<ui::MouseEvent> ev;
543 scoped_ptr<ui::KeyEvent> kev; 450 scoped_ptr<ui::KeyEvent> kev;
544 MockStickyKeysHandlerDelegate* mock_delegate = 451 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
545 new MockStickyKeysHandlerDelegate(this);
546 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
547 452
548 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 453 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
549 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 454 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
550 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 455 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
551 456
552 // We should still be in the ENABLED state until we get the mouse 457 // We should still be in the ENABLED state until we get the mouse
553 // release event. 458 // release event.
554 ev.reset(GenerateMouseEvent(true)); 459 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
555 sticky_key.HandleMouseEvent(ev.get()); 460 int mod_down_flags = 0, mod_up_flags = 0;
556 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 461 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
462 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
557 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 463 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
558 464
559 ev.reset(GenerateMouseEvent(false)); 465 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
560 sticky_key.HandleMouseEvent(ev.get()); 466 mod_down_flags = mod_up_flags = 0;
561 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 467 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
468 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
562 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 469 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
563 470
564 // Making sure modifier key release event is dispatched in the right order. 471 // Making sure modifier key release event is dispatched in the right order.
565 ASSERT_EQ(2u, mock_delegate->GetEventCount()); 472 EXPECT_TRUE(mod_up_flags & ui::EF_CONTROL_DOWN);
566 EXPECT_EQ(ui::ET_MOUSE_RELEASED, mock_delegate->GetEvent(0)->type()); 473 scoped_ptr<ui::Event> up_event;
567 EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); 474 ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event));
475 EXPECT_TRUE(up_event.get());
476 EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type());
568 EXPECT_EQ(ui::VKEY_CONTROL, 477 EXPECT_EQ(ui::VKEY_CONTROL,
569 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) 478 static_cast<const ui::KeyEvent*>(up_event.get())->key_code());
570 ->key_code());
571 479
572 // Enabled state is one shot, so next click should not be control modified. 480 // Enabled state is one shot, so next click should not be control modified.
573 ev.reset(GenerateMouseEvent(true)); 481 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
574 sticky_key.HandleMouseEvent(ev.get()); 482 mod_down_flags = mod_up_flags = 0;
575 EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); 483 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
484 EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN);
576 485
577 ev.reset(GenerateMouseEvent(false)); 486 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
578 sticky_key.HandleMouseEvent(ev.get()); 487 mod_down_flags = mod_up_flags = 0;
579 EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); 488 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
489 EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN);
580 } 490 }
581 491
582 TEST_F(StickyKeysTest, MouseEventLocked) { 492 TEST_F(StickyKeysTest, MouseEventLocked) {
583 scoped_ptr<ui::MouseEvent> ev; 493 scoped_ptr<ui::MouseEvent> ev;
584 scoped_ptr<ui::KeyEvent> kev; 494 scoped_ptr<ui::KeyEvent> kev;
585 MockStickyKeysHandlerDelegate* mock_delegate = 495 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
586 new MockStickyKeysHandlerDelegate(this);
587 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
588 496
589 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 497 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
590 498
591 // Pressing modifier key twice should make us enter lock state. 499 // Pressing modifier key twice should make us enter lock state.
592 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 500 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
593 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 501 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
594 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 502 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
595 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 503 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
596 504
597 // Mouse events should not disable locked mode. 505 // Mouse events should not disable locked mode.
598 for (int i = 0; i < 3; ++i) { 506 for (int i = 0; i < 3; ++i) {
599 ev.reset(GenerateMouseEvent(true)); 507 int mod_up_flags = 0, mod_down_flags = 0;
600 sticky_key.HandleMouseEvent(ev.get()); 508 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
601 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 509 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
602 ev.reset(GenerateMouseEvent(false)); 510 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
603 sticky_key.HandleMouseEvent(ev.get()); 511 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
604 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 512 mod_up_flags = mod_down_flags = 0;
513 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
514 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
605 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 515 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
606 } 516 }
607 517
608 // Test with mouse wheel. 518 // Test with mouse wheel.
609 for (int i = 0; i < 3; ++i) { 519 for (int i = 0; i < 3; ++i) {
520 int mod_up_flags = 0, mod_down_flags = 0;
610 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); 521 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta));
611 sticky_key.HandleMouseEvent(ev.get()); 522 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
612 ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta)); 523 ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta));
613 sticky_key.HandleMouseEvent(ev.get()); 524 mod_up_flags = mod_down_flags = 0;
614 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 525 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
526 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
615 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 527 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
616 } 528 }
617 529
618 // Test mixed case with mouse events and key events. 530 // Test mixed case with mouse events and key events.
619 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); 531 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta));
620 sticky_key.HandleMouseEvent(ev.get()); 532 int mod_up_flags = 0, mod_down_flags = 0;
621 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 533 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
622 kev.reset(GenerateKey(true, ui::VKEY_N)); 534 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
623 sticky_key.HandleKeyEvent(kev.get()); 535 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N));
624 EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); 536 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
625 kev.reset(GenerateKey(false, ui::VKEY_N)); 537 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
626 sticky_key.HandleKeyEvent(kev.get()); 538 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
627 EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); 539 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
628 540
629 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 541 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
630 } 542 }
631 543
632 TEST_F(StickyKeysTest, ScrollEventOneshot) { 544 TEST_F(StickyKeysTest, ScrollEventOneshot) {
633 scoped_ptr<ui::ScrollEvent> ev; 545 scoped_ptr<ui::ScrollEvent> ev;
634 scoped_ptr<ui::KeyEvent> kev; 546 scoped_ptr<ui::KeyEvent> kev;
635 MockStickyKeysHandlerDelegate* mock_delegate = 547 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
636 new MockStickyKeysHandlerDelegate(this);
637 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
638 548
639 int scroll_deltas[] = {-10, 10}; 549 int scroll_deltas[] = {-10, 10};
640 for (int i = 0; i < 2; ++i) { 550 for (int i = 0; i < 2; ++i) {
641 mock_delegate->ClearEvents();
642
643 // Enable sticky keys. 551 // Enable sticky keys.
644 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 552 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
645 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 553 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
646 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 554 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
647 555
648 // Test a scroll sequence. Sticky keys should only be disabled at the end 556 // Test a scroll sequence. Sticky keys should only be disabled at the end
649 // of the scroll sequence. Fling cancel event starts the scroll sequence. 557 // of the scroll sequence. Fling cancel event starts the scroll sequence.
650 ev.reset(GenerateFlingScrollEvent(0, true)); 558 ev.reset(GenerateFlingScrollEvent(0, true));
651 sticky_key.HandleScrollEvent(ev.get()); 559 int mod_up_flags = 0, mod_down_flags = 0;
652 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 560 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
561 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
653 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 562 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
654 563
655 // Scrolls should all be modified but not disable sticky keys. 564 // Scrolls should all be modified but not disable sticky keys.
656 for (int j = 0; j < 3; ++j) { 565 for (int j = 0; j < 3; ++j) {
657 ev.reset(GenerateScrollEvent(scroll_deltas[i])); 566 ev.reset(GenerateScrollEvent(scroll_deltas[i]));
658 sticky_key.HandleScrollEvent(ev.get()); 567 mod_up_flags = mod_down_flags = 0;
659 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 568 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
569 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
660 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 570 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
661 } 571 }
662 572
663 // Fling start event ends scroll sequence. 573 // Fling start event ends scroll sequence.
664 ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false)); 574 ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false));
665 sticky_key.HandleScrollEvent(ev.get()); 575 mod_up_flags = mod_down_flags = 0;
666 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 576 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
577 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
667 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 578 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
668 579
669 ASSERT_EQ(2U, mock_delegate->GetEventCount()); 580 scoped_ptr<ui::Event> up_event;
670 EXPECT_EQ(ui::ET_SCROLL_FLING_START, mock_delegate->GetEvent(0)->type()); 581 EXPECT_TRUE(mod_up_flags & ui::EF_CONTROL_DOWN);
671 EXPECT_FLOAT_EQ(scroll_deltas[i], 582 ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event));
672 static_cast<const ui::ScrollEvent*>( 583 EXPECT_TRUE(up_event.get());
673 mock_delegate->GetEvent(0))->y_offset()); 584 EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type());
674 EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type());
675 EXPECT_EQ(ui::VKEY_CONTROL, 585 EXPECT_EQ(ui::VKEY_CONTROL,
676 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) 586 static_cast<const ui::KeyEvent*>(up_event.get())->key_code());
677 ->key_code());
678 } 587 }
679 } 588 }
680 589
681 TEST_F(StickyKeysTest, ScrollDirectionChanged) { 590 TEST_F(StickyKeysTest, ScrollDirectionChanged) {
682 scoped_ptr<ui::ScrollEvent> ev; 591 scoped_ptr<ui::ScrollEvent> ev;
683 scoped_ptr<ui::KeyEvent> kev; 592 scoped_ptr<ui::KeyEvent> kev;
684 MockStickyKeysHandlerDelegate* mock_delegate = 593 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
685 new MockStickyKeysHandlerDelegate(this);
686 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
687 594
688 // Test direction change with both boundary value and negative value. 595 // Test direction change with both boundary value and negative value.
689 const int direction_change_values[2] = {0, -10}; 596 const int direction_change_values[2] = {0, -10};
690 for (int i = 0; i < 2; ++i) { 597 for (int i = 0; i < 2; ++i) {
691 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 598 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
692 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 599 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
693 600
694 // Fling cancel starts scroll sequence. 601 // Fling cancel starts scroll sequence.
695 ev.reset(GenerateFlingScrollEvent(0, true)); 602 ev.reset(GenerateFlingScrollEvent(0, true));
696 sticky_key.HandleScrollEvent(ev.get()); 603 int mod_up_flags = 0, mod_down_flags = 0;
604 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
697 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 605 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
698 606
699 // Test that changing directions in a scroll sequence will 607 // Test that changing directions in a scroll sequence will
700 // return sticky keys to DISABLED state. 608 // return sticky keys to DISABLED state.
701 for (int j = 0; j < 3; ++j) { 609 for (int j = 0; j < 3; ++j) {
702 ev.reset(GenerateScrollEvent(10)); 610 ev.reset(GenerateScrollEvent(10));
703 sticky_key.HandleScrollEvent(ev.get()); 611 mod_up_flags = mod_down_flags = 0;
704 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 612 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
613 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
705 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 614 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
706 } 615 }
707 616
708 ev.reset(GenerateScrollEvent(direction_change_values[i])); 617 ev.reset(GenerateScrollEvent(direction_change_values[i]));
709 sticky_key.HandleScrollEvent(ev.get()); 618 mod_up_flags = mod_down_flags = 0;
710 EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); 619 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
711 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 620 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
712 } 621 }
713 } 622 }
714 623
715 TEST_F(StickyKeysTest, ScrollEventLocked) { 624 TEST_F(StickyKeysTest, ScrollEventLocked) {
716 scoped_ptr<ui::ScrollEvent> ev; 625 scoped_ptr<ui::ScrollEvent> ev;
717 scoped_ptr<ui::KeyEvent> kev; 626 scoped_ptr<ui::KeyEvent> kev;
718 MockStickyKeysHandlerDelegate* mock_delegate = 627 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
719 new MockStickyKeysHandlerDelegate(this);
720 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
721 628
722 // Lock sticky keys. 629 // Lock sticky keys.
723 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 630 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
724 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 631 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
725 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 632 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
726 633
727 // Test scroll events are correctly modified in locked state. 634 // Test scroll events are correctly modified in locked state.
728 for (int i = 0; i < 5; ++i) { 635 for (int i = 0; i < 5; ++i) {
729 // Fling cancel starts scroll sequence. 636 // Fling cancel starts scroll sequence.
730 ev.reset(GenerateFlingScrollEvent(0, true)); 637 ev.reset(GenerateFlingScrollEvent(0, true));
731 sticky_key.HandleScrollEvent(ev.get()); 638 int mod_up_flags = 0, mod_down_flags = 0;
639 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
732 640
733 ev.reset(GenerateScrollEvent(10)); 641 ev.reset(GenerateScrollEvent(10));
734 sticky_key.HandleScrollEvent(ev.get()); 642 mod_up_flags = mod_down_flags = 0;
735 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 643 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
644 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
736 ev.reset(GenerateScrollEvent(-10)); 645 ev.reset(GenerateScrollEvent(-10));
737 sticky_key.HandleScrollEvent(ev.get()); 646 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
738 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 647 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
739 648
740 // Fling start ends scroll sequence. 649 // Fling start ends scroll sequence.
741 ev.reset(GenerateFlingScrollEvent(-10, false)); 650 ev.reset(GenerateFlingScrollEvent(-10, false));
742 sticky_key.HandleScrollEvent(ev.get()); 651 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &mod_up_flags);
743 } 652 }
744 653
745 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 654 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
746 } 655 }
747 656
748 TEST_F(StickyKeysTest, EventTargetDestroyed) {
749 scoped_ptr<ui::KeyEvent> ev;
750 MockStickyKeysHandlerDelegate* mock_delegate =
751 new MockStickyKeysHandlerDelegate(this);
752 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
753
754 target()->Focus();
755
756 // Go into ENABLED state.
757 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
758 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
759 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
760
761 // CTRL+J is a special shortcut that will destroy the event target.
762 ev.reset(GenerateKey(true, ui::VKEY_J));
763 sticky_key.HandleKeyEvent(ev.get());
764 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
765 EXPECT_FALSE(target());
766 }
767
768 TEST_F(StickyKeysTest, SynthesizedEvents) { 657 TEST_F(StickyKeysTest, SynthesizedEvents) {
769 // Non-native, internally generated events should be properly handled 658 // Non-native, internally generated events should be properly handled
770 // by sticky keys. 659 // by sticky keys.
771 MockStickyKeysHandlerDelegate* mock_delegate = 660 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
772 new MockStickyKeysHandlerDelegate(this);
773 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
774 661
775 // Test non-native key events. 662 // Test non-native key events.
776 scoped_ptr<ui::KeyEvent> kev; 663 scoped_ptr<ui::KeyEvent> kev;
777 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 664 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
778 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 665 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
779 666
780 kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K)); 667 kev.reset(GenerateSynthesizedKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_K));
781 sticky_key.HandleKeyEvent(kev.get()); 668 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
782 EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); 669 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
783 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 670 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
784 671
785 kev.reset(GenerateSynthesizedKeyEvent(false, ui::VKEY_K)); 672 kev.reset(GenerateSynthesizedKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_K));
786 sticky_key.HandleKeyEvent(kev.get()); 673 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
787 EXPECT_FALSE(kev->flags() & ui::EF_CONTROL_DOWN); 674 EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN);
788 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 675 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
789 676
790 // Test non-native mouse events. 677 // Test non-native mouse events.
791 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 678 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
792 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 679 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
793 680
794 scoped_ptr<ui::MouseEvent> mev; 681 scoped_ptr<ui::MouseEvent> mev;
795 mev.reset(GenerateSynthesizedMouseClickEvent(true, gfx::Point(0, 0))); 682 mev.reset(GenerateSynthesizedMouseClickEvent(ui::ET_MOUSE_PRESSED,
796 sticky_key.HandleMouseEvent(mev.get()); 683 gfx::Point(0, 0)));
797 EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); 684 int mod_up_flags = 0;
685 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &mod_up_flags);
686 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
798 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 687 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
799 688
800 mev.reset(GenerateSynthesizedMouseClickEvent(false, gfx::Point(0, 0))); 689 mev.reset(GenerateSynthesizedMouseClickEvent(ui::ET_MOUSE_RELEASED,
801 sticky_key.HandleMouseEvent(mev.get()); 690 gfx::Point(0, 0)));
802 EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); 691 mod_up_flags = mod_down_flags = 0;
692 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &mod_up_flags);
693 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
694 EXPECT_TRUE(mod_up_flags & ui::EF_CONTROL_DOWN);
803 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 695 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
804 } 696 }
805 697
806 TEST_F(StickyKeysTest, KeyEventDispatchImpl) {
807 // Test the actual key event dispatch implementation.
808 EventBuffer buffer;
809 ScopedVector<ui::Event> events;
810 ui::EventProcessor* dispatcher =
811 Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
812 Shell::GetInstance()->AddPreTargetHandler(&buffer);
813 Shell::GetInstance()->sticky_keys_controller()->Enable(true);
814
815 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
816 scoped_ptr<ui::KeyEvent> ev;
817 buffer.PopEvents(&events);
818
819 // Test key press event is correctly modified and modifier release
820 // event is sent.
821 ev.reset(GenerateKey(true, ui::VKEY_C));
822 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get());
823 buffer.PopEvents(&events);
824 EXPECT_EQ(2u, events.size());
825 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
826 EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
827 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
828 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
829 EXPECT_EQ(ui::VKEY_CONTROL,
830 static_cast<ui::KeyEvent*>(events[1])->key_code());
831
832 // Test key release event is not modified.
833 ev.reset(GenerateKey(false, ui::VKEY_C));
834 details = dispatcher->OnEventFromSource(ev.get());
835 ASSERT_FALSE(details.dispatcher_destroyed);
836 buffer.PopEvents(&events);
837 EXPECT_EQ(1u, events.size());
838 EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type());
839 EXPECT_EQ(ui::VKEY_C,
840 static_cast<ui::KeyEvent*>(events[0])->key_code());
841 EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN);
842
843 // Test that synthesized key events are dispatched correctly.
844 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
845 buffer.PopEvents(&events);
846 scoped_ptr<ui::KeyEvent> kev;
847 kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K));
848 details = dispatcher->OnEventFromSource(kev.get());
849 ASSERT_FALSE(details.dispatcher_destroyed);
850 buffer.PopEvents(&events);
851 EXPECT_EQ(2u, events.size());
852 EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
853 EXPECT_EQ(ui::VKEY_K, static_cast<ui::KeyEvent*>(events[0])->key_code());
854 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
855 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
856 EXPECT_EQ(ui::VKEY_CONTROL,
857 static_cast<ui::KeyEvent*>(events[1])->key_code());
858
859 Shell::GetInstance()->RemovePreTargetHandler(&buffer);
860 }
861
862 class StickyKeysMouseDispatchTest
863 : public StickyKeysTest,
864 public ::testing::WithParamInterface<int> {
865 };
866
867 TEST_P(StickyKeysMouseDispatchTest, MouseEventDispatchImpl) {
868 int scale_factor = GetParam();
869 std::ostringstream display_specs;
870 display_specs << "1280x1024*" << scale_factor;
871 UpdateDisplay(display_specs.str());
872
873 EventBuffer buffer;
874 ScopedVector<ui::Event> events;
875 ui::EventProcessor* dispatcher =
876 Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
877 Shell::GetInstance()->AddPreTargetHandler(&buffer);
878 Shell::GetInstance()->sticky_keys_controller()->Enable(true);
879
880 scoped_ptr<ui::MouseEvent> ev;
881 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
882 buffer.PopEvents(&events);
883
884 // Test mouse press event is correctly modified and has correct DIP location.
885 gfx::Point physical_location(400, 400);
886 gfx::Point dip_location(physical_location.x() / scale_factor,
887 physical_location.y() / scale_factor);
888 ev.reset(GenerateMouseEventAt(true, physical_location));
889 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get());
890 buffer.PopEvents(&events);
891 EXPECT_EQ(1u, events.size());
892 EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type());
893 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
894 EXPECT_EQ(dip_location.ToString(),
895 static_cast<ui::MouseEvent*>(events[0])->location().ToString());
896
897 // Test mouse release event is correctly modified and modifier release
898 // event is sent. The mouse event should have the correct DIP location.
899 ev.reset(GenerateMouseEventAt(false, physical_location));
900 details = dispatcher->OnEventFromSource(ev.get());
901 ASSERT_FALSE(details.dispatcher_destroyed);
902 buffer.PopEvents(&events);
903 EXPECT_EQ(2u, events.size());
904 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type());
905 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
906 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
907 EXPECT_EQ(dip_location.ToString(),
908 static_cast<ui::MouseEvent*>(events[0])->location().ToString());
909 EXPECT_EQ(ui::VKEY_CONTROL,
910 static_cast<ui::KeyEvent*>(events[1])->key_code());
911
912 // Test synthesized mouse events are dispatched correctly.
913 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
914 buffer.PopEvents(&events);
915 ev.reset(GenerateSynthesizedMouseClickEvent(false, physical_location));
916 details = dispatcher->OnEventFromSource(ev.get());
917 ASSERT_FALSE(details.dispatcher_destroyed);
918 buffer.PopEvents(&events);
919 EXPECT_EQ(2u, events.size());
920 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type());
921 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
922 EXPECT_EQ(dip_location.ToString(),
923 static_cast<ui::MouseEvent*>(events[0])->location().ToString());
924 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
925 EXPECT_EQ(ui::VKEY_CONTROL,
926 static_cast<ui::KeyEvent*>(events[1])->key_code());
927
928 Shell::GetInstance()->RemovePreTargetHandler(&buffer);
929 }
930
931 TEST_P(StickyKeysMouseDispatchTest, MouseWheelEventDispatchImpl) {
932 int scale_factor = GetParam();
933 std::ostringstream display_specs;
934 display_specs << "1280x1024*" << scale_factor;
935 UpdateDisplay(display_specs.str());
936
937 // Test the actual mouse wheel event dispatch implementation.
938 EventBuffer buffer;
939 ScopedVector<ui::Event> events;
940 ui::EventProcessor* dispatcher =
941 Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
942 Shell::GetInstance()->AddPreTargetHandler(&buffer);
943 Shell::GetInstance()->sticky_keys_controller()->Enable(true);
944
945 scoped_ptr<ui::MouseWheelEvent> ev;
946 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
947 buffer.PopEvents(&events);
948
949 // Test positive mouse wheel event is correctly modified and modifier release
950 // event is sent.
951 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta));
952 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get());
953 ASSERT_FALSE(details.dispatcher_destroyed);
954 buffer.PopEvents(&events);
955 EXPECT_EQ(2u, events.size());
956 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
957 EXPECT_EQ(ui::MouseWheelEvent::kWheelDelta / scale_factor,
958 static_cast<ui::MouseWheelEvent*>(events[0])->y_offset());
959 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
960 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
961 EXPECT_EQ(ui::VKEY_CONTROL,
962 static_cast<ui::KeyEvent*>(events[1])->key_code());
963
964 // Test negative mouse wheel event is correctly modified and modifier release
965 // event is sent.
966 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
967 buffer.PopEvents(&events);
968
969 ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta));
970 details = dispatcher->OnEventFromSource(ev.get());
971 ASSERT_FALSE(details.dispatcher_destroyed);
972 buffer.PopEvents(&events);
973 EXPECT_EQ(2u, events.size());
974 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
975 EXPECT_EQ(-ui::MouseWheelEvent::kWheelDelta / scale_factor,
976 static_cast<ui::MouseWheelEvent*>(events[0])->y_offset());
977 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
978 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
979 EXPECT_EQ(ui::VKEY_CONTROL,
980 static_cast<ui::KeyEvent*>(events[1])->key_code());
981
982 // Test synthesized mouse wheel events are dispatched correctly.
983 SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL);
984 buffer.PopEvents(&events);
985 ev.reset(
986 GenerateSynthesizedMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta));
987 details = dispatcher->OnEventFromSource(ev.get());
988 ASSERT_FALSE(details.dispatcher_destroyed);
989 buffer.PopEvents(&events);
990 EXPECT_EQ(2u, events.size());
991 EXPECT_TRUE(events[0]->IsMouseWheelEvent());
992 EXPECT_EQ(ui::MouseWheelEvent::kWheelDelta / scale_factor,
993 static_cast<ui::MouseWheelEvent*>(events[0])->y_offset());
994 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
995 EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
996 EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
997 EXPECT_EQ(ui::VKEY_CONTROL,
998 static_cast<ui::KeyEvent*>(events[1])->key_code());
999
1000 Shell::GetInstance()->RemovePreTargetHandler(&buffer);
1001 }
1002
1003 INSTANTIATE_TEST_CASE_P(DPIScaleFactors,
1004 StickyKeysMouseDispatchTest,
1005 ::testing::Values(1, 2));
1006
1007 } // namespace ash 698 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698