OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "remoting/host/touch_injector_win.h" |
| 6 |
| 7 #include <map> |
| 8 |
| 9 #include "base/stl_util.h" |
| 10 #include "remoting/proto/event.pb.h" |
| 11 #include "testing/gmock/include/gmock/gmock.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 |
| 14 using ::testing::_; |
| 15 using ::testing::AtLeast; |
| 16 using ::testing::InSequence; |
| 17 using ::testing::ExpectationSet; |
| 18 using ::testing::Return; |
| 19 |
| 20 namespace remoting { |
| 21 |
| 22 using protocol::TouchEvent; |
| 23 using protocol::TouchEventPoint; |
| 24 |
| 25 namespace { |
| 26 |
| 27 // Maps touch pointer ID to expected flags [start, move, end, cancel] listed |
| 28 // below. |
| 29 typedef std::map<uint32_t, uint32_t> IdFlagMap; |
| 30 |
| 31 const uint32_t kStartFlag = |
| 32 POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_DOWN; |
| 33 |
| 34 const uint32_t kMoveFlag = |
| 35 POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE; |
| 36 |
| 37 const uint32_t kEndFlag = POINTER_FLAG_UP; |
| 38 |
| 39 const uint32_t kCancelFlag = POINTER_FLAG_UP | POINTER_FLAG_CANCELED; |
| 40 |
| 41 MATCHER_P(EqualsSinglePointerTouchInfo, expected, "") { |
| 42 return arg->touchMask == expected.touchMask && |
| 43 arg->rcContact.left == expected.rcContact.left && |
| 44 arg->rcContact.top == expected.rcContact.top && |
| 45 arg->rcContact.right == expected.rcContact.right && |
| 46 arg->rcContact.bottom == expected.rcContact.bottom && |
| 47 arg->orientation == expected.orientation && |
| 48 arg->pressure == expected.pressure && |
| 49 arg->pointerInfo.pointerType == expected.pointerInfo.pointerType && |
| 50 arg->pointerInfo.pointerId == expected.pointerInfo.pointerId && |
| 51 arg->pointerInfo.ptPixelLocation.x == |
| 52 expected.pointerInfo.ptPixelLocation.x && |
| 53 arg->pointerInfo.ptPixelLocation.y == |
| 54 expected.pointerInfo.ptPixelLocation.y; |
| 55 } |
| 56 |
| 57 // Make sure that every touch point has the right flag (pointerFlags). |
| 58 MATCHER_P(EqualsPointerTouchInfoFlag, id_to_flag_map, "") { |
| 59 for (size_t i = 0; i < id_to_flag_map.size(); ++i) { |
| 60 const POINTER_TOUCH_INFO* touch_info = arg + i; |
| 61 const uint32_t id = touch_info->pointerInfo.pointerId; |
| 62 if (!ContainsKey(id_to_flag_map, id)) |
| 63 return false; |
| 64 |
| 65 if (id_to_flag_map.find(id)->second != touch_info->pointerInfo.pointerFlags) |
| 66 return false; |
| 67 } |
| 68 return true; |
| 69 } |
| 70 |
| 71 class TouchInjectFunctionsWinMock : public TouchInjectFunctionsWin { |
| 72 public: |
| 73 TouchInjectFunctionsWinMock() = default; |
| 74 ~TouchInjectFunctionsWinMock() override {}; |
| 75 |
| 76 MOCK_METHOD0(Init, bool()); |
| 77 MOCK_METHOD0(Initialized, bool()); |
| 78 MOCK_METHOD2(InitializeTouchInjection, BOOL(UINT32 max_count, DWORD dw_mode)); |
| 79 MOCK_METHOD2(InjectTouchInput, |
| 80 DWORD(UINT32 count, const POINTER_TOUCH_INFO* contacts)); |
| 81 }; |
| 82 |
| 83 } // namespace |
| 84 |
| 85 // A test to make sure that the touch event is converted correctly to |
| 86 // POINTER_TOUCH_INFO. |
| 87 TEST(TouchInjectorWinTest, CheckConversionWithPressure) { |
| 88 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 89 new TouchInjectFunctionsWinMock()); |
| 90 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 91 |
| 92 TouchEvent event; |
| 93 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 94 TouchEventPoint* point = event.add_touch_points(); |
| 95 point->set_id(1234u); |
| 96 point->set_x(321.0f); |
| 97 point->set_y(123.0f); |
| 98 point->set_radius_x(10.0f); |
| 99 point->set_radius_y(20.0f); |
| 100 point->set_pressure(0.5); |
| 101 point->set_angle(45.0f); |
| 102 |
| 103 POINTER_TOUCH_INFO expected_touch_info; |
| 104 expected_touch_info.touchMask = |
| 105 TOUCH_MASK_CONTACTAREA | TOUCH_MASK_ORIENTATION | TOUCH_MASK_PRESSURE; |
| 106 expected_touch_info.rcContact.left = 311; |
| 107 expected_touch_info.rcContact.top = 103; |
| 108 expected_touch_info.rcContact.right = 331; |
| 109 expected_touch_info.rcContact.bottom = 143; |
| 110 expected_touch_info.orientation = 0; |
| 111 expected_touch_info.pressure = 512; |
| 112 expected_touch_info.orientation = 45; |
| 113 |
| 114 expected_touch_info.pointerInfo.pointerType = PT_TOUCH; |
| 115 expected_touch_info.pointerInfo.pointerId = 1234u; |
| 116 expected_touch_info.pointerInfo.ptPixelLocation.x = 321; |
| 117 expected_touch_info.pointerInfo.ptPixelLocation.y = 123; |
| 118 |
| 119 InSequence s; |
| 120 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(true)); |
| 121 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 122 .WillOnce(Return(1)); |
| 123 EXPECT_CALL( |
| 124 *functions_mock, |
| 125 InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info))) |
| 126 .WillOnce(Return(1)); |
| 127 |
| 128 TouchInjectorWin injector; |
| 129 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 130 EXPECT_TRUE(injector.Init()); |
| 131 injector.InjectTouchEvent(event); |
| 132 } |
| 133 |
| 134 // Some devices don't detect pressure. This test is a conversion check for |
| 135 // such devices. |
| 136 TEST(TouchInjectorWinTest, CheckConversionNoPressure) { |
| 137 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 138 new TouchInjectFunctionsWinMock()); |
| 139 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 140 |
| 141 TouchEvent event; |
| 142 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 143 TouchEventPoint* point = event.add_touch_points(); |
| 144 point->set_id(1234u); |
| 145 point->set_x(321.0f); |
| 146 point->set_y(123.0f); |
| 147 point->set_radius_x(10.0f); |
| 148 point->set_radius_y(20.0f); |
| 149 point->set_angle(45.0f); |
| 150 |
| 151 POINTER_TOUCH_INFO expected_touch_info; |
| 152 expected_touch_info.touchMask = |
| 153 TOUCH_MASK_CONTACTAREA | TOUCH_MASK_ORIENTATION; |
| 154 expected_touch_info.rcContact.left = 311; |
| 155 expected_touch_info.rcContact.top = 103; |
| 156 expected_touch_info.rcContact.right = 331; |
| 157 expected_touch_info.rcContact.bottom = 143; |
| 158 expected_touch_info.orientation = 0; |
| 159 expected_touch_info.pressure = 0; |
| 160 expected_touch_info.orientation = 45; |
| 161 |
| 162 expected_touch_info.pointerInfo.pointerType = PT_TOUCH; |
| 163 expected_touch_info.pointerInfo.pointerId = 1234u; |
| 164 expected_touch_info.pointerInfo.ptPixelLocation.x = 321; |
| 165 expected_touch_info.pointerInfo.ptPixelLocation.y = 123; |
| 166 |
| 167 InSequence s; |
| 168 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(true)); |
| 169 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 170 .WillOnce(Return(1)); |
| 171 EXPECT_CALL( |
| 172 *functions_mock, |
| 173 InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info))) |
| 174 .WillOnce(Return(1)); |
| 175 |
| 176 TouchInjectorWin injector; |
| 177 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 178 EXPECT_TRUE(injector.Init()); |
| 179 injector.InjectTouchEvent(event); |
| 180 } |
| 181 |
| 182 // If initialization fails, it should not call any touch injection functions. |
| 183 TEST(TouchInjectorWinTest, InitFailed) { |
| 184 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 185 new TouchInjectFunctionsWinMock()); |
| 186 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(false)); |
| 187 |
| 188 TouchEvent event; |
| 189 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 190 |
| 191 InSequence s; |
| 192 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(false)); |
| 193 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)).Times(0); |
| 194 EXPECT_CALL(*functions_mock, InjectTouchInput(_, _)).Times(0); |
| 195 |
| 196 TouchInjectorWin injector; |
| 197 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 198 EXPECT_FALSE(injector.Init()); |
| 199 injector.InjectTouchEvent(event); |
| 200 } |
| 201 |
| 202 // Deinitialize and initialize should clean the state. |
| 203 TEST(TouchInjectorWinTest, Reinitialize) { |
| 204 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 205 new TouchInjectFunctionsWinMock()); |
| 206 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 207 |
| 208 TouchEvent first_event; |
| 209 first_event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 210 TouchEventPoint* point0 = first_event.add_touch_points(); |
| 211 point0->set_id(0u); |
| 212 |
| 213 TouchEvent second_event; |
| 214 second_event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 215 TouchEventPoint* point1 = second_event.add_touch_points(); |
| 216 point1->set_id(1u); |
| 217 |
| 218 EXPECT_CALL(*functions_mock, Init()) |
| 219 .Times(AtLeast(1)) |
| 220 .WillRepeatedly(Return(true)); |
| 221 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 222 .Times(AtLeast(1)) |
| 223 .WillRepeatedly(Return(1)); |
| 224 |
| 225 InSequence s; |
| 226 IdFlagMap id_to_flags; |
| 227 id_to_flags[0u] = kStartFlag; |
| 228 EXPECT_CALL( |
| 229 *functions_mock, |
| 230 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 231 .WillOnce(Return(1)); |
| 232 |
| 233 // After deinitializing and then initializing, previous touch points should be |
| 234 // gone. |
| 235 id_to_flags.clear(); |
| 236 id_to_flags[1u] = kStartFlag; |
| 237 EXPECT_CALL( |
| 238 *functions_mock, |
| 239 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 240 .WillOnce(Return(1)); |
| 241 |
| 242 TouchInjectorWin injector; |
| 243 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 244 |
| 245 EXPECT_TRUE(injector.Init()); |
| 246 injector.InjectTouchEvent(first_event); |
| 247 injector.Deinitialize(); |
| 248 |
| 249 EXPECT_TRUE(injector.Init()); |
| 250 injector.InjectTouchEvent(second_event); |
| 251 } |
| 252 |
| 253 // Make sure that the flag is set to kStartFlag. |
| 254 TEST(TouchInjectorWinTest, StartTouchPoint) { |
| 255 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 256 new TouchInjectFunctionsWinMock()); |
| 257 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 258 |
| 259 TouchEvent event; |
| 260 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 261 TouchEventPoint* point = event.add_touch_points(); |
| 262 point->set_id(0u); |
| 263 |
| 264 InSequence s; |
| 265 EXPECT_CALL(*functions_mock, Init()) |
| 266 .WillOnce(Return(true)); |
| 267 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 268 .WillOnce(Return(1)); |
| 269 |
| 270 IdFlagMap id_to_flags; |
| 271 id_to_flags[0u] = kStartFlag; |
| 272 EXPECT_CALL( |
| 273 *functions_mock, |
| 274 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 275 .WillOnce(Return(1)); |
| 276 |
| 277 TouchInjectorWin injector; |
| 278 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 279 EXPECT_TRUE(injector.Init()); |
| 280 injector.InjectTouchEvent(event); |
| 281 } |
| 282 |
| 283 // Start a point and then move, make sure the flag is set to kMoveFlag. |
| 284 TEST(TouchInjectorWinTest, MoveTouchPoint) { |
| 285 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 286 new TouchInjectFunctionsWinMock()); |
| 287 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 288 |
| 289 TouchEvent event; |
| 290 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 291 TouchEventPoint* point = event.add_touch_points(); |
| 292 point->set_id(0u); |
| 293 |
| 294 |
| 295 InSequence s; |
| 296 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(true)); |
| 297 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 298 .WillOnce(Return(1)); |
| 299 |
| 300 IdFlagMap id_to_flags; |
| 301 id_to_flags[0u] = kStartFlag; |
| 302 EXPECT_CALL( |
| 303 *functions_mock, |
| 304 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 305 .WillOnce(Return(1)); |
| 306 |
| 307 id_to_flags[0u] = kMoveFlag; |
| 308 EXPECT_CALL( |
| 309 *functions_mock, |
| 310 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 311 .WillOnce(Return(1)); |
| 312 |
| 313 TouchInjectorWin injector; |
| 314 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 315 EXPECT_TRUE(injector.Init()); |
| 316 injector.InjectTouchEvent(event); |
| 317 event.set_event_type(TouchEvent::TOUCH_POINT_MOVE); |
| 318 injector.InjectTouchEvent(event); |
| 319 } |
| 320 |
| 321 // Start a point and then move, make sure the flag is set to kEndFlag. |
| 322 TEST(TouchInjectorWinTest, EndTouchPoint) { |
| 323 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 324 new TouchInjectFunctionsWinMock()); |
| 325 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 326 |
| 327 TouchEvent event; |
| 328 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 329 TouchEventPoint* point = event.add_touch_points(); |
| 330 point->set_id(0u); |
| 331 |
| 332 InSequence s; |
| 333 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(true)); |
| 334 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 335 .WillOnce(Return(1)); |
| 336 |
| 337 IdFlagMap id_to_flags; |
| 338 id_to_flags[0u] = kStartFlag; |
| 339 EXPECT_CALL( |
| 340 *functions_mock, |
| 341 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 342 .WillOnce(Return(1)); |
| 343 |
| 344 id_to_flags[0u] = kEndFlag; |
| 345 EXPECT_CALL( |
| 346 *functions_mock, |
| 347 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 348 .WillOnce(Return(1)); |
| 349 |
| 350 TouchInjectorWin injector; |
| 351 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 352 EXPECT_TRUE(injector.Init()); |
| 353 injector.InjectTouchEvent(event); |
| 354 event.set_event_type(TouchEvent::TOUCH_POINT_END); |
| 355 injector.InjectTouchEvent(event); |
| 356 } |
| 357 |
| 358 // Start a point and then move, make sure the flag is set to kCancelFlag. |
| 359 TEST(TouchInjectorWinTest, CancelTouchPoint) { |
| 360 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 361 new TouchInjectFunctionsWinMock()); |
| 362 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 363 |
| 364 TouchEvent event; |
| 365 event.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 366 TouchEventPoint* point = event.add_touch_points(); |
| 367 point->set_id(0u); |
| 368 |
| 369 InSequence s; |
| 370 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(true)); |
| 371 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 372 .WillOnce(Return(1)); |
| 373 |
| 374 IdFlagMap id_to_flags; |
| 375 id_to_flags[0u] = kStartFlag; |
| 376 EXPECT_CALL( |
| 377 *functions_mock, |
| 378 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 379 .WillOnce(Return(1)); |
| 380 |
| 381 id_to_flags[0u] = kCancelFlag; |
| 382 EXPECT_CALL( |
| 383 *functions_mock, |
| 384 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 385 .WillOnce(Return(1)); |
| 386 |
| 387 TouchInjectorWin injector; |
| 388 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 389 EXPECT_TRUE(injector.Init()); |
| 390 injector.InjectTouchEvent(event); |
| 391 event.set_event_type(TouchEvent::TOUCH_POINT_CANCEL); |
| 392 injector.InjectTouchEvent(event); |
| 393 } |
| 394 |
| 395 // Note that points that haven't changed should be injected as MOVE. |
| 396 // This tests: |
| 397 // 1. Start first touch point. |
| 398 // 2. Start second touch point. |
| 399 // 3. Move both touch points. |
| 400 // 4. Start third touch point. |
| 401 // 5. End second touch point. |
| 402 // 6. Cancel remaining (first and third) touch points. |
| 403 TEST(TouchInjectorWinTest, MultiTouch) { |
| 404 scoped_ptr<TouchInjectFunctionsWinMock> functions_mock( |
| 405 new TouchInjectFunctionsWinMock()); |
| 406 ON_CALL(*functions_mock, Initialized()).WillByDefault(Return(true)); |
| 407 |
| 408 InSequence s; |
| 409 EXPECT_CALL(*functions_mock, Init()).WillOnce(Return(true)); |
| 410 EXPECT_CALL(*functions_mock, InitializeTouchInjection(_, _)) |
| 411 .WillOnce(Return(1)); |
| 412 |
| 413 IdFlagMap id_to_flags; |
| 414 id_to_flags[0u] = kStartFlag; |
| 415 EXPECT_CALL( |
| 416 *functions_mock, |
| 417 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 418 .WillOnce(Return(1)); |
| 419 |
| 420 id_to_flags[0u] = kMoveFlag; |
| 421 id_to_flags[1u] = kStartFlag; |
| 422 EXPECT_CALL( |
| 423 *functions_mock, |
| 424 InjectTouchInput(2, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 425 .WillOnce(Return(1)); |
| 426 |
| 427 id_to_flags[0u] = kMoveFlag; |
| 428 id_to_flags[1u] = kMoveFlag; |
| 429 EXPECT_CALL( |
| 430 *functions_mock, |
| 431 InjectTouchInput(2, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 432 .WillOnce(Return(1)); |
| 433 |
| 434 id_to_flags[0u] = kMoveFlag; |
| 435 id_to_flags[1u] = kMoveFlag; |
| 436 id_to_flags[2u] = kStartFlag; |
| 437 EXPECT_CALL( |
| 438 *functions_mock, |
| 439 InjectTouchInput(3, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 440 .WillOnce(Return(1)); |
| 441 |
| 442 id_to_flags[0u] = kMoveFlag; |
| 443 id_to_flags[1u] = kEndFlag; |
| 444 id_to_flags[2u] = kMoveFlag; |
| 445 EXPECT_CALL( |
| 446 *functions_mock, |
| 447 InjectTouchInput(3, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 448 .WillOnce(Return(1)); |
| 449 |
| 450 id_to_flags.erase(1u); |
| 451 id_to_flags[0u] = kCancelFlag; |
| 452 id_to_flags[2u] = kCancelFlag; |
| 453 EXPECT_CALL( |
| 454 *functions_mock, |
| 455 InjectTouchInput(2, EqualsPointerTouchInfoFlag(id_to_flags))) |
| 456 .WillOnce(Return(1)); |
| 457 |
| 458 TouchInjectorWin injector; |
| 459 injector.SetInjectFunctionsForTest(functions_mock.Pass()); |
| 460 EXPECT_TRUE(injector.Init()); |
| 461 |
| 462 // Start first touch point. |
| 463 TouchEvent first_touch_start; |
| 464 first_touch_start.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 465 TouchEventPoint* point0 = first_touch_start.add_touch_points(); |
| 466 point0->set_id(0u); |
| 467 injector.InjectTouchEvent(first_touch_start); |
| 468 |
| 469 // Add second touch point. |
| 470 TouchEvent second_touch_start; |
| 471 second_touch_start.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 472 TouchEventPoint* point1 = second_touch_start.add_touch_points(); |
| 473 point1->set_id(1u); |
| 474 injector.InjectTouchEvent(second_touch_start); |
| 475 |
| 476 // Move both touch points. |
| 477 TouchEvent move_both; |
| 478 move_both.set_event_type(TouchEvent::TOUCH_POINT_MOVE); |
| 479 point0 = second_touch_start.add_touch_points(); |
| 480 point1 = second_touch_start.add_touch_points(); |
| 481 point0->set_id(0u); |
| 482 point1->set_id(1u); |
| 483 injector.InjectTouchEvent(move_both); |
| 484 |
| 485 // Add another. |
| 486 TouchEvent third_touch_start; |
| 487 third_touch_start.set_event_type(TouchEvent::TOUCH_POINT_START); |
| 488 TouchEventPoint* point2 = third_touch_start.add_touch_points(); |
| 489 point2->set_id(2u); |
| 490 injector.InjectTouchEvent(third_touch_start); |
| 491 |
| 492 // Release second touch point. |
| 493 TouchEvent release_second; |
| 494 release_second.set_event_type(TouchEvent::TOUCH_POINT_END); |
| 495 point1 = release_second.add_touch_points(); |
| 496 point1->set_id(1u); |
| 497 injector.InjectTouchEvent(release_second); |
| 498 |
| 499 // Cancel the remaining two points. |
| 500 TouchEvent cancel_rest; |
| 501 cancel_rest.set_event_type(TouchEvent::TOUCH_POINT_CANCEL); |
| 502 point0 = cancel_rest.add_touch_points(); |
| 503 point0->set_id(0u); |
| 504 point2 = cancel_rest.add_touch_points(); |
| 505 point2->set_id(2u); |
| 506 injector.InjectTouchEvent(cancel_rest); |
| 507 } |
| 508 |
| 509 } // namespace remoting |
OLD | NEW |