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

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

Powered by Google App Engine
This is Rietveld 408576698