ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / ui / events / ozone / evdev / tablet_event_converter_evdev_unittest.cc
blob5a70e553137c5fb2ff06e7fad6f51dc355683455
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.
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <linux/input.h>
8 #include <unistd.h>
10 #include <vector>
12 #include "base/bind.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/run_loop.h"
17 #include "base/time/time.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/events/event.h"
20 #include "ui/events/ozone/device/device_manager.h"
21 #include "ui/events/ozone/evdev/event_converter_test_util.h"
22 #include "ui/events/ozone/evdev/event_factory_evdev.h"
23 #include "ui/events/ozone/evdev/tablet_event_converter_evdev.h"
24 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
25 #include "ui/events/platform/platform_event_dispatcher.h"
26 #include "ui/events/platform/platform_event_source.h"
28 namespace {
30 static int SetNonBlocking(int fd) {
31 int flags = fcntl(fd, F_GETFL, 0);
32 if (flags == -1)
33 flags = 0;
34 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
37 const char kTestDevicePath[] = "/dev/input/test-device";
39 } // namespace
41 namespace ui {
43 class MockTabletEventConverterEvdev : public TabletEventConverterEvdev {
44 public:
45 MockTabletEventConverterEvdev(int fd,
46 base::FilePath path,
47 CursorDelegateEvdev* cursor,
48 DeviceEventDispatcherEvdev* dispatcher);
49 ~MockTabletEventConverterEvdev() override {};
51 void ConfigureReadMock(struct input_event* queue,
52 long read_this_many,
53 long queue_index);
55 // Actually dispatch the event reader code.
56 void ReadNow() {
57 OnFileCanReadWithoutBlocking(read_pipe_);
58 base::RunLoop().RunUntilIdle();
61 private:
62 int read_pipe_;
63 int write_pipe_;
65 ScopedVector<Event> dispatched_events_;
67 DISALLOW_COPY_AND_ASSIGN(MockTabletEventConverterEvdev);
70 class MockTabletCursorEvdev : public CursorDelegateEvdev {
71 public:
72 MockTabletCursorEvdev() { cursor_confined_bounds_ = gfx::Rect(1024, 768); }
73 ~MockTabletCursorEvdev() override {}
75 // CursorDelegateEvdev:
76 void MoveCursorTo(gfx::AcceleratedWidget widget,
77 const gfx::PointF& location) override {
78 NOTREACHED();
80 void MoveCursorTo(const gfx::PointF& location) override {
81 cursor_location_ = location;
83 void MoveCursor(const gfx::Vector2dF& delta) override { NOTREACHED(); }
84 bool IsCursorVisible() override { return 1; }
85 gfx::PointF GetLocation() override { return cursor_location_; }
86 gfx::Rect GetCursorConfinedBounds() override {
87 return cursor_confined_bounds_;
90 private:
91 gfx::PointF cursor_location_;
92 gfx::Rect cursor_confined_bounds_;
93 DISALLOW_COPY_AND_ASSIGN(MockTabletCursorEvdev);
96 MockTabletEventConverterEvdev::MockTabletEventConverterEvdev(
97 int fd,
98 base::FilePath path,
99 CursorDelegateEvdev* cursor,
100 DeviceEventDispatcherEvdev* dispatcher)
101 : TabletEventConverterEvdev(fd,
102 path,
104 INPUT_DEVICE_UNKNOWN,
105 cursor,
106 EventDeviceInfo(),
107 dispatcher) {
108 // Real values taken from Wacom Intuos 4
109 x_abs_min_ = 0;
110 x_abs_range_ = 65024;
111 y_abs_min_ = 0;
112 y_abs_range_ = 40640;
114 int fds[2];
116 if (pipe(fds))
117 PLOG(FATAL) << "failed pipe";
119 DCHECK(SetNonBlocking(fds[0]) == 0)
120 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
121 DCHECK(SetNonBlocking(fds[1]) == 0)
122 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
123 read_pipe_ = fds[0];
124 write_pipe_ = fds[1];
127 void MockTabletEventConverterEvdev::ConfigureReadMock(struct input_event* queue,
128 long read_this_many,
129 long queue_index) {
130 int nwrite = HANDLE_EINTR(write(write_pipe_, queue + queue_index,
131 sizeof(struct input_event) * read_this_many));
132 DCHECK(nwrite ==
133 static_cast<int>(sizeof(struct input_event) * read_this_many))
134 << "write() failed, errno: " << errno;
137 } // namespace ui
139 // Test fixture.
140 class TabletEventConverterEvdevTest : public testing::Test {
141 public:
142 TabletEventConverterEvdevTest() {}
144 // Overridden from testing::Test:
145 void SetUp() override {
146 // Set up pipe to satisfy message pump (unused).
147 int evdev_io[2];
148 if (pipe(evdev_io))
149 PLOG(FATAL) << "failed pipe";
150 events_in_ = evdev_io[0];
151 events_out_ = evdev_io[1];
153 cursor_.reset(new ui::MockTabletCursorEvdev());
154 device_manager_ = ui::CreateDeviceManagerForTest();
155 event_factory_ = ui::CreateEventFactoryEvdevForTest(
156 cursor_.get(), device_manager_.get(),
157 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine(),
158 base::Bind(&TabletEventConverterEvdevTest::DispatchEventForTest,
159 base::Unretained(this)));
160 dispatcher_ =
161 ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get());
162 device_.reset(new ui::MockTabletEventConverterEvdev(
163 events_in_, base::FilePath(kTestDevicePath), cursor_.get(),
164 dispatcher_.get()));
167 void TearDown() override {
168 cursor_.reset();
169 device_.reset();
172 ui::MockTabletEventConverterEvdev* device() { return device_.get(); }
173 ui::CursorDelegateEvdev* cursor() { return cursor_.get(); }
175 unsigned size() { return dispatched_events_.size(); }
176 ui::MouseEvent* dispatched_event(unsigned index) {
177 DCHECK_GT(dispatched_events_.size(), index);
178 ui::Event* ev = dispatched_events_[index];
179 DCHECK(ev->IsMouseEvent());
180 return static_cast<ui::MouseEvent*>(ev);
183 void DispatchEventForTest(ui::Event* event) {
184 scoped_ptr<ui::Event> cloned_event = ui::Event::Clone(*event);
185 dispatched_events_.push_back(cloned_event.release());
188 private:
189 scoped_ptr<ui::MockTabletCursorEvdev> cursor_;
190 scoped_ptr<ui::DeviceManager> device_manager_;
191 scoped_ptr<ui::EventFactoryEvdev> event_factory_;
192 scoped_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
193 scoped_ptr<ui::MockTabletEventConverterEvdev> device_;
195 ScopedVector<ui::Event> dispatched_events_;
197 int events_out_;
198 int events_in_;
200 DISALLOW_COPY_AND_ASSIGN(TabletEventConverterEvdevTest);
203 #define EPSILON 20
205 // Uses real data captured from Wacom Intuos 4
206 TEST_F(TabletEventConverterEvdevTest, MoveTopLeft) {
207 ui::MockTabletEventConverterEvdev* dev = device();
209 struct input_event mock_kernel_queue[] = {
210 {{0, 0}, EV_ABS, ABS_Y, 616},
211 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
212 {{0, 0}, EV_ABS, ABS_TILT_X, 50},
213 {{0, 0}, EV_ABS, ABS_TILT_Y, 7},
214 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
215 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
216 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
217 {{0, 0}, EV_SYN, SYN_REPORT, 0},
218 {{0, 0}, EV_ABS, ABS_Y, 0},
219 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
220 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
221 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
222 {{0, 0}, EV_ABS, ABS_MISC, 0},
223 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
224 {{0, 0}, EV_SYN, SYN_REPORT, 0},
227 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
228 EXPECT_EQ(1u, size());
230 ui::MouseEvent* event = dispatched_event(0);
231 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
233 EXPECT_LT(cursor()->GetLocation().x(), EPSILON);
234 EXPECT_LT(cursor()->GetLocation().y(), EPSILON);
237 TEST_F(TabletEventConverterEvdevTest, MoveTopRight) {
238 ui::MockTabletEventConverterEvdev* dev = device();
240 struct input_event mock_kernel_queue[] = {
241 {{0, 0}, EV_ABS, ABS_X, 65024},
242 {{0, 0}, EV_ABS, ABS_Y, 33},
243 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
244 {{0, 0}, EV_ABS, ABS_TILT_X, 109},
245 {{0, 0}, EV_ABS, ABS_TILT_Y, 59},
246 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
247 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
248 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
249 {{0, 0}, EV_SYN, SYN_REPORT, 0},
250 {{0, 0}, EV_ABS, ABS_X, 0},
251 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
252 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
253 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
254 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
255 {{0, 0}, EV_ABS, ABS_MISC, 0},
256 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
257 {{0, 0}, EV_SYN, SYN_REPORT, 0},
260 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
261 EXPECT_EQ(1u, size());
263 ui::MouseEvent* event = dispatched_event(0);
264 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
266 EXPECT_GT(cursor()->GetLocation().x(),
267 cursor()->GetCursorConfinedBounds().width() - EPSILON);
268 EXPECT_LT(cursor()->GetLocation().y(), EPSILON);
271 TEST_F(TabletEventConverterEvdevTest, MoveBottomLeft) {
272 ui::MockTabletEventConverterEvdev* dev = device();
274 struct input_event mock_kernel_queue[] = {
275 {{0, 0}, EV_ABS, ABS_Y, 40640},
276 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
277 {{0, 0}, EV_ABS, ABS_TILT_X, 95},
278 {{0, 0}, EV_ABS, ABS_TILT_Y, 44},
279 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
280 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
281 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
282 {{0, 0}, EV_SYN, SYN_REPORT, 0},
283 {{0, 0}, EV_ABS, ABS_Y, 0},
284 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
285 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
286 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
287 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
288 {{0, 0}, EV_ABS, ABS_MISC, 0},
289 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
290 {{0, 0}, EV_SYN, SYN_REPORT, 0},
293 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
294 EXPECT_EQ(1u, size());
296 ui::MouseEvent* event = dispatched_event(0);
297 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
299 EXPECT_LT(cursor()->GetLocation().x(), EPSILON);
300 EXPECT_GT(cursor()->GetLocation().y(),
301 cursor()->GetCursorConfinedBounds().height() - EPSILON);
304 TEST_F(TabletEventConverterEvdevTest, MoveBottomRight) {
305 ui::MockTabletEventConverterEvdev* dev = device();
307 struct input_event mock_kernel_queue[] = {
308 {{0, 0}, EV_ABS, ABS_X, 65024},
309 {{0, 0}, EV_ABS, ABS_Y, 40640},
310 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
311 {{0, 0}, EV_ABS, ABS_TILT_X, 127},
312 {{0, 0}, EV_ABS, ABS_TILT_Y, 89},
313 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
314 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
315 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
316 {{0, 0}, EV_SYN, SYN_REPORT, 0},
317 {{0, 0}, EV_ABS, ABS_X, 0},
318 {{0, 0}, EV_ABS, ABS_Y, 0},
319 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
320 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
321 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
322 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
323 {{0, 0}, EV_ABS, ABS_MISC, 0},
324 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
325 {{0, 0}, EV_SYN, SYN_REPORT, 0},
328 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
329 EXPECT_EQ(1u, size());
331 ui::MouseEvent* event = dispatched_event(0);
332 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
334 EXPECT_GT(cursor()->GetLocation().x(),
335 cursor()->GetCursorConfinedBounds().height() - EPSILON);
336 EXPECT_GT(cursor()->GetLocation().y(),
337 cursor()->GetCursorConfinedBounds().height() - EPSILON);
340 TEST_F(TabletEventConverterEvdevTest, Tap) {
341 ui::MockTabletEventConverterEvdev* dev = device();
343 struct input_event mock_kernel_queue[] = {
344 {{0, 0}, EV_ABS, ABS_X, 31628},
345 {{0, 0}, EV_ABS, ABS_Y, 21670},
346 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
347 {{0, 0}, EV_ABS, ABS_TILT_X, 114},
348 {{0, 0}, EV_ABS, ABS_TILT_Y, 85},
349 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
350 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
351 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
352 {{0, 0}, EV_SYN, SYN_REPORT, 0},
353 {{0, 0}, EV_ABS, ABS_X, 32094},
354 {{0, 0}, EV_ABS, ABS_DISTANCE, 17},
355 {{0, 0}, EV_ABS, ABS_PRESSURE, 883},
356 {{0, 0}, EV_ABS, ABS_TILT_Y, 68},
357 {{0, 0}, EV_KEY, BTN_TOUCH, 1},
358 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
359 {{0, 0}, EV_SYN, SYN_REPORT, 0},
360 {{0, 0}, EV_ABS, ABS_X, 32036},
361 {{0, 0}, EV_ABS, ABS_Y, 21658},
362 {{0, 0}, EV_ABS, ABS_DISTANCE, 19},
363 {{0, 0}, EV_ABS, ABS_PRESSURE, 0},
364 {{0, 0}, EV_KEY, BTN_TOUCH, 0},
365 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
366 {{0, 0}, EV_SYN, SYN_REPORT, 0},
367 {{0, 0}, EV_ABS, ABS_X, 0},
368 {{0, 0}, EV_ABS, ABS_Y, 0},
369 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
370 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
371 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
372 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
373 {{0, 0}, EV_ABS, ABS_MISC, 0},
374 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
375 {{0, 0}, EV_SYN, SYN_REPORT, 0},
378 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
379 EXPECT_EQ(3u, size());
381 ui::MouseEvent* event = dispatched_event(0);
382 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
383 event = dispatched_event(1);
384 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
385 EXPECT_EQ(true, event->IsLeftMouseButton());
386 event = dispatched_event(2);
387 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
388 EXPECT_EQ(true, event->IsLeftMouseButton());
391 TEST_F(TabletEventConverterEvdevTest, StylusButtonPress) {
392 ui::MockTabletEventConverterEvdev* dev = device();
394 struct input_event mock_kernel_queue[] = {
395 {{0, 0}, EV_ABS, ABS_X, 30055},
396 {{0, 0}, EV_ABS, ABS_Y, 18094},
397 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
398 {{0, 0}, EV_ABS, ABS_TILT_X, 99},
399 {{0, 0}, EV_ABS, ABS_TILT_Y, 68},
400 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
401 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
402 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
403 {{0, 0}, EV_SYN, SYN_REPORT, 0},
404 {{0, 0}, EV_ABS, ABS_X, 29380},
405 {{0, 0}, EV_KEY, BTN_STYLUS2, 1},
406 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
407 {{0, 0}, EV_SYN, SYN_REPORT, 0},
408 {{0, 0}, EV_ABS, ABS_X, 29355},
409 {{0, 0}, EV_ABS, ABS_Y, 20091},
410 {{0, 0}, EV_ABS, ABS_DISTANCE, 34},
411 {{0, 0}, EV_KEY, BTN_STYLUS2, 0},
412 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
413 {{0, 0}, EV_SYN, SYN_REPORT, 0},
414 {{0, 0}, EV_ABS, ABS_X, 0},
415 {{0, 0}, EV_ABS, ABS_Y, 0},
416 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
417 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
418 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
419 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
420 {{0, 0}, EV_ABS, ABS_MISC, 0},
421 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
422 {{0, 0}, EV_SYN, SYN_REPORT, 0},
425 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
426 EXPECT_EQ(3u, size());
428 ui::MouseEvent* event = dispatched_event(0);
429 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
430 event = dispatched_event(1);
431 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
432 EXPECT_EQ(true, event->IsRightMouseButton());
433 event = dispatched_event(2);
434 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
435 EXPECT_EQ(true, event->IsRightMouseButton());
438 // Should only get an event if BTN_TOOL received
439 TEST_F(TabletEventConverterEvdevTest, CheckStylusFiltering) {
440 ui::MockTabletEventConverterEvdev* dev = device();
442 struct input_event mock_kernel_queue[] = {
443 {{0, 0}, EV_ABS, ABS_X, 0},
444 {{0, 0}, EV_ABS, ABS_Y, 0},
445 {{0, 0}, EV_SYN, SYN_REPORT, 0},
448 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
449 EXPECT_EQ(0u, size());