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/tablet_event_converter_evdev.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <linux/input.h>
10 #include <unistd.h>
11
12 #include <memory>
13 #include <utility>
14 #include <vector>
15
16 #include "base/bind.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_file.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/posix/eintr_wrapper.h"
21 #include "base/run_loop.h"
22 #include "base/stl_util.h"
23 #include "base/time/time.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/events/event.h"
26 #include "ui/events/ozone/device/device_manager.h"
27 #include "ui/events/ozone/evdev/event_converter_test_util.h"
28 #include "ui/events/ozone/evdev/event_device_test_util.h"
29 #include "ui/events/ozone/evdev/event_factory_evdev.h"
30 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
31 #include "ui/events/platform/platform_event_dispatcher.h"
32 #include "ui/events/platform/platform_event_source.h"
33 #include "ui/events/test/scoped_event_test_tick_clock.h"
34
35 namespace {
36
37 const char kTestDevicePath[] = "/dev/input/test-device";
38
39 const ui::DeviceAbsoluteAxis kWacomIntuos5SPenAbsAxes[] = {
40 {ABS_X, {0, 0, 31496, 4, 0, 200}},
41 {ABS_Y, {0, 0, 19685, 4, 0, 200}},
42 {ABS_Z, {0, -900, 899, 0, 0, 0}},
43 {ABS_RZ, {0, -900, 899, 0, 0, 0}},
44 {ABS_THROTTLE, {0, -1023, 1023, 0, 0, 0}},
45 {ABS_WHEEL, {0, 0, 1023, 0, 0, 0}},
46 {ABS_PRESSURE, {0, 0, 2047, 0, 0, 0}},
47 {ABS_DISTANCE, {0, 0, 63, 0, 0, 0}},
48 {ABS_TILT_X, {0, 0, 127, 0, 0, 0}},
49 {ABS_TILT_Y, {0, 0, 127, 0, 0, 0}},
50 {ABS_MISC, {0, 0, 0, 0, 0, 0}},
51 };
52
53 const ui::DeviceCapabilities kWacomIntuos5SPen = {
54 /* path */
55 "/sys/devices/pci0000:00/0000:00:14.0/usb1/"
56 "1-1/1-1:1.0/input/input19/event5",
57 /* name */ "Wacom Intuos5 touch S Pen",
58 /* phys */ "",
59 /* uniq */ "",
60 /* bustype */ "0003",
61 /* vendor */ "056a",
62 /* product */ "0026",
63 /* version */ "0107",
64 /* prop */ "1",
65 /* ev */ "1f",
66 /* key */ "1cdf 1f007f 0 0 0 0",
67 /* rel */ "100",
68 /* abs */ "1000f000167",
69 /* msc */ "1",
70 /* sw */ "0",
71 /* led */ "0",
72 /* ff */ "0",
73 kWacomIntuos5SPenAbsAxes,
74 base::size(kWacomIntuos5SPenAbsAxes),
75 };
76
77 const ui::DeviceAbsoluteAxis EpsonBrightLink1430AbsAxes[] = {
78 {ABS_X, {0, 0, 32767, 0, 0, 200}},
79 {ABS_Y, {0, 0, 32767, 0, 0, 200}},
80 {ABS_Z, {0, 0, 32767, 0, 0, 200}},
81 {ABS_RX,{0, 0, 32767, 0, 0, 200}},
82 {ABS_PRESSURE, {0, 0, 32767, 0, 0, 0}},
83 };
84
85 const ui::DeviceCapabilities EpsonBrightLink1430 = {
86 /* path */
87 "/sys/devices/ff580000.usb/usb3/3-1/"
88 "3-1.1/3-1.1.3/3-1.1.3:1.1/0003:04B8:061B.0006/"
89 "input/input12/event6",
90 /* name */ "EPSON EPSON EPSON 1430",
91 /* phys */ "USB-ff580000.USB-1.1.3/input1",
92 /* uniq */ "2.04",
93 /* bustype */ "0003",
94 /* vendor */ "04b8",
95 /* product */ "061b",
96 /* version */ "0200",
97 /* prop */ "0",
98 /* ev */ "1b",
99 /* key */ "c07 30000 0 0 0 0",
100 /* rel */ "0",
101 /* abs */ "100000f",
102 /* msc */ "10",
103 /* sw */ "0",
104 /* led */ "0",
105 /* ff */ "0",
106 EpsonBrightLink1430AbsAxes,
107 base::size(EpsonBrightLink1430AbsAxes),
108 };
109
110 } // namespace
111
112 namespace ui {
113
114 class MockTabletEventConverterEvdev : public TabletEventConverterEvdev {
115 public:
116 MockTabletEventConverterEvdev(base::ScopedFD fd,
117 base::FilePath path,
118 CursorDelegateEvdev* cursor,
119 const EventDeviceInfo& devinfo,
120 DeviceEventDispatcherEvdev* dispatcher);
~MockTabletEventConverterEvdev()121 ~MockTabletEventConverterEvdev() override {}
122
123 void ConfigureReadMock(struct input_event* queue,
124 long read_this_many,
125 long queue_index);
126
127 // Actually dispatch the event reader code.
ReadNow()128 void ReadNow() {
129 OnFileCanReadWithoutBlocking(read_pipe_);
130 base::RunLoop().RunUntilIdle();
131 }
132
133 private:
134 int read_pipe_;
135 int write_pipe_;
136
137 std::vector<std::unique_ptr<Event>> dispatched_events_;
138
139 DISALLOW_COPY_AND_ASSIGN(MockTabletEventConverterEvdev);
140 };
141
142 class MockTabletCursorEvdev : public CursorDelegateEvdev {
143 public:
MockTabletCursorEvdev()144 MockTabletCursorEvdev() { cursor_confined_bounds_ = gfx::Rect(1024, 768); }
~MockTabletCursorEvdev()145 ~MockTabletCursorEvdev() override {}
146
147 // CursorDelegateEvdev:
MoveCursorTo(gfx::AcceleratedWidget widget,const gfx::PointF & location)148 void MoveCursorTo(gfx::AcceleratedWidget widget,
149 const gfx::PointF& location) override {
150 NOTREACHED();
151 }
MoveCursorTo(const gfx::PointF & location)152 void MoveCursorTo(const gfx::PointF& location) override {
153 cursor_location_ = location;
154 }
MoveCursor(const gfx::Vector2dF & delta)155 void MoveCursor(const gfx::Vector2dF& delta) override { NOTREACHED(); }
IsCursorVisible()156 bool IsCursorVisible() override { return 1; }
GetLocation()157 gfx::PointF GetLocation() override { return cursor_location_; }
GetCursorConfinedBounds()158 gfx::Rect GetCursorConfinedBounds() override {
159 return cursor_confined_bounds_;
160 }
InitializeOnEvdev()161 void InitializeOnEvdev() override {}
162 private:
163 gfx::PointF cursor_location_;
164 gfx::Rect cursor_confined_bounds_;
165 DISALLOW_COPY_AND_ASSIGN(MockTabletCursorEvdev);
166 };
167
MockTabletEventConverterEvdev(base::ScopedFD fd,base::FilePath path,CursorDelegateEvdev * cursor,const EventDeviceInfo & devinfo,DeviceEventDispatcherEvdev * dispatcher)168 MockTabletEventConverterEvdev::MockTabletEventConverterEvdev(
169 base::ScopedFD fd,
170 base::FilePath path,
171 CursorDelegateEvdev* cursor,
172 const EventDeviceInfo& devinfo,
173 DeviceEventDispatcherEvdev* dispatcher)
174 : TabletEventConverterEvdev(std::move(fd),
175 path,
176 1,
177 cursor,
178 devinfo,
179 dispatcher) {
180 int fds[2];
181
182 if (pipe(fds))
183 PLOG(FATAL) << "failed pipe";
184
185 EXPECT_TRUE(base::SetNonBlocking(fds[0]) || base::SetNonBlocking(fds[1]))
186 << "failed to set non-blocking: " << strerror(errno);
187
188 read_pipe_ = fds[0];
189 write_pipe_ = fds[1];
190 }
191
ConfigureReadMock(struct input_event * queue,long read_this_many,long queue_index)192 void MockTabletEventConverterEvdev::ConfigureReadMock(struct input_event* queue,
193 long read_this_many,
194 long queue_index) {
195 int nwrite = HANDLE_EINTR(write(write_pipe_, queue + queue_index,
196 sizeof(struct input_event) * read_this_many));
197 DCHECK(nwrite ==
198 static_cast<int>(sizeof(struct input_event) * read_this_many))
199 << "write() failed, errno: " << errno;
200 }
201
202 } // namespace ui
203
204 // Test fixture.
205 class TabletEventConverterEvdevTest : public testing::Test {
206 public:
TabletEventConverterEvdevTest()207 TabletEventConverterEvdevTest() {}
208
209 // Overridden from testing::Test:
SetUp()210 void SetUp() override {
211 cursor_ = std::make_unique<ui::MockTabletCursorEvdev>();
212 device_manager_ = ui::CreateDeviceManagerForTest();
213 keyboard_layout_engine_ = std::make_unique<ui::StubKeyboardLayoutEngine>();
214 event_factory_ = ui::CreateEventFactoryEvdevForTest(
215 cursor_.get(), device_manager_.get(), keyboard_layout_engine_.get(),
216 base::BindRepeating(
217 &TabletEventConverterEvdevTest::DispatchEventForTest,
218 base::Unretained(this)));
219 dispatcher_ =
220 ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get());
221
222 test_clock_ = std::make_unique<ui::test::ScopedEventTestTickClock>();
223 }
224
TearDown()225 void TearDown() override {
226 cursor_.reset();
227 }
228
CreateDevice(const ui::DeviceCapabilities & caps)229 ui::MockTabletEventConverterEvdev* CreateDevice(
230 const ui::DeviceCapabilities& caps) {
231 // Set up pipe to satisfy message pump (unused).
232 int evdev_io[2];
233 if (pipe(evdev_io))
234 PLOG(FATAL) << "failed pipe";
235 base::ScopedFD events_in(evdev_io[0]);
236 events_out_.reset(evdev_io[1]);
237
238 ui::EventDeviceInfo devinfo;
239 CapabilitiesToDeviceInfo(caps, &devinfo);
240 return new ui::MockTabletEventConverterEvdev(
241 std::move(events_in), base::FilePath(kTestDevicePath), cursor_.get(),
242 devinfo, dispatcher_.get());
243 }
244
cursor()245 ui::CursorDelegateEvdev* cursor() { return cursor_.get(); }
246
size()247 unsigned size() { return dispatched_events_.size(); }
dispatched_event(unsigned index)248 ui::MouseEvent* dispatched_event(unsigned index) {
249 DCHECK_GT(dispatched_events_.size(), index);
250 ui::Event* ev = dispatched_events_[index].get();
251 DCHECK(ev->IsMouseEvent());
252 return ev->AsMouseEvent();
253 }
254
DispatchEventForTest(ui::Event * event)255 void DispatchEventForTest(ui::Event* event) {
256 std::unique_ptr<ui::Event> cloned_event = ui::Event::Clone(*event);
257 dispatched_events_.push_back(std::move(cloned_event));
258 }
259
260 private:
261 std::unique_ptr<ui::MockTabletCursorEvdev> cursor_;
262 std::unique_ptr<ui::DeviceManager> device_manager_;
263 std::unique_ptr<ui::KeyboardLayoutEngine> keyboard_layout_engine_;
264 std::unique_ptr<ui::EventFactoryEvdev> event_factory_;
265 std::unique_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
266 std::unique_ptr<ui::test::ScopedEventTestTickClock> test_clock_;
267
268 std::vector<std::unique_ptr<ui::Event>> dispatched_events_;
269
270 base::ScopedFD events_out_;
271
272 DISALLOW_COPY_AND_ASSIGN(TabletEventConverterEvdevTest);
273 };
274
275 #define EPSILON 20
276
277 // Uses real data captured from Wacom Intuos 5 Pen
TEST_F(TabletEventConverterEvdevTest,MoveTopLeft)278 TEST_F(TabletEventConverterEvdevTest, MoveTopLeft) {
279 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
280 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
281
282 struct input_event mock_kernel_queue[] = {
283 {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
284 {{0, 0}, EV_ABS, ABS_X, 477},
285 {{0, 0}, EV_ABS, ABS_TILT_X, 66},
286 {{0, 0}, EV_ABS, ABS_TILT_Y, 62},
287 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
288 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
289 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
290 {{0, 0}, EV_SYN, SYN_REPORT, 0},
291 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
292 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
293 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
294 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
295 {{0, 0}, EV_ABS, ABS_MISC, 0},
296 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
297 {{0, 0}, EV_SYN, SYN_REPORT, 0},
298 };
299
300 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
301 EXPECT_EQ(1u, size());
302
303 ui::MouseEvent* event = dispatched_event(0);
304 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
305
306 EXPECT_LT(cursor()->GetLocation().x(), EPSILON);
307 EXPECT_LT(cursor()->GetLocation().y(), EPSILON);
308 }
309
TEST_F(TabletEventConverterEvdevTest,MoveTopRight)310 TEST_F(TabletEventConverterEvdevTest, MoveTopRight) {
311 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
312 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
313
314 struct input_event mock_kernel_queue[] = {
315 {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
316 {{0, 0}, EV_ABS, ABS_X, 31496},
317 {{0, 0}, EV_ABS, ABS_Y, 109},
318 {{0, 0}, EV_ABS, ABS_TILT_X, 66},
319 {{0, 0}, EV_ABS, ABS_TILT_Y, 61},
320 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
321 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
322 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
323 {{0, 0}, EV_SYN, SYN_REPORT, 0},
324 {{0, 0}, EV_ABS, ABS_X, 0},
325 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
326 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
327 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
328 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
329 {{0, 0}, EV_ABS, ABS_MISC, 0},
330 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
331 {{0, 0}, EV_SYN, SYN_REPORT, 0},
332 };
333
334 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
335 EXPECT_EQ(1u, size());
336
337 ui::MouseEvent* event = dispatched_event(0);
338 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
339
340 EXPECT_GT(cursor()->GetLocation().x(),
341 cursor()->GetCursorConfinedBounds().width() - EPSILON);
342 EXPECT_LT(cursor()->GetLocation().y(), EPSILON);
343 }
344
TEST_F(TabletEventConverterEvdevTest,MoveBottomLeft)345 TEST_F(TabletEventConverterEvdevTest, MoveBottomLeft) {
346 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
347 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
348
349 struct input_event mock_kernel_queue[] = {
350 {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
351 {{0, 0}, EV_ABS, ABS_Y, 19685},
352 {{0, 0}, EV_ABS, ABS_TILT_X, 64},
353 {{0, 0}, EV_ABS, ABS_TILT_Y, 61},
354 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
355 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
356 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
357 {{0, 0}, EV_SYN, SYN_REPORT, 0},
358 {{0, 0}, EV_ABS, ABS_X, 0},
359 {{0, 0}, EV_ABS, ABS_Y, 0},
360 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
361 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
362 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
363 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
364 {{0, 0}, EV_ABS, ABS_MISC, 0},
365 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
366 {{0, 0}, EV_SYN, SYN_REPORT, 0},
367 };
368
369 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
370 EXPECT_EQ(1u, size());
371
372 ui::MouseEvent* event = dispatched_event(0);
373 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
374
375 EXPECT_LT(cursor()->GetLocation().x(), EPSILON);
376 EXPECT_GT(cursor()->GetLocation().y(),
377 cursor()->GetCursorConfinedBounds().height() - EPSILON);
378 }
379
TEST_F(TabletEventConverterEvdevTest,MoveBottomRight)380 TEST_F(TabletEventConverterEvdevTest, MoveBottomRight) {
381 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
382 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
383
384 struct input_event mock_kernel_queue[] = {
385 {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
386 {{0, 0}, EV_ABS, ABS_X, 31496},
387 {{0, 0}, EV_ABS, ABS_Y, 19685},
388 {{0, 0}, EV_ABS, ABS_TILT_X, 67},
389 {{0, 0}, EV_ABS, ABS_TILT_Y, 63},
390 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
391 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
392 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
393 {{0, 0}, EV_SYN, SYN_REPORT, 0},
394 {{0, 0}, EV_ABS, ABS_X, 0},
395 {{0, 0}, EV_ABS, ABS_Y, 0},
396 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
397 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
398 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
399 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
400 {{0, 0}, EV_ABS, ABS_MISC, 0},
401 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
402 {{0, 0}, EV_SYN, SYN_REPORT, 0},
403 };
404
405 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
406 EXPECT_EQ(1u, size());
407
408 ui::MouseEvent* event = dispatched_event(0);
409 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
410
411 EXPECT_GT(cursor()->GetLocation().x(),
412 cursor()->GetCursorConfinedBounds().height() - EPSILON);
413 EXPECT_GT(cursor()->GetLocation().y(),
414 cursor()->GetCursorConfinedBounds().height() - EPSILON);
415 }
416
TEST_F(TabletEventConverterEvdevTest,Tap)417 TEST_F(TabletEventConverterEvdevTest, Tap) {
418 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
419 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
420
421 struct input_event mock_kernel_queue[] = {
422 {{0, 0}, EV_ABS, ABS_X, 15456},
423 {{0, 0}, EV_ABS, ABS_Y, 8605},
424 {{0, 0}, EV_ABS, ABS_DISTANCE, 49},
425 {{0, 0}, EV_ABS, ABS_TILT_X, 68},
426 {{0, 0}, EV_ABS, ABS_TILT_Y, 64},
427 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
428 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
429 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
430 {{0, 0}, EV_SYN, SYN_REPORT, 0},
431 {{0, 0}, EV_ABS, ABS_X, 15725},
432 {{0, 0}, EV_ABS, ABS_Y, 8755},
433 {{0, 0}, EV_ABS, ABS_DISTANCE, 29},
434 {{0, 0}, EV_ABS, ABS_PRESSURE, 992},
435 {{0, 0}, EV_KEY, BTN_TOUCH, 1},
436 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
437 {{0, 0}, EV_SYN, SYN_REPORT, 0},
438 {{0, 0}, EV_ABS, ABS_X, 15922},
439 {{0, 0}, EV_ABS, ABS_Y, 8701},
440 {{0, 0}, EV_ABS, ABS_DISTANCE, 32},
441 {{0, 0}, EV_ABS, ABS_PRESSURE, 0},
442 {{0, 0}, EV_KEY, BTN_TOUCH, 0},
443 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
444 {{0, 0}, EV_SYN, SYN_REPORT, 0},
445 {{0, 0}, EV_ABS, ABS_X, 0},
446 {{0, 0}, EV_ABS, ABS_Y, 0},
447 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
448 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
449 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
450 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
451 {{0, 0}, EV_ABS, ABS_MISC, 0},
452 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
453 {{0, 0}, EV_SYN, SYN_REPORT, 0},
454 };
455
456 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
457 EXPECT_EQ(3u, size());
458
459 ui::MouseEvent* event = dispatched_event(0);
460 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
461 EXPECT_EQ(ui::EventPointerType::POINTER_TYPE_PEN,
462 event->pointer_details().pointer_type);
463 EXPECT_FLOAT_EQ(5.625f, event->pointer_details().tilt_x);
464 EXPECT_FLOAT_EQ(0.f, event->pointer_details().tilt_y);
465 event = dispatched_event(1);
466 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
467 EXPECT_EQ(ui::EventPointerType::POINTER_TYPE_PEN,
468 event->pointer_details().pointer_type);
469 EXPECT_FLOAT_EQ((float)992 / 2047, event->pointer_details().force);
470 EXPECT_EQ(true, event->IsLeftMouseButton());
471 event = dispatched_event(2);
472 EXPECT_EQ(ui::EventPointerType::POINTER_TYPE_PEN,
473 event->pointer_details().pointer_type);
474 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
475 EXPECT_FLOAT_EQ(0.0f, event->pointer_details().force);
476 EXPECT_EQ(true, event->IsLeftMouseButton());
477 }
478
TEST_F(TabletEventConverterEvdevTest,StylusButtonPress)479 TEST_F(TabletEventConverterEvdevTest, StylusButtonPress) {
480 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
481 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
482
483 struct input_event mock_kernel_queue[] = {
484 {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
485 {{0, 0}, EV_ABS, ABS_X, 18372},
486 {{0, 0}, EV_ABS, ABS_Y, 9880},
487 {{0, 0}, EV_ABS, ABS_DISTANCE, 61},
488 {{0, 0}, EV_ABS, ABS_TILT_X, 60},
489 {{0, 0}, EV_ABS, ABS_TILT_Y, 63},
490 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
491 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
492 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
493 {{0, 0}, EV_SYN, SYN_REPORT, 0},
494 {{0, 0}, EV_ABS, ABS_X, 18294},
495 {{0, 0}, EV_ABS, ABS_Y, 9723},
496 {{0, 0}, EV_ABS, ABS_DISTANCE, 20},
497 {{0, 0}, EV_ABS, ABS_PRESSURE, 1015},
498 {{0, 0}, EV_KEY, BTN_STYLUS2, 1},
499 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
500 {{0, 0}, EV_SYN, SYN_REPORT, 0},
501 {{0, 0}, EV_ABS, ABS_X, 18516},
502 {{0, 0}, EV_ABS, ABS_Y, 9723},
503 {{0, 0}, EV_ABS, ABS_DISTANCE, 23},
504 {{0, 0}, EV_KEY, BTN_STYLUS2, 0},
505 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
506 {{0, 0}, EV_SYN, SYN_REPORT, 0},
507 {{0, 0}, EV_ABS, ABS_X, 0},
508 {{0, 0}, EV_ABS, ABS_Y, 0},
509 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
510 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
511 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
512 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
513 {{0, 0}, EV_ABS, ABS_MISC, 0},
514 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
515 {{0, 0}, EV_SYN, SYN_REPORT, 0},
516 };
517
518 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
519 EXPECT_EQ(3u, size());
520
521 ui::MouseEvent* event = dispatched_event(0);
522 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
523 event = dispatched_event(1);
524 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
525 EXPECT_EQ(true, event->IsRightMouseButton());
526 event = dispatched_event(2);
527 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
528 EXPECT_EQ(true, event->IsRightMouseButton());
529 }
530
531 // Should only get an event if BTN_TOOL received
TEST_F(TabletEventConverterEvdevTest,CheckStylusFiltering)532 TEST_F(TabletEventConverterEvdevTest, CheckStylusFiltering) {
533 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
534 base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
535
536 struct input_event mock_kernel_queue[] = {
537 {{0, 0}, EV_ABS, ABS_X, 0},
538 {{0, 0}, EV_ABS, ABS_Y, 0},
539 {{0, 0}, EV_SYN, SYN_REPORT, 0},
540 };
541
542 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
543 EXPECT_EQ(0u, size());
544 }
545
546 // for digitizer pen with only one side button
TEST_F(TabletEventConverterEvdevTest,DigitizerPenOneSideButtonPress)547 TEST_F(TabletEventConverterEvdevTest, DigitizerPenOneSideButtonPress) {
548 std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
549 base::WrapUnique(CreateDevice(EpsonBrightLink1430));
550
551 struct input_event mock_kernel_queue[] = {
552 {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
553 {{0, 0}, EV_ABS, ABS_X, 18372},
554 {{0, 0}, EV_ABS, ABS_Y, 9880},
555 {{0, 0}, EV_ABS, ABS_DISTANCE, 61},
556 {{0, 0}, EV_ABS, ABS_TILT_X, 60},
557 {{0, 0}, EV_ABS, ABS_TILT_Y, 63},
558 {{0, 0}, EV_ABS, ABS_MISC, 1050626},
559 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
560 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
561 {{0, 0}, EV_SYN, SYN_REPORT, 0},
562
563 {{0, 0}, EV_ABS, ABS_X, 18294},
564 {{0, 0}, EV_ABS, ABS_Y, 9723},
565 {{0, 0}, EV_ABS, ABS_DISTANCE, 20},
566 {{0, 0}, EV_ABS, ABS_PRESSURE, 1015},
567 {{0, 0}, EV_KEY, BTN_STYLUS, 1},
568 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
569 {{0, 0}, EV_SYN, SYN_REPORT, 0},
570
571 {{0, 0}, EV_ABS, ABS_X, 18516},
572 {{0, 0}, EV_ABS, ABS_Y, 9723},
573 {{0, 0}, EV_ABS, ABS_DISTANCE, 23},
574 {{0, 0}, EV_KEY, BTN_STYLUS, 0},
575 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
576 {{0, 0}, EV_SYN, SYN_REPORT, 0},
577
578 {{0, 0}, EV_ABS, ABS_X, 0},
579 {{0, 0}, EV_ABS, ABS_Y, 0},
580 {{0, 0}, EV_ABS, ABS_DISTANCE, 0},
581 {{0, 0}, EV_ABS, ABS_TILT_X, 0},
582 {{0, 0}, EV_ABS, ABS_TILT_Y, 0},
583 {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0},
584 {{0, 0}, EV_ABS, ABS_MISC, 0},
585 {{0, 0}, EV_MSC, MSC_SERIAL, 897618290},
586 {{0, 0}, EV_SYN, SYN_REPORT, 0},
587 };
588
589 dev->ProcessEvents(mock_kernel_queue, base::size(mock_kernel_queue));
590 EXPECT_EQ(3u, size());
591
592 ui::MouseEvent* event = dispatched_event(0);
593 EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
594
595 event = dispatched_event(1);
596 EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
597 EXPECT_EQ(true, event->IsRightMouseButton());
598
599 event = dispatched_event(2);
600 EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
601 EXPECT_EQ(true, event->IsRightMouseButton());
602
603 }
604