Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / remoting / host / touch_injector_win_unittest.cc
blob791b95fcca045670d65c26f497d956167df6f0a7
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.
5 #include "remoting/host/touch_injector_win.h"
7 #include <map>
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"
14 using ::testing::_;
15 using ::testing::AtLeast;
16 using ::testing::InSequence;
17 using ::testing::ExpectationSet;
18 using ::testing::Return;
20 namespace remoting {
22 using protocol::TouchEvent;
23 using protocol::TouchEventPoint;
25 namespace {
27 // Maps touch pointer ID to expected flags [start, move, end, cancel] listed
28 // below.
29 typedef std::map<uint32_t, uint32_t> IdFlagMap;
31 const uint32_t kStartFlag =
32 POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_DOWN;
34 const uint32_t kMoveFlag =
35 POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE;
37 const uint32_t kEndFlag = POINTER_FLAG_UP;
39 const uint32_t kCancelFlag = POINTER_FLAG_UP | POINTER_FLAG_CANCELED;
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;
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;
65 if (id_to_flag_map.find(id)->second != touch_info->pointerInfo.pointerFlags)
66 return false;
68 return true;
71 class TouchInjectorWinDelegateMock : public TouchInjectorWinDelegate {
72 public:
73 TouchInjectorWinDelegateMock()
74 : TouchInjectorWinDelegate(nullptr, nullptr, nullptr) {}
75 ~TouchInjectorWinDelegateMock() override {};
77 MOCK_METHOD2(InitializeTouchInjection, BOOL(UINT32 max_count, DWORD dw_mode));
78 MOCK_METHOD2(InjectTouchInput,
79 DWORD(UINT32 count, const POINTER_TOUCH_INFO* contacts));
82 } // namespace
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>());
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);
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;
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;
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));
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));
132 expected_touch_info.pressure = 0; // Min
133 EXPECT_CALL(
134 *delegate_mock,
135 InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info)))
136 .WillOnce(Return(1));
138 TouchInjectorWin injector;
139 injector.SetInjectorDelegateForTest(delegate_mock.Pass());
140 EXPECT_TRUE(injector.Init());
141 injector.InjectTouchEvent(event);
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);
148 point->set_pressure(-3.0f);
149 injector.InjectTouchEvent(event);
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>());
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);
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;
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;
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));
192 TouchInjectorWin injector;
193 injector.SetInjectorDelegateForTest(delegate_mock.Pass());
194 EXPECT_TRUE(injector.Init());
195 injector.InjectTouchEvent(event);
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>());
203 TouchEvent event;
204 event.set_event_type(TouchEvent::TOUCH_POINT_START);
206 InSequence s;
207 EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
208 .WillOnce(Return(0));
209 EXPECT_CALL(*delegate_mock, InjectTouchInput(_, _)).Times(0);
211 TouchInjectorWin injector;
212 injector.SetInjectorDelegateForTest(delegate_mock.Pass());
213 EXPECT_FALSE(injector.Init());
214 injector.InjectTouchEvent(event);
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>());
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);
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);
234 InSequence s;
235 EXPECT_CALL(*delegate_mock_before_deinitialize,
236 InitializeTouchInjection(_, _)).WillOnce(Return(1));
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));
245 EXPECT_CALL(*delegate_mock_after_deinitialize,
246 InitializeTouchInjection(_, _)).WillOnce(Return(1));
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));
257 TouchInjectorWin injector;
258 injector.SetInjectorDelegateForTest(delegate_mock_before_deinitialize.Pass());
260 EXPECT_TRUE(injector.Init());
261 injector.InjectTouchEvent(first_event);
262 injector.Deinitialize();
264 injector.SetInjectorDelegateForTest(delegate_mock_after_deinitialize.Pass());
265 EXPECT_TRUE(injector.Init());
266 injector.InjectTouchEvent(second_event);
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>());
274 TouchEvent event;
275 event.set_event_type(TouchEvent::TOUCH_POINT_START);
276 TouchEventPoint* point = event.add_touch_points();
277 point->set_id(0u);
279 InSequence s;
280 EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
281 .WillOnce(Return(1));
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));
290 TouchInjectorWin injector;
291 injector.SetInjectorDelegateForTest(delegate_mock.Pass());
292 EXPECT_TRUE(injector.Init());
293 injector.InjectTouchEvent(event);
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>());
301 TouchEvent event;
302 event.set_event_type(TouchEvent::TOUCH_POINT_START);
303 TouchEventPoint* point = event.add_touch_points();
304 point->set_id(0u);
307 InSequence s;
308 EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
309 .WillOnce(Return(1));
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));
318 id_to_flags[0u] = kMoveFlag;
319 EXPECT_CALL(
320 *delegate_mock,
321 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
322 .WillOnce(Return(1));
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);
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>());
337 TouchEvent event;
338 event.set_event_type(TouchEvent::TOUCH_POINT_START);
339 TouchEventPoint* point = event.add_touch_points();
340 point->set_id(0u);
342 InSequence s;
343 EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
344 .WillOnce(Return(1));
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));
353 id_to_flags[0u] = kEndFlag;
354 EXPECT_CALL(
355 *delegate_mock,
356 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
357 .WillOnce(Return(1));
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);
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>());
372 TouchEvent event;
373 event.set_event_type(TouchEvent::TOUCH_POINT_START);
374 TouchEventPoint* point = event.add_touch_points();
375 point->set_id(0u);
377 InSequence s;
378 EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
379 .WillOnce(Return(1));
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));
388 id_to_flags[0u] = kCancelFlag;
389 EXPECT_CALL(
390 *delegate_mock,
391 InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
392 .WillOnce(Return(1));
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);
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>());
414 InSequence s;
415 EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
416 .WillOnce(Return(1));
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));
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));
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));
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));
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));
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));
463 TouchInjectorWin injector;
464 injector.SetInjectorDelegateForTest(delegate_mock.Pass());
465 EXPECT_TRUE(injector.Init());
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);
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);
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);
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);
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);
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);
514 } // namespace remoting