Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / events / ozone / evdev / tablet_event_converter_evdev_unittest.cc
blob0df01995e9ee1d5955412abc45af7be0633cb907
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 EXPECT_FALSE(SetNonBlocking(fds[0]) || SetNonBlocking(fds[1]))
120 << "failed to set non-blocking: " << strerror(errno);
122 read_pipe_ = fds[0];
123 write_pipe_ = fds[1];
126 void MockTabletEventConverterEvdev::ConfigureReadMock(struct input_event* queue,
127 long read_this_many,
128 long queue_index) {
129 int nwrite = HANDLE_EINTR(write(write_pipe_, queue + queue_index,
130 sizeof(struct input_event) * read_this_many));
131 DCHECK(nwrite ==
132 static_cast<int>(sizeof(struct input_event) * read_this_many))
133 << "write() failed, errno: " << errno;
136 } // namespace ui
138 // Test fixture.
139 class TabletEventConverterEvdevTest : public testing::Test {
140 public:
141 TabletEventConverterEvdevTest() {}
143 // Overridden from testing::Test:
144 void SetUp() override {
145 // Set up pipe to satisfy message pump (unused).
146 int evdev_io[2];
147 if (pipe(evdev_io))
148 PLOG(FATAL) << "failed pipe";
149 events_in_ = evdev_io[0];
150 events_out_ = evdev_io[1];
152 cursor_.reset(new ui::MockTabletCursorEvdev());
153 device_manager_ = ui::CreateDeviceManagerForTest();
154 event_factory_ = ui::CreateEventFactoryEvdevForTest(
155 cursor_.get(), device_manager_.get(),
156 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine(),
157 base::Bind(&TabletEventConverterEvdevTest::DispatchEventForTest,
158 base::Unretained(this)));
159 dispatcher_ =
160 ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get());
161 device_.reset(new ui::MockTabletEventConverterEvdev(
162 events_in_, base::FilePath(kTestDevicePath), cursor_.get(),
163 dispatcher_.get()));
166 void TearDown() override {
167 cursor_.reset();
168 device_.reset();
171 ui::MockTabletEventConverterEvdev* device() { return device_.get(); }
172 ui::CursorDelegateEvdev* cursor() { return cursor_.get(); }
174 unsigned size() { return dispatched_events_.size(); }
175 ui::MouseEvent* dispatched_event(unsigned index) {
176 DCHECK_GT(dispatched_events_.size(), index);
177 ui::Event* ev = dispatched_events_[index];
178 DCHECK(ev->IsMouseEvent());
179 return static_cast<ui::MouseEvent*>(ev);
182 void DispatchEventForTest(ui::Event* event) {
183 scoped_ptr<ui::Event> cloned_event = ui::Event::Clone(*event);
184 dispatched_events_.push_back(cloned_event.release());
187 private:
188 scoped_ptr<ui::MockTabletCursorEvdev> cursor_;
189 scoped_ptr<ui::DeviceManager> device_manager_;
190 scoped_ptr<ui::EventFactoryEvdev> event_factory_;
191 scoped_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
192 scoped_ptr<ui::MockTabletEventConverterEvdev> device_;
194 ScopedVector<ui::Event> dispatched_events_;
196 int events_out_;
197 int events_in_;
199 DISALLOW_COPY_AND_ASSIGN(TabletEventConverterEvdevTest);
202 #define EPSILON 20
204 // Uses real data captured from Wacom Intuos 4
205 TEST_F(TabletEventConverterEvdevTest, MoveTopLeft) {
206 ui::MockTabletEventConverterEvdev* dev = device();
208 struct input_event mock_kernel_queue[] = {
209 {{0, 0}, EV_ABS, ABS_Y, 616},
210 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
211 {{0, 0}, EV_ABS, ABS_TILT_X, 50},
212 {{0, 0}, EV_ABS, ABS_TILT_Y, 7},
213 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
214 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
215 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
216 {{0, 0}, EV_SYN, SYN_REPORT, 0},
217 {{0, 0}, EV_ABS, ABS_Y, 0},
218 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
219 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
220 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
221 {{0, 0}, EV_ABS, ABS_MISC, 0},
222 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
223 {{0, 0}, EV_SYN, SYN_REPORT, 0},
226 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
227 EXPECT_EQ(1u, size());
229 ui::MouseEvent* event = dispatched_event(0);
230 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
232 EXPECT_LT(cursor()->GetLocation().x(), EPSILON);
233 EXPECT_LT(cursor()->GetLocation().y(), EPSILON);
236 TEST_F(TabletEventConverterEvdevTest, MoveTopRight) {
237 ui::MockTabletEventConverterEvdev* dev = device();
239 struct input_event mock_kernel_queue[] = {
240 {{0, 0}, EV_ABS, ABS_X, 65024},
241 {{0, 0}, EV_ABS, ABS_Y, 33},
242 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
243 {{0, 0}, EV_ABS, ABS_TILT_X, 109},
244 {{0, 0}, EV_ABS, ABS_TILT_Y, 59},
245 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
246 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
247 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
248 {{0, 0}, EV_SYN, SYN_REPORT, 0},
249 {{0, 0}, EV_ABS, ABS_X, 0},
250 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
251 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
252 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
253 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
254 {{0, 0}, EV_ABS, ABS_MISC, 0},
255 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
256 {{0, 0}, EV_SYN, SYN_REPORT, 0},
259 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
260 EXPECT_EQ(1u, size());
262 ui::MouseEvent* event = dispatched_event(0);
263 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
265 EXPECT_GT(cursor()->GetLocation().x(),
266 cursor()->GetCursorConfinedBounds().width() - EPSILON);
267 EXPECT_LT(cursor()->GetLocation().y(), EPSILON);
270 TEST_F(TabletEventConverterEvdevTest, MoveBottomLeft) {
271 ui::MockTabletEventConverterEvdev* dev = device();
273 struct input_event mock_kernel_queue[] = {
274 {{0, 0}, EV_ABS, ABS_Y, 40640},
275 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
276 {{0, 0}, EV_ABS, ABS_TILT_X, 95},
277 {{0, 0}, EV_ABS, ABS_TILT_Y, 44},
278 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
279 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
280 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
281 {{0, 0}, EV_SYN, SYN_REPORT, 0},
282 {{0, 0}, EV_ABS, ABS_Y, 0},
283 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
284 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
285 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
286 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
287 {{0, 0}, EV_ABS, ABS_MISC, 0},
288 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
289 {{0, 0}, EV_SYN, SYN_REPORT, 0},
292 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
293 EXPECT_EQ(1u, size());
295 ui::MouseEvent* event = dispatched_event(0);
296 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
298 EXPECT_LT(cursor()->GetLocation().x(), EPSILON);
299 EXPECT_GT(cursor()->GetLocation().y(),
300 cursor()->GetCursorConfinedBounds().height() - EPSILON);
303 TEST_F(TabletEventConverterEvdevTest, MoveBottomRight) {
304 ui::MockTabletEventConverterEvdev* dev = device();
306 struct input_event mock_kernel_queue[] = {
307 {{0, 0}, EV_ABS, ABS_X, 65024},
308 {{0, 0}, EV_ABS, ABS_Y, 40640},
309 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
310 {{0, 0}, EV_ABS, ABS_TILT_X, 127},
311 {{0, 0}, EV_ABS, ABS_TILT_Y, 89},
312 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
313 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
314 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
315 {{0, 0}, EV_SYN, SYN_REPORT, 0},
316 {{0, 0}, EV_ABS, ABS_X, 0},
317 {{0, 0}, EV_ABS, ABS_Y, 0},
318 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
319 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
320 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
321 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
322 {{0, 0}, EV_ABS, ABS_MISC, 0},
323 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
324 {{0, 0}, EV_SYN, SYN_REPORT, 0},
327 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
328 EXPECT_EQ(1u, size());
330 ui::MouseEvent* event = dispatched_event(0);
331 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
333 EXPECT_GT(cursor()->GetLocation().x(),
334 cursor()->GetCursorConfinedBounds().height() - EPSILON);
335 EXPECT_GT(cursor()->GetLocation().y(),
336 cursor()->GetCursorConfinedBounds().height() - EPSILON);
339 TEST_F(TabletEventConverterEvdevTest, Tap) {
340 ui::MockTabletEventConverterEvdev* dev = device();
342 struct input_event mock_kernel_queue[] = {
343 {{0, 0}, EV_ABS, ABS_X, 31628},
344 {{0, 0}, EV_ABS, ABS_Y, 21670},
345 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
346 {{0, 0}, EV_ABS, ABS_TILT_X, 114},
347 {{0, 0}, EV_ABS, ABS_TILT_Y, 85},
348 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
349 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
350 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
351 {{0, 0}, EV_SYN, SYN_REPORT, 0},
352 {{0, 0}, EV_ABS, ABS_X, 32094},
353 {{0, 0}, EV_ABS, ABS_DISTANCE, 17},
354 {{0, 0}, EV_ABS, ABS_PRESSURE, 883},
355 {{0, 0}, EV_ABS, ABS_TILT_Y, 68},
356 {{0, 0}, EV_KEY, BTN_TOUCH, 1},
357 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
358 {{0, 0}, EV_SYN, SYN_REPORT, 0},
359 {{0, 0}, EV_ABS, ABS_X, 32036},
360 {{0, 0}, EV_ABS, ABS_Y, 21658},
361 {{0, 0}, EV_ABS, ABS_DISTANCE, 19},
362 {{0, 0}, EV_ABS, ABS_PRESSURE, 0},
363 {{0, 0}, EV_KEY, BTN_TOUCH, 0},
364 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
365 {{0, 0}, EV_SYN, SYN_REPORT, 0},
366 {{0, 0}, EV_ABS, ABS_X, 0},
367 {{0, 0}, EV_ABS, ABS_Y, 0},
368 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
369 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
370 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
371 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
372 {{0, 0}, EV_ABS, ABS_MISC, 0},
373 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
374 {{0, 0}, EV_SYN, SYN_REPORT, 0},
377 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
378 EXPECT_EQ(3u, size());
380 ui::MouseEvent* event = dispatched_event(0);
381 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
382 event = dispatched_event(1);
383 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
384 EXPECT_EQ(true, event->IsLeftMouseButton());
385 event = dispatched_event(2);
386 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
387 EXPECT_EQ(true, event->IsLeftMouseButton());
390 TEST_F(TabletEventConverterEvdevTest, StylusButtonPress) {
391 ui::MockTabletEventConverterEvdev* dev = device();
393 struct input_event mock_kernel_queue[] = {
394 {{0, 0}, EV_ABS, ABS_X, 30055},
395 {{0, 0}, EV_ABS, ABS_Y, 18094},
396 {{0, 0}, EV_ABS, ABS_DISTANCE, 62},
397 {{0, 0}, EV_ABS, ABS_TILT_X, 99},
398 {{0, 0}, EV_ABS, ABS_TILT_Y, 68},
399 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
400 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
401 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
402 {{0, 0}, EV_SYN, SYN_REPORT, 0},
403 {{0, 0}, EV_ABS, ABS_X, 29380},
404 {{0, 0}, EV_KEY, BTN_STYLUS2, 1},
405 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
406 {{0, 0}, EV_SYN, SYN_REPORT, 0},
407 {{0, 0}, EV_ABS, ABS_X, 29355},
408 {{0, 0}, EV_ABS, ABS_Y, 20091},
409 {{0, 0}, EV_ABS, ABS_DISTANCE, 34},
410 {{0, 0}, EV_KEY, BTN_STYLUS2, 0},
411 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
412 {{0, 0}, EV_SYN, SYN_REPORT, 0},
413 {{0, 0}, EV_ABS, ABS_X, 0},
414 {{0, 0}, EV_ABS, ABS_Y, 0},
415 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
416 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
417 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
418 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
419 {{0, 0}, EV_ABS, ABS_MISC, 0},
420 {{0, 0}, EV_MSC, MSC_SERIAL, 159403517},
421 {{0, 0}, EV_SYN, SYN_REPORT, 0},
424 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
425 EXPECT_EQ(3u, size());
427 ui::MouseEvent* event = dispatched_event(0);
428 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
429 event = dispatched_event(1);
430 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
431 EXPECT_EQ(true, event->IsRightMouseButton());
432 event = dispatched_event(2);
433 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
434 EXPECT_EQ(true, event->IsRightMouseButton());
437 // Should only get an event if BTN_TOOL received
438 TEST_F(TabletEventConverterEvdevTest, CheckStylusFiltering) {
439 ui::MockTabletEventConverterEvdev* dev = device();
441 struct input_event mock_kernel_queue[] = {
442 {{0, 0}, EV_ABS, ABS_X, 0},
443 {{0, 0}, EV_ABS, ABS_Y, 0},
444 {{0, 0}, EV_SYN, SYN_REPORT, 0},
447 dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
448 EXPECT_EQ(0u, size());