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