1 // Copyright 2014 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.
4
5 #include "ui/events/ozone/evdev/input_injector_evdev.h"
6
7 #include "base/bind.h"
8 #include "base/macros.h"
9 #include "base/run_loop.h"
10 #include "base/test/task_environment.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/events/ozone/device/device_manager.h"
14 #include "ui/events/ozone/evdev/event_converter_test_util.h"
15 #include "ui/events/ozone/evdev/event_factory_evdev.h"
16 #include "ui/events/ozone/evdev/testing/fake_cursor_delegate_evdev.h"
17 #include "ui/events/ozone/events_ozone.h"
18 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
19
20 namespace ui {
21
22 using testing::AllOf;
23 using testing::InSequence;
24 using testing::Property;
25
26 class EventObserver {
27 public:
EventDispatchCallback(Event * event)28 void EventDispatchCallback(Event* event) {
29 DispatchEventFromNativeUiEvent(
30 event, base::BindOnce(&EventObserver::OnEvent, base::Unretained(this)));
31 }
32
OnEvent(Event * event)33 void OnEvent(Event* event) {
34 if (event->IsMouseEvent()) {
35 if (event->type() == ET_MOUSEWHEEL) {
36 OnMouseWheelEvent(event->AsMouseWheelEvent());
37 } else {
38 OnMouseEvent(event->AsMouseEvent());
39 }
40 }
41 }
42
43 // Mock functions for intercepting mouse events.
44 MOCK_METHOD1(OnMouseEvent, void(MouseEvent* event));
45 MOCK_METHOD1(OnMouseWheelEvent, void(MouseWheelEvent* event));
46 };
47
48 MATCHER_P4(MatchesMouseEvent, type, button, x, y, "") {
49 if (arg->type() != type) {
50 *result_listener << "Expected type: " << type << " actual: " << arg->type()
51 << " (" << arg->GetName() << ")";
52 return false;
53 }
54 if (button == EF_LEFT_MOUSE_BUTTON && !arg->IsLeftMouseButton()) {
55 *result_listener << "Expected the left button flag is set.";
56 return false;
57 }
58 if (button == EF_RIGHT_MOUSE_BUTTON && !arg->IsRightMouseButton()) {
59 *result_listener << "Expected the right button flag is set.";
60 return false;
61 }
62 if (button == EF_MIDDLE_MOUSE_BUTTON && !arg->IsMiddleMouseButton()) {
63 *result_listener << "Expected the middle button flag is set.";
64 return false;
65 }
66 if (arg->x() != x || arg->y() != y) {
67 *result_listener << "Expected location: (" << x << ", " << y
68 << ") actual: (" << arg->x() << ", " << arg->y() << ")";
69 return false;
70 }
71 return true;
72 }
73
74 class InputInjectorEvdevTest : public testing::Test {
75 public:
76 InputInjectorEvdevTest();
77
78 protected:
79 void SimulateMouseClick(int x, int y, EventFlags button, int count);
80 void ExpectClick(int x, int y, int button, int count);
81
82 EventObserver event_observer_;
83 const EventDispatchCallback dispatch_callback_;
84 FakeCursorDelegateEvdev cursor_;
85
86 std::unique_ptr<DeviceManager> device_manager_;
87 std::unique_ptr<StubKeyboardLayoutEngine> keyboard_layout_engine_;
88 std::unique_ptr<EventFactoryEvdev> event_factory_;
89
90 InputInjectorEvdev injector_;
91
92 base::test::SingleThreadTaskEnvironment task_environment_;
93 base::RunLoop run_loop_;
94
95 private:
96 DISALLOW_COPY_AND_ASSIGN(InputInjectorEvdevTest);
97 };
98
InputInjectorEvdevTest()99 InputInjectorEvdevTest::InputInjectorEvdevTest()
100 : dispatch_callback_(
101 base::BindRepeating(&EventObserver::EventDispatchCallback,
102 base::Unretained(&event_observer_))),
103 device_manager_(CreateDeviceManagerForTest()),
104 keyboard_layout_engine_(std::make_unique<ui::StubKeyboardLayoutEngine>()),
105 event_factory_(
106 CreateEventFactoryEvdevForTest(&cursor_,
107 device_manager_.get(),
108 keyboard_layout_engine_.get(),
109 dispatch_callback_)),
110 injector_(CreateDeviceEventDispatcherEvdevForTest(event_factory_.get()),
111 &cursor_) {}
112
SimulateMouseClick(int x,int y,EventFlags button,int count)113 void InputInjectorEvdevTest::SimulateMouseClick(int x,
114 int y,
115 EventFlags button,
116 int count) {
117 injector_.MoveCursorTo(gfx::PointF(x, y));
118 for (int i = 0; i < count; i++) {
119 injector_.InjectMouseButton(button, true);
120 injector_.InjectMouseButton(button, false);
121 }
122 }
123
ExpectClick(int x,int y,int button,int count)124 void InputInjectorEvdevTest::ExpectClick(int x, int y, int button, int count) {
125 InSequence dummy;
126 EXPECT_CALL(event_observer_,
127 OnMouseEvent(MatchesMouseEvent(ET_MOUSE_MOVED, EF_NONE, x, y)));
128
129 for (int i = 0; i < count; i++) {
130 EXPECT_CALL(event_observer_, OnMouseEvent(MatchesMouseEvent(
131 ET_MOUSE_PRESSED, button, x, y)));
132 EXPECT_CALL(event_observer_, OnMouseEvent(MatchesMouseEvent(
133 ET_MOUSE_RELEASED, button, x, y)));
134 }
135 }
136
TEST_F(InputInjectorEvdevTest,LeftClick)137 TEST_F(InputInjectorEvdevTest, LeftClick) {
138 ExpectClick(12, 13, EF_LEFT_MOUSE_BUTTON, 1);
139 SimulateMouseClick(12, 13, EF_LEFT_MOUSE_BUTTON, 1);
140 run_loop_.RunUntilIdle();
141 }
142
TEST_F(InputInjectorEvdevTest,RightClick)143 TEST_F(InputInjectorEvdevTest, RightClick) {
144 ExpectClick(12, 13, EF_RIGHT_MOUSE_BUTTON, 1);
145 SimulateMouseClick(12, 13, EF_RIGHT_MOUSE_BUTTON, 1);
146 run_loop_.RunUntilIdle();
147 }
148
TEST_F(InputInjectorEvdevTest,MiddleClick)149 TEST_F(InputInjectorEvdevTest, MiddleClick) {
150 ExpectClick(12, 13, EF_MIDDLE_MOUSE_BUTTON, 1);
151 SimulateMouseClick(12, 13, EF_MIDDLE_MOUSE_BUTTON, 1);
152 run_loop_.RunUntilIdle();
153 }
154
TEST_F(InputInjectorEvdevTest,DoubleClick)155 TEST_F(InputInjectorEvdevTest, DoubleClick) {
156 ExpectClick(12, 13, EF_LEFT_MOUSE_BUTTON, 2);
157 SimulateMouseClick(12, 13, EF_LEFT_MOUSE_BUTTON, 2);
158 run_loop_.RunUntilIdle();
159 }
160
TEST_F(InputInjectorEvdevTest,MouseMoved)161 TEST_F(InputInjectorEvdevTest, MouseMoved) {
162 injector_.MoveCursorTo(gfx::PointF(1, 1));
163 run_loop_.RunUntilIdle();
164 EXPECT_EQ(cursor_.GetLocation(), gfx::PointF(1, 1));
165 }
166
TEST_F(InputInjectorEvdevTest,MouseDragged)167 TEST_F(InputInjectorEvdevTest, MouseDragged) {
168 InSequence dummy;
169 EXPECT_CALL(event_observer_,
170 OnMouseEvent(MatchesMouseEvent(ET_MOUSE_PRESSED,
171 EF_LEFT_MOUSE_BUTTON, 0, 0)));
172 EXPECT_CALL(event_observer_,
173 OnMouseEvent(MatchesMouseEvent(ET_MOUSE_DRAGGED,
174 EF_LEFT_MOUSE_BUTTON, 1, 1)));
175 EXPECT_CALL(event_observer_,
176 OnMouseEvent(MatchesMouseEvent(ET_MOUSE_DRAGGED,
177 EF_LEFT_MOUSE_BUTTON, 2, 3)));
178 EXPECT_CALL(event_observer_,
179 OnMouseEvent(MatchesMouseEvent(ET_MOUSE_RELEASED,
180 EF_LEFT_MOUSE_BUTTON, 2, 3)));
181 injector_.InjectMouseButton(EF_LEFT_MOUSE_BUTTON, true);
182 injector_.MoveCursorTo(gfx::PointF(1, 1));
183 injector_.MoveCursorTo(gfx::PointF(2, 3));
184 injector_.InjectMouseButton(EF_LEFT_MOUSE_BUTTON, false);
185 run_loop_.RunUntilIdle();
186 }
187
TEST_F(InputInjectorEvdevTest,MouseWheel)188 TEST_F(InputInjectorEvdevTest, MouseWheel) {
189 InSequence dummy;
190 EXPECT_CALL(event_observer_, OnMouseWheelEvent(AllOf(
191 MatchesMouseEvent(ET_MOUSEWHEEL, 0, 10, 20),
192 Property(&MouseWheelEvent::x_offset, 0),
193 Property(&MouseWheelEvent::y_offset, 100))));
194 EXPECT_CALL(event_observer_, OnMouseWheelEvent(AllOf(
195 MatchesMouseEvent(ET_MOUSEWHEEL, 0, 10, 20),
196 Property(&MouseWheelEvent::x_offset, 100),
197 Property(&MouseWheelEvent::y_offset, 0))));
198 injector_.MoveCursorTo(gfx::PointF(10, 20));
199 injector_.InjectMouseWheel(0, 100);
200 injector_.InjectMouseWheel(100, 0);
201 run_loop_.RunUntilIdle();
202 }
203
204 } // namespace ui
205