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/base/events/event.h" 20 #include "ui/base/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 } 397