Integrate the notification database with the normal code path.
[chromium-blink-merge.git] / ash / autoclick / autoclick_unittest.cc
blobff66e04fc1518a45bc52053274715c38d1ddb2c3
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/autoclick/autoclick_controller.h"
6 #include "ash/shell.h"
7 #include "ash/test/ash_test_base.h"
8 #include "ui/aura/test/test_window_delegate.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_event_dispatcher.h"
11 #include "ui/events/event.h"
12 #include "ui/events/event_constants.h"
13 #include "ui/events/event_handler.h"
14 #include "ui/events/event_utils.h"
15 #include "ui/events/keycodes/keyboard_codes.h"
16 #include "ui/events/test/event_generator.h"
18 namespace ash {
20 class MouseEventCapturer : public ui::EventHandler {
21 public:
22 MouseEventCapturer() { Reset(); }
23 ~MouseEventCapturer() override {}
25 void Reset() {
26 events_.clear();
29 void OnMouseEvent(ui::MouseEvent* event) override {
30 if (!(event->flags() & ui::EF_LEFT_MOUSE_BUTTON))
31 return;
32 // Filter out extraneous mouse events like mouse entered, exited,
33 // capture changed, etc.
34 ui::EventType type = event->type();
35 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_PRESSED ||
36 type == ui::ET_MOUSE_RELEASED) {
37 events_.push_back(ui::MouseEvent(event->type(), event->location(),
38 event->root_location(),
39 ui::EventTimeForNow(), event->flags(),
40 event->changed_button_flags()));
41 // Stop event propagation so we don't click on random stuff that
42 // might break test assumptions.
43 event->StopPropagation();
46 // If there is a possibility that we're in an infinite loop, we should
47 // exit early with a sensible error rather than letting the test time out.
48 ASSERT_LT(events_.size(), 100u);
51 const std::vector<ui::MouseEvent>& captured_events() const {
52 return events_;
55 private:
56 std::vector<ui::MouseEvent> events_;
58 DISALLOW_COPY_AND_ASSIGN(MouseEventCapturer);
61 class AutoclickTest : public test::AshTestBase {
62 public:
63 AutoclickTest() {}
64 ~AutoclickTest() override {}
66 void SetUp() override {
67 test::AshTestBase::SetUp();
68 Shell::GetInstance()->AddPreTargetHandler(&mouse_event_capturer_);
69 GetAutoclickController()->SetAutoclickDelay(0);
71 // Move mouse to deterministic location at the start of each test.
72 GetEventGenerator().MoveMouseTo(100, 100);
75 void TearDown() override {
76 Shell::GetInstance()->RemovePreTargetHandler(&mouse_event_capturer_);
77 test::AshTestBase::TearDown();
80 void MoveMouseWithFlagsTo(int x, int y, ui::EventFlags flags) {
81 GetEventGenerator().set_flags(flags);
82 GetEventGenerator().MoveMouseTo(x, y);
83 GetEventGenerator().set_flags(ui::EF_NONE);
86 const std::vector<ui::MouseEvent>& WaitForMouseEvents() {
87 mouse_event_capturer_.Reset();
88 RunAllPendingInMessageLoop();
89 return mouse_event_capturer_.captured_events();
92 AutoclickController* GetAutoclickController() {
93 return Shell::GetInstance()->autoclick_controller();
96 private:
97 MouseEventCapturer mouse_event_capturer_;
99 DISALLOW_COPY_AND_ASSIGN(AutoclickTest);
102 TEST_F(AutoclickTest, ToggleEnabled) {
103 std::vector<ui::MouseEvent> events;
105 // We should not see any events initially.
106 EXPECT_FALSE(GetAutoclickController()->IsEnabled());
107 events = WaitForMouseEvents();
108 EXPECT_EQ(0u, events.size());
110 // Enable autoclick, and we should see a mouse pressed and
111 // a mouse released event, simulating a click.
112 GetAutoclickController()->SetEnabled(true);
113 GetEventGenerator().MoveMouseTo(0, 0);
114 EXPECT_TRUE(GetAutoclickController()->IsEnabled());
115 events = WaitForMouseEvents();
116 EXPECT_EQ(2u, events.size());
117 EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0].type());
118 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[1].type());
120 // We should not get any more clicks until we move the mouse.
121 events = WaitForMouseEvents();
122 EXPECT_EQ(0u, events.size());
123 GetEventGenerator().MoveMouseTo(30, 30);
124 events = WaitForMouseEvents();
125 EXPECT_EQ(2u, events.size());
126 EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0].type());
127 EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[1].type());
129 // Disable autoclick, and we should see the original behaviour.
130 GetAutoclickController()->SetEnabled(false);
131 EXPECT_FALSE(GetAutoclickController()->IsEnabled());
132 events = WaitForMouseEvents();
133 EXPECT_EQ(0u, events.size());
136 TEST_F(AutoclickTest, MouseMovement) {
137 std::vector<ui::MouseEvent> events;
138 GetAutoclickController()->SetEnabled(true);
140 gfx::Point p1(0, 0);
141 gfx::Point p2(20, 20);
142 gfx::Point p3(40, 40);
144 // Move mouse to p1.
145 GetEventGenerator().MoveMouseTo(p1);
146 events = WaitForMouseEvents();
147 EXPECT_EQ(2u, events.size());
148 EXPECT_EQ(p1.ToString(), events[0].root_location().ToString());
149 EXPECT_EQ(p1.ToString(), events[1].root_location().ToString());
151 // Move mouse to multiple locations and finally arrive at p3.
152 GetEventGenerator().MoveMouseTo(p2);
153 GetEventGenerator().MoveMouseTo(p1);
154 GetEventGenerator().MoveMouseTo(p3);
155 events = WaitForMouseEvents();
156 EXPECT_EQ(2u, events.size());
157 EXPECT_EQ(p3.ToString(), events[0].root_location().ToString());
158 EXPECT_EQ(p3.ToString(), events[1].root_location().ToString());
161 TEST_F(AutoclickTest, MovementThreshold) {
162 UpdateDisplay("1280x1024,800x600");
163 RunAllPendingInMessageLoop();
164 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
165 EXPECT_EQ(2u, root_windows.size());
167 // Run test for the secondary display too to test fix for crbug.com/449870.
168 for (const auto& root_window : root_windows) {
169 gfx::Point center = root_window->GetBoundsInScreen().CenterPoint();
171 GetAutoclickController()->SetEnabled(true);
172 GetEventGenerator().MoveMouseTo(center);
173 EXPECT_EQ(2u, WaitForMouseEvents().size());
175 // Small mouse movements should not trigger an autoclick.
176 GetEventGenerator().MoveMouseTo(center + gfx::Vector2d(1, 1));
177 EXPECT_EQ(0u, WaitForMouseEvents().size());
178 GetEventGenerator().MoveMouseTo(center + gfx::Vector2d(2, 2));
179 EXPECT_EQ(0u, WaitForMouseEvents().size());
180 GetEventGenerator().MoveMouseTo(center);
181 EXPECT_EQ(0u, WaitForMouseEvents().size());
183 // A large mouse movement should trigger an autoclick.
184 GetEventGenerator().MoveMouseTo(center + gfx::Vector2d(100, 100));
185 EXPECT_EQ(2u, WaitForMouseEvents().size());
189 TEST_F(AutoclickTest, SingleKeyModifier) {
190 GetAutoclickController()->SetEnabled(true);
191 MoveMouseWithFlagsTo(20, 20, ui::EF_SHIFT_DOWN);
192 std::vector<ui::MouseEvent> events = WaitForMouseEvents();
193 EXPECT_EQ(2u, events.size());
194 EXPECT_EQ(ui::EF_SHIFT_DOWN, events[0].flags() & ui::EF_SHIFT_DOWN);
195 EXPECT_EQ(ui::EF_SHIFT_DOWN, events[1].flags() & ui::EF_SHIFT_DOWN);
198 TEST_F(AutoclickTest, MultipleKeyModifiers) {
199 GetAutoclickController()->SetEnabled(true);
200 ui::EventFlags modifier_flags = static_cast<ui::EventFlags>(
201 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN);
202 MoveMouseWithFlagsTo(30, 30, modifier_flags);
203 std::vector<ui::MouseEvent> events = WaitForMouseEvents();
204 EXPECT_EQ(2u, events.size());
205 EXPECT_EQ(modifier_flags, events[0].flags() & modifier_flags);
206 EXPECT_EQ(modifier_flags, events[1].flags() & modifier_flags);
209 TEST_F(AutoclickTest, KeyModifiersReleased) {
210 GetAutoclickController()->SetEnabled(true);
212 ui::EventFlags modifier_flags = static_cast<ui::EventFlags>(
213 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN);
214 MoveMouseWithFlagsTo(12, 12, modifier_flags);
216 // Simulate releasing key modifiers by sending key released events.
217 GetEventGenerator().ReleaseKey(ui::VKEY_CONTROL,
218 static_cast<ui::EventFlags>(ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN));
219 GetEventGenerator().ReleaseKey(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
221 std::vector<ui::MouseEvent> events;
222 events = WaitForMouseEvents();
223 EXPECT_EQ(2u, events.size());
224 EXPECT_EQ(0, events[0].flags() & ui::EF_CONTROL_DOWN);
225 EXPECT_EQ(0, events[0].flags() & ui::EF_SHIFT_DOWN);
226 EXPECT_EQ(ui::EF_ALT_DOWN, events[0].flags() & ui::EF_ALT_DOWN);
229 TEST_F(AutoclickTest, UserInputCancelsAutoclick) {
230 GetAutoclickController()->SetEnabled(true);
231 std::vector<ui::MouseEvent> events;
233 // Pressing a normal key should cancel the autoclick.
234 GetEventGenerator().MoveMouseTo(200, 200);
235 GetEventGenerator().PressKey(ui::VKEY_K, ui::EF_NONE);
236 GetEventGenerator().ReleaseKey(ui::VKEY_K, ui::EF_NONE);
237 events = WaitForMouseEvents();
238 EXPECT_EQ(0u, events.size());
240 // Pressing a modifier key should NOT cancel the autoclick.
241 GetEventGenerator().MoveMouseTo(100, 100);
242 GetEventGenerator().PressKey(ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN);
243 GetEventGenerator().ReleaseKey(ui::VKEY_SHIFT, ui::EF_NONE);
244 events = WaitForMouseEvents();
245 EXPECT_EQ(2u, events.size());
247 // Performing a gesture should cancel the autoclick.
248 GetEventGenerator().MoveMouseTo(200, 200);
249 GetEventGenerator().GestureTapDownAndUp(gfx::Point(100, 100));
250 events = WaitForMouseEvents();
251 EXPECT_EQ(0u, events.size());
253 // Test another gesture.
254 GetEventGenerator().MoveMouseTo(100, 100);
255 GetEventGenerator().GestureScrollSequence(
256 gfx::Point(100, 100),
257 gfx::Point(200, 200),
258 base::TimeDelta::FromMilliseconds(200),
260 events = WaitForMouseEvents();
261 EXPECT_EQ(0u, events.size());
263 // Test scroll events.
264 GetEventGenerator().MoveMouseTo(200, 200);
265 GetEventGenerator().ScrollSequence(
266 gfx::Point(100, 100), base::TimeDelta::FromMilliseconds(200),
267 0, 100, 3, 2);
268 events = WaitForMouseEvents();
269 EXPECT_EQ(0u, events.size());
272 TEST_F(AutoclickTest, SynthesizedMouseMovesIgnored) {
273 GetAutoclickController()->SetEnabled(true);
274 std::vector<ui::MouseEvent> events;
275 GetEventGenerator().MoveMouseTo(100, 100);
276 events = WaitForMouseEvents();
277 EXPECT_EQ(2u, events.size());
279 // Show a window and make sure the new window is under the cursor. As a
280 // result, synthesized mouse events will be dispatched to the window, but it
281 // should not trigger an autoclick.
282 aura::test::EventCountDelegate delegate;
283 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
284 &delegate, 123, gfx::Rect(50, 50, 100, 100)));
285 window->Show();
286 events = WaitForMouseEvents();
287 EXPECT_EQ(0u, events.size());
288 EXPECT_EQ("1 1 0", delegate.GetMouseMotionCountsAndReset());
291 } // namespace ash