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