OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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 <errno.h> | |
6 #include <fcntl.h> | |
7 #include <linux/input.h> | |
8 #include <unistd.h> | |
9 | |
10 #include <vector> | |
11 | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/memory/scoped_vector.h" | |
14 #include "base/message_loop/message_loop.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/evdev/touch_event_converter_ozone.h" | |
21 | |
22 namespace { | |
23 | |
24 static int SetNonBlocking(int fd) { | |
25 int flags = fcntl(fd, F_GETFL, 0); | |
26 if (flags == -1) | |
27 flags = 0; | |
28 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); | |
29 } | |
30 | |
31 } // namespace | |
32 | |
33 namespace ui { | |
34 | |
35 class MockTouchEventConverterOzone : public TouchEventConverterOzone, | |
36 public base::MessageLoop::Dispatcher { | |
37 public: | |
38 MockTouchEventConverterOzone(int a, int b); | |
39 virtual ~MockTouchEventConverterOzone() {}; | |
40 | |
41 void ConfigureReadMock(struct input_event* queue, | |
42 long read_this_many, | |
43 long queue_index); | |
44 | |
45 unsigned size() { return dispatched_events_.size(); } | |
46 TouchEvent* event(unsigned index) { return dispatched_events_[index]; } | |
47 | |
48 // Actually dispatch the event reader code. | |
49 void ReadNow() { | |
50 OnFileCanReadWithoutBlocking(read_pipe_); | |
51 base::RunLoop().RunUntilIdle(); | |
52 } | |
53 | |
54 virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; | |
55 | |
56 private: | |
57 int read_pipe_; | |
58 int write_pipe_; | |
59 | |
60 ScopedVector<TouchEvent> dispatched_events_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterOzone); | |
63 }; | |
64 | |
65 MockTouchEventConverterOzone::MockTouchEventConverterOzone(int a, int b) | |
66 : TouchEventConverterOzone(a, b) { | |
67 pressure_min_ = 30; | |
68 pressure_max_ = 60; | |
69 | |
70 int fds[2]; | |
71 | |
72 DCHECK(pipe(fds) >= 0) << "pipe() failed, errno: " << errno; | |
73 DCHECK(SetNonBlocking(fds[0]) == 0) | |
74 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; | |
75 DCHECK(SetNonBlocking(fds[1]) == 0) | |
76 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; | |
77 read_pipe_ = fds[0]; | |
78 write_pipe_ = fds[1]; | |
79 } | |
80 | |
81 bool MockTouchEventConverterOzone::Dispatch(const base::NativeEvent& event) { | |
82 ui::TouchEvent* ev = new ui::TouchEvent(event); | |
83 dispatched_events_.push_back(ev); | |
84 return true; | |
85 } | |
86 | |
87 void MockTouchEventConverterOzone::ConfigureReadMock(struct input_event* queue, | |
88 long read_this_many, | |
89 long queue_index) { | |
90 int nwrite = HANDLE_EINTR(write(write_pipe_, | |
91 queue + queue_index, | |
92 sizeof(struct input_event) * read_this_many)); | |
93 DCHECK(nwrite == | |
94 static_cast<int>(sizeof(struct input_event) * read_this_many)) | |
95 << "write() failed, errno: " << errno; | |
96 } | |
97 | |
98 } // namespace ui | |
99 | |
100 // Test fixture. | |
101 class TouchEventConverterOzoneTest : public testing::Test { | |
102 public: | |
103 TouchEventConverterOzoneTest() {} | |
104 | |
105 // Overridden from testing::Test: | |
106 virtual void SetUp() OVERRIDE { | |
107 loop_ = new base::MessageLoop(base::MessageLoop::TYPE_UI); | |
108 device_ = new ui::MockTouchEventConverterOzone(-1, 2); | |
109 base::MessagePumpOzone::Current()->AddDispatcherForRootWindow(device_); | |
110 } | |
111 virtual void TearDown() OVERRIDE { | |
112 delete device_; | |
113 delete loop_; | |
114 } | |
115 | |
116 ui::MockTouchEventConverterOzone* device() { return device_; } | |
117 | |
118 private: | |
119 base::MessageLoop* loop_; | |
120 ui::MockTouchEventConverterOzone* device_; | |
121 DISALLOW_COPY_AND_ASSIGN(TouchEventConverterOzoneTest); | |
122 }; | |
123 | |
124 // TODO(rjkroege): Test for valid handling of time stamps. | |
125 TEST_F(TouchEventConverterOzoneTest, TouchDown) { | |
126 ui::MockTouchEventConverterOzone* dev = device(); | |
127 | |
128 struct input_event mock_kernel_queue[] = { | |
129 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, | |
130 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, | |
131 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, | |
132 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, | |
133 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
134 }; | |
135 | |
136 dev->ConfigureReadMock(mock_kernel_queue, 1, 0); | |
137 dev->ReadNow(); | |
138 EXPECT_EQ(0u, dev->size()); | |
139 | |
140 dev->ConfigureReadMock(mock_kernel_queue, 2, 1); | |
141 dev->ReadNow(); | |
142 EXPECT_EQ(0u, dev->size()); | |
143 | |
144 dev->ConfigureReadMock(mock_kernel_queue, 3, 3); | |
145 dev->ReadNow(); | |
146 EXPECT_EQ(1u, dev->size()); | |
147 | |
148 ui::TouchEvent* event = dev->event(0); | |
149 EXPECT_FALSE(event == NULL); | |
150 | |
151 EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type()); | |
152 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); | |
153 EXPECT_EQ(42, event->x()); | |
154 EXPECT_EQ(51, event->y()); | |
155 EXPECT_EQ(0, event->touch_id()); | |
156 EXPECT_FLOAT_EQ(.5f, event->force()); | |
157 EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); | |
158 } | |
159 | |
160 TEST_F(TouchEventConverterOzoneTest, NoEvents) { | |
161 ui::MockTouchEventConverterOzone* dev = device(); | |
162 dev->ConfigureReadMock(NULL, 0, 0); | |
163 EXPECT_EQ(0u, dev->size()); | |
164 } | |
165 | |
166 TEST_F(TouchEventConverterOzoneTest, TouchMove) { | |
167 ui::MockTouchEventConverterOzone* dev = device(); | |
168 | |
169 struct input_event mock_kernel_queue_press[] = { | |
170 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, | |
171 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, | |
172 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, | |
173 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, | |
174 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
175 }; | |
176 | |
177 struct input_event mock_kernel_queue_move1[] = { | |
178 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 50}, | |
179 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, | |
180 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
181 }; | |
182 | |
183 struct input_event mock_kernel_queue_move2[] = { | |
184 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
185 }; | |
186 | |
187 // Setup and discard a press. | |
188 dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); | |
189 dev->ReadNow(); | |
190 EXPECT_EQ(1u, dev->size()); | |
191 | |
192 dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0); | |
193 dev->ReadNow(); | |
194 EXPECT_EQ(2u, dev->size()); | |
195 ui::TouchEvent* event = dev->event(1); | |
196 EXPECT_FALSE(event == NULL); | |
197 | |
198 EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); | |
199 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); | |
200 EXPECT_EQ(42, event->x()); | |
201 EXPECT_EQ(43, event->y()); | |
202 EXPECT_EQ(0, event->touch_id()); | |
203 EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); | |
204 EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); | |
205 | |
206 dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0); | |
207 dev->ReadNow(); | |
208 EXPECT_EQ(3u, dev->size()); | |
209 event = dev->event(2); | |
210 EXPECT_FALSE(event == NULL); | |
211 | |
212 EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); | |
213 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); | |
214 EXPECT_EQ(42, event->x()); | |
215 EXPECT_EQ(42, event->y()); | |
216 EXPECT_EQ(0, event->touch_id()); | |
217 EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); | |
218 EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); | |
219 } | |
220 | |
221 TEST_F(TouchEventConverterOzoneTest, TouchRelease) { | |
222 ui::MockTouchEventConverterOzone* dev = device(); | |
223 | |
224 struct input_event mock_kernel_queue_press[] = { | |
225 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, | |
226 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, | |
227 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, | |
228 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, | |
229 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
230 }; | |
231 | |
232 struct input_event mock_kernel_queue_release[] = { | |
233 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
234 }; | |
235 | |
236 // Setup and discard a press. | |
237 dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); | |
238 dev->ReadNow(); | |
239 EXPECT_EQ(1u, dev->size()); | |
240 ui::TouchEvent* event = dev->event(0); | |
241 EXPECT_FALSE(event == NULL); | |
242 | |
243 dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0); | |
244 dev->ReadNow(); | |
245 EXPECT_EQ(2u, dev->size()); | |
246 event = dev->event(1); | |
247 EXPECT_FALSE(event == NULL); | |
248 | |
249 EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type()); | |
250 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); | |
251 EXPECT_EQ(42, event->x()); | |
252 EXPECT_EQ(51, event->y()); | |
253 EXPECT_EQ(0, event->touch_id()); | |
254 EXPECT_FLOAT_EQ(.5f, event->force()); | |
255 EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); | |
256 } | |
257 | |
258 TEST_F(TouchEventConverterOzoneTest, TwoFingerGesture) { | |
259 ui::MockTouchEventConverterOzone* dev = device(); | |
260 | |
261 ui::TouchEvent* ev0; | |
262 ui::TouchEvent* ev1; | |
263 | |
264 struct input_event mock_kernel_queue_press0[] = { | |
265 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, | |
266 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, | |
267 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, | |
268 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, | |
269 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
270 }; | |
271 // Setup and discard a press. | |
272 dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0); | |
273 dev->ReadNow(); | |
274 EXPECT_EQ(1u, dev->size()); | |
275 | |
276 struct input_event mock_kernel_queue_move0[] = { | |
277 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
278 }; | |
279 // Setup and discard a move. | |
280 dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0); | |
281 dev->ReadNow(); | |
282 EXPECT_EQ(2u, dev->size()); | |
283 | |
284 struct input_event mock_kernel_queue_move0press1[] = { | |
285 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}, | |
286 {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686}, | |
287 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, | |
288 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, | |
289 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 101}, | |
290 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
291 }; | |
292 // Move on 0, press on 1. | |
293 dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0); | |
294 dev->ReadNow(); | |
295 EXPECT_EQ(4u, dev->size()); | |
296 ev0 = dev->event(2); | |
297 ev1 = dev->event(3); | |
298 | |
299 // Move | |
300 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); | |
301 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); | |
302 EXPECT_EQ(40, ev0->x()); | |
303 EXPECT_EQ(51, ev0->y()); | |
304 EXPECT_EQ(0, ev0->touch_id()); | |
305 EXPECT_FLOAT_EQ(.5f, ev0->force()); | |
306 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); | |
307 | |
308 // Press | |
309 EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type()); | |
310 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); | |
311 EXPECT_EQ(101, ev1->x()); | |
312 EXPECT_EQ(102, ev1->y()); | |
313 EXPECT_EQ(1, ev1->touch_id()); | |
314 EXPECT_FLOAT_EQ(.5f, ev1->force()); | |
315 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); | |
316 | |
317 // Stationary 0, Moves 1. | |
318 struct input_event mock_kernel_queue_stationary0_move1[] = { | |
319 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
320 }; | |
321 dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0); | |
322 dev->ReadNow(); | |
323 EXPECT_EQ(5u, dev->size()); | |
324 ev1 = dev->event(4); | |
325 | |
326 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); | |
327 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); | |
328 EXPECT_EQ(40, ev1->x()); | |
329 EXPECT_EQ(102, ev1->y()); | |
330 EXPECT_EQ(1, ev1->touch_id()); | |
331 | |
332 EXPECT_FLOAT_EQ(.5f, ev1->force()); | |
333 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); | |
334 | |
335 // Move 0, stationary 1. | |
336 struct input_event mock_kernel_queue_move0_stationary1[] = { | |
337 {{0, 0}, EV_ABS, ABS_MT_SLOT, 0}, {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 39}, | |
338 {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
339 }; | |
340 dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0); | |
341 dev->ReadNow(); | |
342 EXPECT_EQ(6u, dev->size()); | |
343 ev0 = dev->event(5); | |
344 | |
345 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); | |
346 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); | |
347 EXPECT_EQ(39, ev0->x()); | |
348 EXPECT_EQ(51, ev0->y()); | |
349 EXPECT_EQ(0, ev0->touch_id()); | |
350 EXPECT_FLOAT_EQ(.5f, ev0->force()); | |
351 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); | |
352 | |
353 // Release 0, move 1. | |
354 struct input_event mock_kernel_queue_release0_move1[] = { | |
355 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, | |
356 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 38}, {{0, 0}, EV_SYN, SYN_REPORT, 0} | |
357 }; | |
358 dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0); | |
359 dev->ReadNow(); | |
360 EXPECT_EQ(8u, dev->size()); | |
361 ev0 = dev->event(6); | |
362 ev1 = dev->event(7); | |
363 | |
364 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type()); | |
365 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); | |
366 EXPECT_EQ(39, ev0->x()); | |
367 EXPECT_EQ(51, ev0->y()); | |
368 EXPECT_EQ(0, ev0->touch_id()); | |
369 EXPECT_FLOAT_EQ(.5f, ev0->force()); | |
370 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); | |
371 | |
372 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); | |
373 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); | |
374 EXPECT_EQ(38, ev1->x()); | |
375 EXPECT_EQ(102, ev1->y()); | |
376 EXPECT_EQ(1, ev1->touch_id()); | |
377 EXPECT_FLOAT_EQ(.5f, ev1->force()); | |
378 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); | |
379 | |
380 // Release 1. | |
381 struct input_event mock_kernel_queue_release1[] = { | |
382 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0}, | |
383 }; | |
384 dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0); | |
385 dev->ReadNow(); | |
386 EXPECT_EQ(9u, dev->size()); | |
387 ev1 = dev->event(8); | |
388 | |
389 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type()); | |
390 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); | |
391 EXPECT_EQ(38, ev1->x()); | |
392 EXPECT_EQ(102, ev1->y()); | |
393 EXPECT_EQ(1, ev1->touch_id()); | |
394 EXPECT_FLOAT_EQ(.5f, ev1->force()); | |
395 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); | |
396 } | |
OLD | NEW |