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

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: distinguish between MouseEvent and MouseWheelEvent 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: 53 virtual void OnShortcutPressed() {
155 virtual aura::Window* GetExpectedTarget() OVERRIDE {
156 return target_ ? target_ : root_window_;
157 }
158
159 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 return new ui::KeyEvent(type, code, 0, true);
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;
245 } 127 }
246 128
247 // Creates a synthesized MouseEvent that is not backed by a native event. 129 // Creates a synthesized MouseEvent that is not backed by a native event.
248 ui::MouseEvent* GenerateSynthesizedMouseEventAt(ui::EventType event_type, 130 ui::MouseEvent* GenerateSynthesizedMouseEventAt(ui::EventType event_type,
249 const gfx::Point& location) { 131 const gfx::Point& location) {
250 ui::MouseEvent* event = new ui::MouseEvent(event_type, 132 ui::MouseEvent* event = new ui::MouseEvent(event_type,
251 location, 133 location,
252 location, 134 location,
253 ui::EF_LEFT_MOUSE_BUTTON, 135 ui::EF_LEFT_MOUSE_BUTTON,
254 ui::EF_LEFT_MOUSE_BUTTON); 136 ui::EF_LEFT_MOUSE_BUTTON);
255 ui::Event::DispatcherApi dispatcher(event); 137 ui::Event::DispatcherApi dispatcher(event);
256 dispatcher.set_target(target_); 138 dispatcher.set_target(target_);
257 return event; 139 return event;
258 } 140 }
259 141
260 // Creates a synthesized mouse press or release event. 142 // Creates a synthesized mouse press or release event.
261 ui::MouseEvent* GenerateSynthesizedMouseClickEvent( 143 ui::MouseEvent* GenerateSynthesizedMouseClickEvent(
262 bool is_button_press, 144 ui::EventType type,
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 bool released = false;
168 int down_flags = 0;
287 scoped_ptr<ui::KeyEvent> ev; 169 scoped_ptr<ui::KeyEvent> ev;
288 ev.reset(GenerateKey(true, key_code)); 170 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, key_code));
289 handler->HandleKeyEvent(ev.get()); 171 handler->HandleKeyEvent(*ev.get(), key_code, &down_flags, &released);
290 ev.reset(GenerateKey(false, key_code)); 172 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, key_code));
291 handler->HandleKeyEvent(ev.get()); 173 handler->HandleKeyEvent(*ev.get(), key_code, &down_flags, &released);
292 } 174 }
293 175
294 void SendActivateStickyKeyPattern(ui::EventProcessor* dispatcher, 176 bool HandleKeyEvent(const ui::KeyEvent& key_event,
295 ui::KeyboardCode key_code) { 177 StickyKeysHandler* handler,
296 scoped_ptr<ui::KeyEvent> ev; 178 int* down,
297 ev.reset(GenerateKey(true, key_code)); 179 bool* up) {
298 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get()); 180 return handler->HandleKeyEvent(key_event, key_event.key_code(), down, up);
299 CHECK(!details.dispatcher_destroyed); 181 }
300 ev.reset(GenerateKey(false, key_code)); 182
301 details = dispatcher->OnEventFromSource(ev.get()); 183 int HandleKeyEventForDownFlags(const ui::KeyEvent& key_event,
302 CHECK(!details.dispatcher_destroyed); 184 StickyKeysHandler* handler) {
185 bool released = false;
186 int down = 0;
187 handler->HandleKeyEvent(key_event, key_event.key_code(), &down, &released);
188 return down;
303 } 189 }
304 190
305 aura::Window* target() { return target_; } 191 aura::Window* target() { return target_; }
306 192
307 private: 193 private:
308 // Owned by root window of shell, but we can still delete |target_| safely. 194 // Owned by root window of shell, but we can still delete |target_| safely.
309 aura::Window* target_; 195 aura::Window* target_;
310 // The root window of |target_|. Not owned. 196 // The root window of |target_|. Not owned.
311 aura::Window* root_window_; 197 aura::Window* root_window_;
312 198
313 // Used to construct the various X events. 199 // Used to construct the various X events.
314 ui::ScopedXI2Event scoped_xevent_; 200 ui::ScopedXI2Event scoped_xevent_;
315 201
316 DISALLOW_COPY_AND_ASSIGN(StickyKeysTest); 202 DISALLOW_COPY_AND_ASSIGN(StickyKeysTest);
317 }; 203 };
318 204
319 TEST_F(StickyKeysTest, BasicOneshotScenarioTest) { 205 TEST_F(StickyKeysTest, BasicOneshotScenarioTest) {
320 scoped_ptr<ui::KeyEvent> ev; 206 scoped_ptr<ui::KeyEvent> ev;
321 MockStickyKeysHandlerDelegate* mock_delegate = 207 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN);
322 new MockStickyKeysHandlerDelegate(this);
323 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
324 208
325 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 209 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
326 210
327 // By typing Shift key, internal state become ENABLED. 211 // By typing Shift key, internal state become ENABLED.
328 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 212 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
329 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 213 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
330 214
331 ev.reset(GenerateKey(true, ui::VKEY_A)); 215 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A));
332 sticky_key.HandleKeyEvent(ev.get()); 216 bool released = false;
217 int mod_down_flags = 0;
218 HandleKeyEvent(*ev.get(), &sticky_key, &mod_down_flags, &released);
219 // Next keyboard event is shift modified.
220 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
221 // Modifier release notification happens.
222 EXPECT_TRUE(released);
333 223
334 // Next keyboard event is shift modified. 224 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A));
335 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 225 released = false;
336 226 mod_down_flags = 0;
337 ev.reset(GenerateKey(false, ui::VKEY_A)); 227 HandleKeyEvent(*ev.get(), &sticky_key, &mod_down_flags, &released);
338 sticky_key.HandleKeyEvent(ev.get());
339 228
340 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 229 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
341 // Making sure Shift up keyboard event is dispatched. 230 // Making sure Shift up keyboard event is available.
342 ASSERT_EQ(2U, mock_delegate->GetEventCount()); 231 scoped_ptr<ui::Event> up_event;
343 EXPECT_EQ(ui::ET_KEY_PRESSED, mock_delegate->GetEvent(0)->type()); 232 ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event));
344 EXPECT_EQ(ui::VKEY_A, 233 EXPECT_TRUE(up_event.get());
345 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(0)) 234 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, 235 EXPECT_EQ(ui::VKEY_SHIFT,
349 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) 236 static_cast<const ui::KeyEvent*>(up_event.get())->key_code());
350 ->key_code());
351 237
352 // Enabled state is one shot, so next key event should not be shift modified. 238 // Enabled state is one shot, so next key event should not be shift modified.
353 ev.reset(GenerateKey(true, ui::VKEY_A)); 239 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A));
354 sticky_key.HandleKeyEvent(ev.get()); 240 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
355 EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); 241 EXPECT_FALSE(mod_down_flags & ui::EF_SHIFT_DOWN);
356 242
357 ev.reset(GenerateKey(false, ui::VKEY_A)); 243 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A));
358 sticky_key.HandleKeyEvent(ev.get()); 244 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
359 EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); 245 EXPECT_FALSE(mod_down_flags & ui::EF_SHIFT_DOWN);
360 } 246 }
361 247
362 TEST_F(StickyKeysTest, BasicLockedScenarioTest) { 248 TEST_F(StickyKeysTest, BasicLockedScenarioTest) {
363 scoped_ptr<ui::KeyEvent> ev; 249 scoped_ptr<ui::KeyEvent> ev;
364 MockStickyKeysHandlerDelegate* mock_delegate = 250 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN);
365 new MockStickyKeysHandlerDelegate(this);
366 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
367 251
368 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 252 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
369 253
370 // By typing shift key, internal state become ENABLED. 254 // By typing shift key, internal state become ENABLED.
371 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 255 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
372 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 256 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
373 257
374 // By typing shift key again, internal state become LOCKED. 258 // By typing shift key again, internal state become LOCKED.
375 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 259 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
376 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 260 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
377 261
378 // All keyboard events including keyUp become shift modified. 262 // All keyboard events including keyUp become shift modified.
379 ev.reset(GenerateKey(true, ui::VKEY_A)); 263 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A));
380 sticky_key.HandleKeyEvent(ev.get()); 264 int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
381 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 265 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
382 266
383 ev.reset(GenerateKey(false, ui::VKEY_A)); 267 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A));
384 sticky_key.HandleKeyEvent(ev.get()); 268 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
385 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 269 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
386 270
387 // Locked state keeps after normal keyboard event. 271 // Locked state keeps after normal keyboard event.
388 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 272 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
389 273
390 ev.reset(GenerateKey(true, ui::VKEY_B)); 274 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_B));
391 sticky_key.HandleKeyEvent(ev.get()); 275 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
392 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 276 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
393 277
394 ev.reset(GenerateKey(false, ui::VKEY_B)); 278 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_B));
395 sticky_key.HandleKeyEvent(ev.get()); 279 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
396 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); 280 EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN);
397 281
398 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 282 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
399 283
400 // By typing shift key again, internal state become back to DISABLED. 284 // By typing shift key again, internal state become back to DISABLED.
401 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 285 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
402 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 286 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
403 } 287 }
404 288
405 TEST_F(StickyKeysTest, NonTargetModifierTest) { 289 TEST_F(StickyKeysTest, NonTargetModifierTest) {
406 scoped_ptr<ui::KeyEvent> ev; 290 scoped_ptr<ui::KeyEvent> ev;
407 MockStickyKeysHandlerDelegate* mock_delegate = 291 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN);
408 new MockStickyKeysHandlerDelegate(this);
409 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
410 292
411 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 293 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
412 294
413 // Non target modifier key does not affect internal state 295 // Non target modifier key does not affect internal state
414 ev.reset(GenerateKey(true, ui::VKEY_MENU)); 296 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU));
415 sticky_key.HandleKeyEvent(ev.get()); 297 int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
416 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 298 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
299 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
417 300
418 ev.reset(GenerateKey(false, ui::VKEY_MENU)); 301 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU));
419 sticky_key.HandleKeyEvent(ev.get()); 302 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
420 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 303 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
304 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
421 305
422 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 306 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
423 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 307 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
424 308
425 // Non target modifier key does not affect internal state 309 // Non target modifier key does not affect internal state
426 ev.reset(GenerateKey(true, ui::VKEY_MENU)); 310 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU));
427 sticky_key.HandleKeyEvent(ev.get()); 311 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
428 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 312 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
313 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
429 314
430 ev.reset(GenerateKey(false, ui::VKEY_MENU)); 315 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU));
431 sticky_key.HandleKeyEvent(ev.get()); 316 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
432 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 317 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
318 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
433 319
434 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); 320 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
435 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 321 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
436 322
437 // Non target modifier key does not affect internal state 323 // Non target modifier key does not affect internal state
438 ev.reset(GenerateKey(true, ui::VKEY_MENU)); 324 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU));
439 sticky_key.HandleKeyEvent(ev.get()); 325 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
440 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 326 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
327 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
441 328
442 ev.reset(GenerateKey(false, ui::VKEY_MENU)); 329 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU));
443 sticky_key.HandleKeyEvent(ev.get()); 330 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
444 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 331 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
332 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
445 } 333 }
446 334
447 TEST_F(StickyKeysTest, NormalShortcutTest) { 335 TEST_F(StickyKeysTest, NormalShortcutTest) {
448 // Sticky keys should not be enabled if we perform a normal shortcut. 336 // Sticky keys should not be enabled if we perform a normal shortcut.
449 scoped_ptr<ui::KeyEvent> ev; 337 scoped_ptr<ui::KeyEvent> ev;
450 MockStickyKeysHandlerDelegate* mock_delegate = 338 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
451 new MockStickyKeysHandlerDelegate(this);
452 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
453 339
454 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 340 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
455 341
456 // Perform ctrl+n shortcut. 342 // Perform ctrl+n shortcut.
457 ev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 343 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
458 sticky_key.HandleKeyEvent(ev.get()); 344 int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
459 ev.reset(GenerateKey(true, ui::VKEY_N)); 345 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N));
460 sticky_key.HandleKeyEvent(ev.get()); 346 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
461 ev.reset(GenerateKey(false, ui::VKEY_N)); 347 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_N));
462 sticky_key.HandleKeyEvent(ev.get()); 348 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
463 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 349 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
350 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
351 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
464 352
465 // Sticky keys should not be enabled afterwards. 353 // 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()); 354 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
355 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
356
357 // Perform ctrl+n shortcut, releasing ctrl first.
358 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
359 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
360 ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N));
361 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
362 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
363 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
364 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
365 ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_N));
366 mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key);
367
368 // Sticky keys should not be enabled afterwards.
369 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
370 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
469 } 371 }
470 372
471 TEST_F(StickyKeysTest, NormalModifiedClickTest) { 373 TEST_F(StickyKeysTest, NormalModifiedClickTest) {
472 scoped_ptr<ui::KeyEvent> kev; 374 scoped_ptr<ui::KeyEvent> kev;
473 scoped_ptr<ui::MouseEvent> mev; 375 scoped_ptr<ui::MouseEvent> mev;
474 MockStickyKeysHandlerDelegate* mock_delegate = 376 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
475 new MockStickyKeysHandlerDelegate(this);
476 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
477 377
478 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 378 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
479 379
480 // Perform ctrl+click. 380 // Perform ctrl+click.
481 kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 381 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
482 sticky_key.HandleKeyEvent(kev.get()); 382 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
483 mev.reset(GenerateMouseEvent(true)); 383 mev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
484 sticky_key.HandleMouseEvent(mev.get()); 384 bool released = false;
485 mev.reset(GenerateMouseEvent(false)); 385 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released);
486 sticky_key.HandleMouseEvent(mev.get()); 386 mev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
387 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released);
487 388
488 // Sticky keys should not be enabled afterwards. 389 // Sticky keys should not be enabled afterwards.
489 kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); 390 kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
490 sticky_key.HandleKeyEvent(kev.get()); 391 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
491 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 392 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
393 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
492 } 394 }
493 395
494 TEST_F(StickyKeysTest, MouseMovedModifierTest) { 396 TEST_F(StickyKeysTest, MouseMovedModifierTest) {
495 scoped_ptr<ui::KeyEvent> kev; 397 scoped_ptr<ui::KeyEvent> kev;
496 scoped_ptr<ui::MouseEvent> mev; 398 scoped_ptr<ui::MouseEvent> mev;
497 MockStickyKeysHandlerDelegate* mock_delegate = 399 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
498 new MockStickyKeysHandlerDelegate(this);
499 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
500 400
501 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 401 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
502 402
503 // Press ctrl and handle mouse move events. 403 // Press ctrl and handle mouse move events.
504 kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 404 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
505 sticky_key.HandleKeyEvent(kev.get()); 405 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
506 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(0, 0))); 406 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(0, 0)));
507 sticky_key.HandleMouseEvent(mev.get()); 407 bool released = false;
408 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released);
508 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(100, 100))); 409 mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(100, 100)));
509 sticky_key.HandleMouseEvent(mev.get()); 410 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released);
510 411
511 // Sticky keys should be enabled afterwards. 412 // Sticky keys should be enabled afterwards.
512 kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); 413 kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
513 sticky_key.HandleKeyEvent(kev.get()); 414 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
514 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 415 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
416 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
515 } 417 }
516 418
517 TEST_F(StickyKeysTest, NormalModifiedScrollTest) { 419 TEST_F(StickyKeysTest, NormalModifiedScrollTest) {
518 scoped_ptr<ui::KeyEvent> kev; 420 scoped_ptr<ui::KeyEvent> kev;
519 scoped_ptr<ui::ScrollEvent> sev; 421 scoped_ptr<ui::ScrollEvent> sev;
520 MockStickyKeysHandlerDelegate* mock_delegate = 422 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
521 new MockStickyKeysHandlerDelegate(this);
522 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
523 423
524 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 424 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
525 425
526 // Perform ctrl+scroll. 426 // Perform ctrl+scroll.
527 kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); 427 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL));
428 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
528 sev.reset(GenerateFlingScrollEvent(0, true)); 429 sev.reset(GenerateFlingScrollEvent(0, true));
529 sticky_key.HandleScrollEvent(sev.get()); 430 bool released = false;
431 sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &released);
530 sev.reset(GenerateScrollEvent(10)); 432 sev.reset(GenerateScrollEvent(10));
531 sticky_key.HandleScrollEvent(sev.get()); 433 sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &released);
532 sev.reset(GenerateFlingScrollEvent(10, false)); 434 sev.reset(GenerateFlingScrollEvent(10, false));
533 sticky_key.HandleScrollEvent(sev.get()); 435 sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &released);
534 436
535 // Sticky keys should not be enabled afterwards. 437 // Sticky keys should not be enabled afterwards.
536 kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); 438 kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL));
537 sticky_key.HandleKeyEvent(kev.get()); 439 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
538 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 440 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
441 EXPECT_EQ(ui::EF_NONE, mod_down_flags);
539 } 442 }
540 443
541 TEST_F(StickyKeysTest, MouseEventOneshot) { 444 TEST_F(StickyKeysTest, MouseEventOneshot) {
542 scoped_ptr<ui::MouseEvent> ev; 445 scoped_ptr<ui::MouseEvent> ev;
543 scoped_ptr<ui::KeyEvent> kev; 446 scoped_ptr<ui::KeyEvent> kev;
544 MockStickyKeysHandlerDelegate* mock_delegate = 447 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
545 new MockStickyKeysHandlerDelegate(this);
546 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
547 448
548 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 449 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
549 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 450 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
550 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 451 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
551 452
552 // We should still be in the ENABLED state until we get the mouse 453 // We should still be in the ENABLED state until we get the mouse
553 // release event. 454 // release event.
554 ev.reset(GenerateMouseEvent(true)); 455 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
555 sticky_key.HandleMouseEvent(ev.get()); 456 bool released = false;
556 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 457 int mod_down_flags = 0;
458 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
459 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
557 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 460 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
558 461
559 ev.reset(GenerateMouseEvent(false)); 462 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
560 sticky_key.HandleMouseEvent(ev.get()); 463 released = false;
561 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 464 mod_down_flags = 0;
465 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
466 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
562 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 467 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
563 468
564 // Making sure modifier key release event is dispatched in the right order. 469 // Making sure modifier key release event is dispatched in the right order.
565 ASSERT_EQ(2u, mock_delegate->GetEventCount()); 470 EXPECT_TRUE(released);
566 EXPECT_EQ(ui::ET_MOUSE_RELEASED, mock_delegate->GetEvent(0)->type()); 471 scoped_ptr<ui::Event> up_event;
567 EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); 472 ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event));
473 EXPECT_TRUE(up_event.get());
474 EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type());
568 EXPECT_EQ(ui::VKEY_CONTROL, 475 EXPECT_EQ(ui::VKEY_CONTROL,
569 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) 476 static_cast<const ui::KeyEvent*>(up_event.get())->key_code());
570 ->key_code());
571 477
572 // Enabled state is one shot, so next click should not be control modified. 478 // Enabled state is one shot, so next click should not be control modified.
573 ev.reset(GenerateMouseEvent(true)); 479 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
574 sticky_key.HandleMouseEvent(ev.get()); 480 released = false;
575 EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); 481 mod_down_flags = 0;
482 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
483 EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN);
576 484
577 ev.reset(GenerateMouseEvent(false)); 485 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
578 sticky_key.HandleMouseEvent(ev.get()); 486 released = false;
579 EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); 487 mod_down_flags = 0;
488 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
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 bool released = false;
600 sticky_key.HandleMouseEvent(ev.get()); 508 int mod_down_flags = 0;
601 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 509 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED));
602 ev.reset(GenerateMouseEvent(false)); 510 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
603 sticky_key.HandleMouseEvent(ev.get()); 511 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
604 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 512 ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED));
513 released = false;
514 mod_down_flags = 0;
515 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
516 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
605 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 517 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
606 } 518 }
607 519
608 // Test with mouse wheel. 520 // Test with mouse wheel.
609 for (int i = 0; i < 3; ++i) { 521 for (int i = 0; i < 3; ++i) {
522 bool released = false;
523 int mod_down_flags = 0;
610 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); 524 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta));
611 sticky_key.HandleMouseEvent(ev.get()); 525 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
612 ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta)); 526 ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta));
613 sticky_key.HandleMouseEvent(ev.get()); 527 released = false;
614 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 528 mod_down_flags = 0;
529 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
530 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
615 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 531 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
616 } 532 }
617 533
618 // Test mixed case with mouse events and key events. 534 // Test mixed case with mouse events and key events.
619 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); 535 ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta));
620 sticky_key.HandleMouseEvent(ev.get()); 536 bool released = false;
621 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 537 int mod_down_flags = 0;
622 kev.reset(GenerateKey(true, ui::VKEY_N)); 538 sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released);
623 sticky_key.HandleKeyEvent(kev.get()); 539 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
624 EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); 540 kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N));
625 kev.reset(GenerateKey(false, ui::VKEY_N)); 541 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
626 sticky_key.HandleKeyEvent(kev.get()); 542 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
627 EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); 543 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
544 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
628 545
629 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 546 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
630 } 547 }
631 548
632 TEST_F(StickyKeysTest, ScrollEventOneshot) { 549 TEST_F(StickyKeysTest, ScrollEventOneshot) {
633 scoped_ptr<ui::ScrollEvent> ev; 550 scoped_ptr<ui::ScrollEvent> ev;
634 scoped_ptr<ui::KeyEvent> kev; 551 scoped_ptr<ui::KeyEvent> kev;
635 MockStickyKeysHandlerDelegate* mock_delegate = 552 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
636 new MockStickyKeysHandlerDelegate(this);
637 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
638 553
639 int scroll_deltas[] = {-10, 10}; 554 int scroll_deltas[] = {-10, 10};
640 for (int i = 0; i < 2; ++i) { 555 for (int i = 0; i < 2; ++i) {
641 mock_delegate->ClearEvents();
642
643 // Enable sticky keys. 556 // Enable sticky keys.
644 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 557 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
645 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 558 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
646 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 559 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
647 560
648 // Test a scroll sequence. Sticky keys should only be disabled at the end 561 // 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. 562 // of the scroll sequence. Fling cancel event starts the scroll sequence.
650 ev.reset(GenerateFlingScrollEvent(0, true)); 563 ev.reset(GenerateFlingScrollEvent(0, true));
651 sticky_key.HandleScrollEvent(ev.get()); 564 bool released = false;
652 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 565 int mod_down_flags = 0;
566 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
567 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
653 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 568 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
654 569
655 // Scrolls should all be modified but not disable sticky keys. 570 // Scrolls should all be modified but not disable sticky keys.
656 for (int j = 0; j < 3; ++j) { 571 for (int j = 0; j < 3; ++j) {
657 ev.reset(GenerateScrollEvent(scroll_deltas[i])); 572 ev.reset(GenerateScrollEvent(scroll_deltas[i]));
658 sticky_key.HandleScrollEvent(ev.get()); 573 released = false;
659 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 574 mod_down_flags = 0;
575 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
576 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
660 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 577 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
661 } 578 }
662 579
663 // Fling start event ends scroll sequence. 580 // Fling start event ends scroll sequence.
664 ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false)); 581 ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false));
665 sticky_key.HandleScrollEvent(ev.get()); 582 released = false;
666 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 583 mod_down_flags = 0;
584 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
585 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
667 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 586 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
668 587
669 ASSERT_EQ(2U, mock_delegate->GetEventCount()); 588 scoped_ptr<ui::Event> up_event;
670 EXPECT_EQ(ui::ET_SCROLL_FLING_START, mock_delegate->GetEvent(0)->type()); 589 EXPECT_TRUE(released);
671 EXPECT_FLOAT_EQ(scroll_deltas[i], 590 ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event));
672 static_cast<const ui::ScrollEvent*>( 591 EXPECT_TRUE(up_event.get());
673 mock_delegate->GetEvent(0))->y_offset()); 592 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, 593 EXPECT_EQ(ui::VKEY_CONTROL,
676 static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) 594 static_cast<const ui::KeyEvent*>(up_event.get())->key_code());
677 ->key_code());
678 } 595 }
679 } 596 }
680 597
681 TEST_F(StickyKeysTest, ScrollDirectionChanged) { 598 TEST_F(StickyKeysTest, ScrollDirectionChanged) {
682 scoped_ptr<ui::ScrollEvent> ev; 599 scoped_ptr<ui::ScrollEvent> ev;
683 scoped_ptr<ui::KeyEvent> kev; 600 scoped_ptr<ui::KeyEvent> kev;
684 MockStickyKeysHandlerDelegate* mock_delegate = 601 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
685 new MockStickyKeysHandlerDelegate(this);
686 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
687 602
688 // Test direction change with both boundary value and negative value. 603 // Test direction change with both boundary value and negative value.
689 const int direction_change_values[2] = {0, -10}; 604 const int direction_change_values[2] = {0, -10};
690 for (int i = 0; i < 2; ++i) { 605 for (int i = 0; i < 2; ++i) {
691 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 606 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
692 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 607 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
693 608
694 // Fling cancel starts scroll sequence. 609 // Fling cancel starts scroll sequence.
695 ev.reset(GenerateFlingScrollEvent(0, true)); 610 ev.reset(GenerateFlingScrollEvent(0, true));
696 sticky_key.HandleScrollEvent(ev.get()); 611 bool released = false;
612 int mod_down_flags = 0;
613 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
697 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 614 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
698 615
699 // Test that changing directions in a scroll sequence will 616 // Test that changing directions in a scroll sequence will
700 // return sticky keys to DISABLED state. 617 // return sticky keys to DISABLED state.
701 for (int j = 0; j < 3; ++j) { 618 for (int j = 0; j < 3; ++j) {
702 ev.reset(GenerateScrollEvent(10)); 619 ev.reset(GenerateScrollEvent(10));
703 sticky_key.HandleScrollEvent(ev.get()); 620 released = false;
704 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 621 mod_down_flags = 0;
622 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
623 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
705 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 624 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
706 } 625 }
707 626
708 ev.reset(GenerateScrollEvent(direction_change_values[i])); 627 ev.reset(GenerateScrollEvent(direction_change_values[i]));
709 sticky_key.HandleScrollEvent(ev.get()); 628 released = false;
710 EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); 629 mod_down_flags = 0;
630 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
711 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 631 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
712 } 632 }
713 } 633 }
714 634
715 TEST_F(StickyKeysTest, ScrollEventLocked) { 635 TEST_F(StickyKeysTest, ScrollEventLocked) {
716 scoped_ptr<ui::ScrollEvent> ev; 636 scoped_ptr<ui::ScrollEvent> ev;
717 scoped_ptr<ui::KeyEvent> kev; 637 scoped_ptr<ui::KeyEvent> kev;
718 MockStickyKeysHandlerDelegate* mock_delegate = 638 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
719 new MockStickyKeysHandlerDelegate(this);
720 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
721 639
722 // Lock sticky keys. 640 // Lock sticky keys.
723 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 641 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
724 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 642 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
725 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 643 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
726 644
727 // Test scroll events are correctly modified in locked state. 645 // Test scroll events are correctly modified in locked state.
728 for (int i = 0; i < 5; ++i) { 646 for (int i = 0; i < 5; ++i) {
729 // Fling cancel starts scroll sequence. 647 // Fling cancel starts scroll sequence.
730 ev.reset(GenerateFlingScrollEvent(0, true)); 648 ev.reset(GenerateFlingScrollEvent(0, true));
731 sticky_key.HandleScrollEvent(ev.get()); 649 bool released = false;
650 int mod_down_flags = 0;
651 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
732 652
733 ev.reset(GenerateScrollEvent(10)); 653 ev.reset(GenerateScrollEvent(10));
734 sticky_key.HandleScrollEvent(ev.get()); 654 released = false;
735 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 655 mod_down_flags = 0;
656 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
657 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
736 ev.reset(GenerateScrollEvent(-10)); 658 ev.reset(GenerateScrollEvent(-10));
737 sticky_key.HandleScrollEvent(ev.get()); 659 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
738 EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); 660 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
739 661
740 // Fling start ends scroll sequence. 662 // Fling start ends scroll sequence.
741 ev.reset(GenerateFlingScrollEvent(-10, false)); 663 ev.reset(GenerateFlingScrollEvent(-10, false));
742 sticky_key.HandleScrollEvent(ev.get()); 664 sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released);
743 } 665 }
744 666
745 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); 667 EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
746 } 668 }
747 669
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) { 670 TEST_F(StickyKeysTest, SynthesizedEvents) {
769 // Non-native, internally generated events should be properly handled 671 // Non-native, internally generated events should be properly handled
770 // by sticky keys. 672 // by sticky keys.
771 MockStickyKeysHandlerDelegate* mock_delegate = 673 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN);
772 new MockStickyKeysHandlerDelegate(this);
773 StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
774 674
775 // Test non-native key events. 675 // Test non-native key events.
776 scoped_ptr<ui::KeyEvent> kev; 676 scoped_ptr<ui::KeyEvent> kev;
777 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 677 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
778 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 678 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
779 679
780 kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K)); 680 kev.reset(GenerateSynthesizedKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_K));
781 sticky_key.HandleKeyEvent(kev.get()); 681 int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
782 EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); 682 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
783 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 683 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
784 684
785 kev.reset(GenerateSynthesizedKeyEvent(false, ui::VKEY_K)); 685 kev.reset(GenerateSynthesizedKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_K));
786 sticky_key.HandleKeyEvent(kev.get()); 686 mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key);
787 EXPECT_FALSE(kev->flags() & ui::EF_CONTROL_DOWN); 687 EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN);
788 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 688 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
789 689
790 // Test non-native mouse events. 690 // Test non-native mouse events.
791 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); 691 SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
792 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 692 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
793 693
794 scoped_ptr<ui::MouseEvent> mev; 694 scoped_ptr<ui::MouseEvent> mev;
795 mev.reset(GenerateSynthesizedMouseClickEvent(true, gfx::Point(0, 0))); 695 mev.reset(GenerateSynthesizedMouseClickEvent(ui::ET_MOUSE_PRESSED,
796 sticky_key.HandleMouseEvent(mev.get()); 696 gfx::Point(0, 0)));
797 EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); 697 bool released = false;
698 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released);
699 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
798 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); 700 EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
799 701
800 mev.reset(GenerateSynthesizedMouseClickEvent(false, gfx::Point(0, 0))); 702 mev.reset(GenerateSynthesizedMouseClickEvent(ui::ET_MOUSE_RELEASED,
801 sticky_key.HandleMouseEvent(mev.get()); 703 gfx::Point(0, 0)));
802 EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); 704 released = false;
705 mod_down_flags = 0;
706 sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released);
707 EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN);
708 EXPECT_TRUE(released);
803 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); 709 EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
804 } 710 }
805 711
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 712 } // namespace ash
OLDNEW
« no previous file with comments | « ash/sticky_keys/sticky_keys_overlay_unittest.cc ('k') | chrome/browser/chromeos/chrome_browser_main_chromeos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698