Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / ash / wm / sticky_keys_unittest.cc
blob813fe4ebc5de7946054afc0ab906661e0b088111
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
3 // found in the LICENSE file.
5 #include "ash/wm/sticky_keys.h"
7 #include <X11/Xlib.h>
8 #undef None
9 #undef Bool
11 #include "ash/test/ash_test_base.h"
12 #include "base/memory/scoped_vector.h"
13 #include "ui/base/x/x11_util.h"
15 namespace ash {
17 // A stub implementation of EventTarget.
18 class StubEventTarget : public ui::EventTarget {
19 public:
20 StubEventTarget() {}
21 virtual ~StubEventTarget() {}
23 virtual bool CanAcceptEvent(const ui::Event& event) OVERRIDE {
24 return true;
27 virtual EventTarget* GetParentTarget() OVERRIDE {
28 return NULL;
31 private:
32 DISALLOW_COPY_AND_ASSIGN(StubEventTarget);
35 // A testable and StickyKeysHandler.
36 class MockStickyKeysHandlerDelegate :
37 public StickyKeysHandler::StickyKeysHandlerDelegate {
38 public:
39 MockStickyKeysHandlerDelegate() {}
40 virtual ~MockStickyKeysHandlerDelegate() {}
42 // StickyKeysHandler override.
43 virtual void DispatchKeyEvent(ui::KeyEvent* event,
44 aura::Window* target) OVERRIDE {
45 key_events_.push_back(event->Copy());
48 // Returns the count of dispatched keyboard event.
49 size_t GetKeyEventCount() const {
50 return key_events_.size();
53 // Returns the |index|-th dispatched keyboard event.
54 const ui::KeyEvent* GetKeyEvent(size_t index) const {
55 return key_events_[index];
58 private:
59 ScopedVector<ui::KeyEvent> key_events_;
61 DISALLOW_COPY_AND_ASSIGN(MockStickyKeysHandlerDelegate);
64 class StickyKeysTest : public test::AshTestBase {
65 protected:
66 virtual void SetUp() OVERRIDE {
67 target_.reset(new StubEventTarget());
68 test::AshTestBase::SetUp();
71 virtual void TearDown() OVERRIDE {
72 test::AshTestBase::TearDown();
73 target_.reset();
76 // Generates keyboard event.
77 ui::KeyEvent* GenerateKey(bool is_key_press, ui::KeyboardCode code) {
78 XEvent* xev = new XEvent();
79 ui::InitXKeyEventForTesting(
80 is_key_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED,
81 code,
83 xev);
84 xevs_.push_back(xev);
85 ui::KeyEvent* event = new ui::KeyEvent(xev, false);
86 ui::Event::DispatcherApi dispatcher(event);
87 dispatcher.set_target(target_.get());
88 return event;
91 private:
92 scoped_ptr<StubEventTarget> target_;
93 ScopedVector<XEvent> xevs_;
96 TEST_F(StickyKeysTest, BasicOneshotScenarioTest) {
97 scoped_ptr<ui::KeyEvent> ev;
98 MockStickyKeysHandlerDelegate* mock_delegate =
99 new MockStickyKeysHandlerDelegate();
100 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
102 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
103 ev.reset(GenerateKey(true, ui::VKEY_SHIFT));
104 sticky_key.HandleKeyEvent(ev.get());
106 ev.reset(GenerateKey(false, ui::VKEY_SHIFT));
107 sticky_key.HandleKeyEvent(ev.get());
109 // By typing Shift key, internal state become ENABLED.
110 EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
112 ev.reset(GenerateKey(true, ui::VKEY_A));
113 sticky_key.HandleKeyEvent(ev.get());
115 // Next keyboard event is shift modified.
116 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
118 ev.reset(GenerateKey(false, ui::VKEY_A));
119 sticky_key.HandleKeyEvent(ev.get());
121 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
122 // Making sure Shift up keyboard event is dispatched.
123 ASSERT_EQ(2U, mock_delegate->GetKeyEventCount());
124 EXPECT_EQ(ui::VKEY_A, mock_delegate->GetKeyEvent(0)->key_code());
125 EXPECT_EQ(ui::ET_KEY_PRESSED, mock_delegate->GetKeyEvent(0)->type());
126 EXPECT_EQ(ui::VKEY_SHIFT, mock_delegate->GetKeyEvent(1)->key_code());
127 EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetKeyEvent(1)->type());
129 // Enabled state is one shot, so next key event should not be shift modified.
130 ev.reset(GenerateKey(true, ui::VKEY_A));
131 sticky_key.HandleKeyEvent(ev.get());
132 EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN);
134 ev.reset(GenerateKey(false, ui::VKEY_A));
135 sticky_key.HandleKeyEvent(ev.get());
136 EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN);
139 TEST_F(StickyKeysTest, BasicLockedScenarioTest) {
140 scoped_ptr<ui::KeyEvent> ev;
141 MockStickyKeysHandlerDelegate* mock_delegate =
142 new MockStickyKeysHandlerDelegate();
143 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
145 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
146 ev.reset(GenerateKey(true, ui::VKEY_SHIFT));
147 sticky_key.HandleKeyEvent(ev.get());
149 ev.reset(GenerateKey(false, ui::VKEY_SHIFT));
150 sticky_key.HandleKeyEvent(ev.get());
152 // By typing shift key, internal state become ENABLED.
153 EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
155 ev.reset(GenerateKey(true, ui::VKEY_SHIFT));
156 sticky_key.HandleKeyEvent(ev.get());
158 ev.reset(GenerateKey(false, ui::VKEY_SHIFT));
159 sticky_key.HandleKeyEvent(ev.get());
161 // By typing shift key again, internal state become LOCKED.
162 EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
164 // All keyboard events including keyUp become shift modified.
165 ev.reset(GenerateKey(true, ui::VKEY_A));
166 sticky_key.HandleKeyEvent(ev.get());
167 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
169 ev.reset(GenerateKey(false, ui::VKEY_A));
170 sticky_key.HandleKeyEvent(ev.get());
171 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
173 // Locked state keeps after normal keyboard event.
174 EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
176 ev.reset(GenerateKey(true, ui::VKEY_B));
177 sticky_key.HandleKeyEvent(ev.get());
178 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
180 ev.reset(GenerateKey(false, ui::VKEY_B));
181 sticky_key.HandleKeyEvent(ev.get());
182 EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
184 EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
186 ev.reset(GenerateKey(true, ui::VKEY_SHIFT));
187 sticky_key.HandleKeyEvent(ev.get());
189 ev.reset(GenerateKey(false, ui::VKEY_SHIFT));
190 sticky_key.HandleKeyEvent(ev.get());
192 // By typing shift key again, internal state become back to DISABLED.
193 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
196 TEST_F(StickyKeysTest, NonTargetModifierTest) {
197 scoped_ptr<ui::KeyEvent> ev;
198 MockStickyKeysHandlerDelegate* mock_delegate =
199 new MockStickyKeysHandlerDelegate();
200 StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
202 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
204 // Non target modifier key does not affect internal state
205 ev.reset(GenerateKey(true, ui::VKEY_MENU));
206 sticky_key.HandleKeyEvent(ev.get());
207 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
209 ev.reset(GenerateKey(false, ui::VKEY_MENU));
210 sticky_key.HandleKeyEvent(ev.get());
211 EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
213 ev.reset(GenerateKey(true, ui::VKEY_SHIFT));
214 sticky_key.HandleKeyEvent(ev.get());
215 ev.reset(GenerateKey(false, ui::VKEY_SHIFT));
216 sticky_key.HandleKeyEvent(ev.get());
217 EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
219 // Non target modifier key does not affect internal state
220 ev.reset(GenerateKey(true, ui::VKEY_MENU));
221 sticky_key.HandleKeyEvent(ev.get());
222 EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
224 ev.reset(GenerateKey(false, ui::VKEY_MENU));
225 sticky_key.HandleKeyEvent(ev.get());
226 EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
228 ev.reset(GenerateKey(true, ui::VKEY_SHIFT));
229 sticky_key.HandleKeyEvent(ev.get());
230 ev.reset(GenerateKey(false, ui::VKEY_SHIFT));
231 sticky_key.HandleKeyEvent(ev.get());
232 EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
234 // Non target modifier key does not affect internal state
235 ev.reset(GenerateKey(true, ui::VKEY_MENU));
236 sticky_key.HandleKeyEvent(ev.get());
237 EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
239 ev.reset(GenerateKey(false, ui::VKEY_MENU));
240 sticky_key.HandleKeyEvent(ev.get());
241 EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
244 } // namespace ash