OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h" | 5 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 namespace { | 48 namespace { |
49 | 49 |
50 const int kFlushInputRateInMs = 16; | 50 const int kFlushInputRateInMs = 16; |
51 const int kPointerAssumedStoppedTimeMs = 43; | 51 const int kPointerAssumedStoppedTimeMs = 43; |
52 const float kTouchSlopInDips = 7.0f; | 52 const float kTouchSlopInDips = 7.0f; |
53 const float kMinScalingSpanInDips = 27.5f; | 53 const float kMinScalingSpanInDips = 27.5f; |
54 const int kTouchPointersLength = 16; | 54 const int kTouchPointersLength = 16; |
55 | 55 |
56 enum TouchGestureType { TOUCH_SCROLL, TOUCH_DRAG }; | 56 enum TouchGestureType { TOUCH_SCROLL, TOUCH_DRAG }; |
57 | 57 |
| 58 WebTouchPoint::State ToWebTouchPointState( |
| 59 SyntheticPointerActionParams::PointerActionType action_type) { |
| 60 switch (action_type) { |
| 61 case SyntheticPointerActionParams::PointerActionType::PRESS: |
| 62 return WebTouchPoint::StatePressed; |
| 63 case SyntheticPointerActionParams::PointerActionType::MOVE: |
| 64 return WebTouchPoint::StateMoved; |
| 65 case SyntheticPointerActionParams::PointerActionType::RELEASE: |
| 66 return WebTouchPoint::StateReleased; |
| 67 case SyntheticPointerActionParams::PointerActionType::IDLE: |
| 68 return WebTouchPoint::StateStationary; |
| 69 case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED: |
| 70 NOTREACHED() |
| 71 << "Invalid SyntheticPointerActionParams::PointerActionType."; |
| 72 return WebTouchPoint::StateUndefined; |
| 73 } |
| 74 NOTREACHED() << "Invalid SyntheticPointerActionParams::PointerActionType."; |
| 75 return WebTouchPoint::StateUndefined; |
| 76 } |
| 77 |
| 78 WebInputEvent::Type ToWebMouseEventType( |
| 79 SyntheticPointerActionParams::PointerActionType action_type) { |
| 80 switch (action_type) { |
| 81 case SyntheticPointerActionParams::PointerActionType::PRESS: |
| 82 return WebInputEvent::MouseDown; |
| 83 case SyntheticPointerActionParams::PointerActionType::MOVE: |
| 84 return WebInputEvent::MouseMove; |
| 85 case SyntheticPointerActionParams::PointerActionType::RELEASE: |
| 86 return WebInputEvent::MouseUp; |
| 87 case SyntheticPointerActionParams::PointerActionType::IDLE: |
| 88 case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED: |
| 89 NOTREACHED() |
| 90 << "Invalid SyntheticPointerActionParams::PointerActionType."; |
| 91 return WebInputEvent::Undefined; |
| 92 } |
| 93 NOTREACHED() << "Invalid SyntheticPointerActionParams::PointerActionType."; |
| 94 return WebInputEvent::Undefined; |
| 95 } |
| 96 |
58 class MockSyntheticGesture : public SyntheticGesture { | 97 class MockSyntheticGesture : public SyntheticGesture { |
59 public: | 98 public: |
60 MockSyntheticGesture(bool* finished, int num_steps) | 99 MockSyntheticGesture(bool* finished, int num_steps) |
61 : finished_(finished), | 100 : finished_(finished), |
62 num_steps_(num_steps), | 101 num_steps_(num_steps), |
63 step_count_(0) { | 102 step_count_(0) { |
64 *finished_ = false; | 103 *finished_ = false; |
65 } | 104 } |
66 ~MockSyntheticGesture() override {} | 105 ~MockSyntheticGesture() override {} |
67 | 106 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 break; | 506 break; |
468 case FINISHED: | 507 case FINISHED: |
469 EXPECT_FALSE(true); | 508 EXPECT_FALSE(true); |
470 break; | 509 break; |
471 } | 510 } |
472 } | 511 } |
473 }; | 512 }; |
474 | 513 |
475 class MockSyntheticPointerActionTarget : public MockSyntheticGestureTarget { | 514 class MockSyntheticPointerActionTarget : public MockSyntheticGestureTarget { |
476 public: | 515 public: |
477 MockSyntheticPointerActionTarget() {} | 516 MockSyntheticPointerActionTarget() : num_actions_dispatched_(0) {} |
478 ~MockSyntheticPointerActionTarget() override {} | 517 ~MockSyntheticPointerActionTarget() override {} |
479 | 518 |
480 gfx::PointF positions(int index) const { return positions_[index]; } | |
481 int indexes(int index) const { return indexes_[index]; } | |
482 WebTouchPoint::State states(int index) { return states_[index]; } | |
483 unsigned touch_length() const { return touch_length_; } | |
484 WebInputEvent::Type type() const { return type_; } | 519 WebInputEvent::Type type() const { return type_; } |
| 520 int num_actions_dispatched() const { return num_actions_dispatched_; } |
| 521 void reset_num_actions_dispatched() { num_actions_dispatched_ = 0; } |
485 | 522 |
486 protected: | 523 protected: |
487 gfx::PointF positions_[kTouchPointersLength]; | |
488 unsigned touch_length_; | |
489 int indexes_[kTouchPointersLength]; | |
490 WebTouchPoint::State states_[kTouchPointersLength]; | |
491 WebInputEvent::Type type_; | 524 WebInputEvent::Type type_; |
| 525 int num_actions_dispatched_; |
492 }; | 526 }; |
493 | 527 |
494 class MockSyntheticPointerTouchActionTarget | 528 class MockSyntheticPointerTouchActionTarget |
495 : public MockSyntheticPointerActionTarget { | 529 : public MockSyntheticPointerActionTarget { |
496 public: | 530 public: |
497 MockSyntheticPointerTouchActionTarget() {} | 531 MockSyntheticPointerTouchActionTarget() {} |
498 ~MockSyntheticPointerTouchActionTarget() override {} | 532 ~MockSyntheticPointerTouchActionTarget() override {} |
499 | 533 |
500 void DispatchInputEventToPlatform(const WebInputEvent& event) override { | 534 void DispatchInputEventToPlatform(const WebInputEvent& event) override { |
501 ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type)); | 535 DCHECK(WebInputEvent::isTouchEventType(event.type)); |
502 const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); | 536 const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); |
503 type_ = touch_event.type; | 537 type_ = touch_event.type; |
504 for (size_t i = 0; i < touch_event.touchesLength; ++i) { | 538 for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) { |
505 indexes_[i] = touch_event.touches[i].id; | 539 indexes_[i] = touch_event.touches[i].id; |
506 positions_[i] = gfx::PointF(touch_event.touches[i].position); | 540 positions_[i] = gfx::PointF(touch_event.touches[i].position); |
507 states_[i] = touch_event.touches[i].state; | 541 states_[i] = touch_event.touches[i].state; |
508 } | 542 } |
509 touch_length_ = touch_event.touchesLength; | 543 touch_length_ = touch_event.touchesLength; |
| 544 num_actions_dispatched_++; |
510 } | 545 } |
| 546 |
| 547 testing::AssertionResult SyntheticTouchActionDispatchedCorrectly( |
| 548 const SyntheticPointerActionParams& param, |
| 549 int index) { |
| 550 if (param.pointer_action_type() == |
| 551 SyntheticPointerActionParams::PointerActionType::PRESS || |
| 552 param.pointer_action_type() == |
| 553 SyntheticPointerActionParams::PointerActionType::MOVE) { |
| 554 if (indexes_[index] != param.index()) { |
| 555 return testing::AssertionFailure() |
| 556 << "Pointer index at index " << index << " was " |
| 557 << indexes_[index] << ", expected " << param.index() << "."; |
| 558 } |
| 559 |
| 560 if (positions_[index] != param.position()) { |
| 561 return testing::AssertionFailure() |
| 562 << "Pointer position at index " << index << " was " |
| 563 << positions_[index].ToString() << ", expected " |
| 564 << param.position().ToString() << "."; |
| 565 } |
| 566 } |
| 567 |
| 568 if (states_[index] != ToWebTouchPointState(param.pointer_action_type())) { |
| 569 return testing::AssertionFailure() |
| 570 << "Pointer states at index " << index << " was " << states_[index] |
| 571 << ", expected " |
| 572 << ToWebTouchPointState(param.pointer_action_type()) << "."; |
| 573 } |
| 574 return testing::AssertionSuccess(); |
| 575 } |
| 576 |
| 577 testing::AssertionResult SyntheticTouchActionListDispatchedCorrectly( |
| 578 const std::vector<SyntheticPointerActionParams>& params_list) { |
| 579 if (touch_length_ != params_list.size()) { |
| 580 return testing::AssertionFailure() << "Touch point length was " |
| 581 << touch_length_ << ", expected " |
| 582 << params_list.size() << "."; |
| 583 } |
| 584 |
| 585 testing::AssertionResult result = testing::AssertionSuccess(); |
| 586 for (size_t i = 0; i < params_list.size(); ++i) { |
| 587 result = SyntheticTouchActionDispatchedCorrectly(params_list[i], |
| 588 params_list[i].index()); |
| 589 if (result == testing::AssertionFailure()) |
| 590 return result; |
| 591 } |
| 592 return testing::AssertionSuccess(); |
| 593 } |
| 594 |
| 595 private: |
| 596 gfx::PointF positions_[kTouchPointersLength]; |
| 597 unsigned touch_length_; |
| 598 int indexes_[kTouchPointersLength]; |
| 599 WebTouchPoint::State states_[kTouchPointersLength]; |
| 600 }; |
| 601 |
| 602 class MockSyntheticPointerMouseActionTarget |
| 603 : public MockSyntheticPointerActionTarget { |
| 604 public: |
| 605 MockSyntheticPointerMouseActionTarget() {} |
| 606 ~MockSyntheticPointerMouseActionTarget() override {} |
| 607 |
| 608 void DispatchInputEventToPlatform(const WebInputEvent& event) override { |
| 609 ASSERT_TRUE(WebInputEvent::isMouseEventType(event.type)); |
| 610 const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event); |
| 611 type_ = mouse_event.type; |
| 612 position_ = gfx::PointF(mouse_event.x, mouse_event.y); |
| 613 clickCount_ = mouse_event.clickCount; |
| 614 button_ = mouse_event.button; |
| 615 num_actions_dispatched_++; |
| 616 } |
| 617 |
| 618 testing::AssertionResult SyntheticMouseActionDispatchedCorrectly( |
| 619 const SyntheticPointerActionParams& param, |
| 620 int click_count) { |
| 621 if (type_ != ToWebMouseEventType(param.pointer_action_type())) { |
| 622 return testing::AssertionFailure() |
| 623 << "Pointer type was " << WebInputEvent::GetName(type_) |
| 624 << ", expected " << WebInputEvent::GetName(ToWebMouseEventType( |
| 625 param.pointer_action_type())) << "."; |
| 626 } |
| 627 |
| 628 if (clickCount_ != click_count) { |
| 629 return testing::AssertionFailure() << "Pointer click count was " |
| 630 << clickCount_ << ", expected " |
| 631 << click_count << "."; |
| 632 } |
| 633 |
| 634 if (clickCount_ == 1 && button_ != WebMouseEvent::Button::Left) { |
| 635 return testing::AssertionFailure() |
| 636 << "Pointer button was " << (int)button_ << ", expected " |
| 637 << (int)WebMouseEvent::Button::Left << "."; |
| 638 } |
| 639 |
| 640 if (clickCount_ == 0 && button_ != WebMouseEvent::Button::NoButton) { |
| 641 return testing::AssertionFailure() |
| 642 << "Pointer button was " << (int)button_ << ", expected " |
| 643 << (int)WebMouseEvent::Button::NoButton << "."; |
| 644 } |
| 645 |
| 646 if ((param.pointer_action_type() == |
| 647 SyntheticPointerActionParams::PointerActionType::PRESS || |
| 648 param.pointer_action_type() == |
| 649 SyntheticPointerActionParams::PointerActionType::MOVE) && |
| 650 position_ != param.position()) { |
| 651 return testing::AssertionFailure() |
| 652 << "Pointer position was " << position_.ToString() << ", expected " |
| 653 << param.position().ToString() << "."; |
| 654 } |
| 655 return testing::AssertionSuccess(); |
| 656 } |
| 657 |
| 658 private: |
| 659 gfx::PointF position_; |
| 660 int clickCount_; |
| 661 WebMouseEvent::Button button_; |
511 }; | 662 }; |
512 | 663 |
513 class SyntheticGestureControllerTestBase { | 664 class SyntheticGestureControllerTestBase { |
514 public: | 665 public: |
515 SyntheticGestureControllerTestBase() {} | 666 SyntheticGestureControllerTestBase() {} |
516 ~SyntheticGestureControllerTestBase() {} | 667 ~SyntheticGestureControllerTestBase() {} |
517 | 668 |
518 protected: | 669 protected: |
519 template<typename MockGestureTarget> | 670 template<typename MockGestureTarget> |
520 void CreateControllerAndTarget() { | 671 void CreateControllerAndTarget() { |
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 static_cast<MockSyntheticTapMouseTarget*>(target_); | 1615 static_cast<MockSyntheticTapMouseTarget*>(target_); |
1465 EXPECT_EQ(1, num_success_); | 1616 EXPECT_EQ(1, num_success_); |
1466 EXPECT_EQ(0, num_failure_); | 1617 EXPECT_EQ(0, num_failure_); |
1467 EXPECT_TRUE(tap_target->GestureFinished()); | 1618 EXPECT_TRUE(tap_target->GestureFinished()); |
1468 EXPECT_EQ(tap_target->position(), params.position); | 1619 EXPECT_EQ(tap_target->position(), params.position); |
1469 EXPECT_EQ(tap_target->GetDuration().InMilliseconds(), params.duration_ms); | 1620 EXPECT_EQ(tap_target->GetDuration().InMilliseconds(), params.duration_ms); |
1470 EXPECT_GE(GetTotalTime(), | 1621 EXPECT_GE(GetTotalTime(), |
1471 base::TimeDelta::FromMilliseconds(params.duration_ms)); | 1622 base::TimeDelta::FromMilliseconds(params.duration_ms)); |
1472 } | 1623 } |
1473 | 1624 |
| 1625 TEST_F(SyntheticGestureControllerTest, PointerTouchAction) { |
| 1626 CreateControllerAndTarget<MockSyntheticPointerTouchActionTarget>(); |
| 1627 |
| 1628 // First, send two touch presses for finger 0 and finger 1. |
| 1629 SyntheticPointerActionListParams::ParamList param_list; |
| 1630 SyntheticPointerActionParams param0 = SyntheticPointerActionParams( |
| 1631 SyntheticPointerActionParams::PointerActionType::PRESS); |
| 1632 SyntheticPointerActionParams param1 = SyntheticPointerActionParams( |
| 1633 SyntheticPointerActionParams::PointerActionType::PRESS); |
| 1634 param0.set_position(gfx::PointF(54, 89)); |
| 1635 param0.set_index(0); |
| 1636 param1.set_position(gfx::PointF(79, 132)); |
| 1637 param1.set_index(1); |
| 1638 param_list.push_back(param0); |
| 1639 param_list.push_back(param1); |
| 1640 SyntheticPointerActionListParams params(param_list); |
| 1641 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; |
| 1642 std::unique_ptr<SyntheticPointerAction> gesture( |
| 1643 new SyntheticPointerAction(params)); |
| 1644 QueueSyntheticGesture(std::move(gesture)); |
| 1645 FlushInputUntilComplete(); |
| 1646 |
| 1647 MockSyntheticPointerTouchActionTarget* pointer_touch_target = |
| 1648 static_cast<MockSyntheticPointerTouchActionTarget*>(target_); |
| 1649 EXPECT_EQ(1, num_success_); |
| 1650 EXPECT_EQ(0, num_failure_); |
| 1651 EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 1); |
| 1652 EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly( |
| 1653 param_list)); |
| 1654 |
| 1655 // Second, send a touch release for finger 0, a touch move for finger 1. |
| 1656 param0.set_pointer_action_type( |
| 1657 SyntheticPointerActionParams::PointerActionType::RELEASE); |
| 1658 param1.set_pointer_action_type( |
| 1659 SyntheticPointerActionParams::PointerActionType::MOVE); |
| 1660 param1.set_position(gfx::PointF(183, 239)); |
| 1661 param_list.clear(); |
| 1662 param_list.push_back(param0); |
| 1663 param_list.push_back(param1); |
| 1664 params.PushPointerActionParamsList(param_list); |
| 1665 gesture.reset(new SyntheticPointerAction(params)); |
| 1666 QueueSyntheticGesture(std::move(gesture)); |
| 1667 pointer_touch_target->reset_num_actions_dispatched(); |
| 1668 FlushInputUntilComplete(); |
| 1669 |
| 1670 EXPECT_EQ(2, num_success_); |
| 1671 EXPECT_EQ(0, num_failure_); |
| 1672 EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 2); |
| 1673 EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly( |
| 1674 param_list)); |
| 1675 |
| 1676 // Third, send a touch release for finger 1. |
| 1677 param1.set_pointer_action_type( |
| 1678 SyntheticPointerActionParams::PointerActionType::RELEASE); |
| 1679 param_list.clear(); |
| 1680 param_list.push_back(param1); |
| 1681 params.PushPointerActionParamsList(param_list); |
| 1682 gesture.reset(new SyntheticPointerAction(params)); |
| 1683 QueueSyntheticGesture(std::move(gesture)); |
| 1684 pointer_touch_target->reset_num_actions_dispatched(); |
| 1685 FlushInputUntilComplete(); |
| 1686 |
| 1687 EXPECT_EQ(3, num_success_); |
| 1688 EXPECT_EQ(0, num_failure_); |
| 1689 EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 3); |
| 1690 EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly( |
| 1691 param_list)); |
| 1692 } |
| 1693 |
| 1694 TEST_F(SyntheticGestureControllerTest, PointerMouseAction) { |
| 1695 CreateControllerAndTarget<MockSyntheticPointerMouseActionTarget>(); |
| 1696 |
| 1697 // First, send a mouse move. |
| 1698 SyntheticPointerActionListParams::ParamList param_list; |
| 1699 SyntheticPointerActionParams param = SyntheticPointerActionParams( |
| 1700 SyntheticPointerActionParams::PointerActionType::MOVE); |
| 1701 |
| 1702 param.set_position(gfx::PointF(54, 89)); |
| 1703 SyntheticPointerActionListParams params; |
| 1704 params.PushPointerActionParams(param); |
| 1705 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; |
| 1706 std::unique_ptr<SyntheticPointerAction> gesture( |
| 1707 new SyntheticPointerAction(params)); |
| 1708 QueueSyntheticGesture(std::move(gesture)); |
| 1709 FlushInputUntilComplete(); |
| 1710 |
| 1711 MockSyntheticPointerMouseActionTarget* pointer_mouse_target = |
| 1712 static_cast<MockSyntheticPointerMouseActionTarget*>(target_); |
| 1713 EXPECT_EQ(1, num_success_); |
| 1714 EXPECT_EQ(0, num_failure_); |
| 1715 EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 1); |
| 1716 EXPECT_TRUE( |
| 1717 pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 0)); |
| 1718 |
| 1719 // Second, send a mouse press. |
| 1720 param.set_pointer_action_type( |
| 1721 SyntheticPointerActionParams::PointerActionType::PRESS); |
| 1722 param.set_position(gfx::PointF(183, 239)); |
| 1723 params.PushPointerActionParams(param); |
| 1724 gesture.reset(new SyntheticPointerAction(params)); |
| 1725 QueueSyntheticGesture(std::move(gesture)); |
| 1726 pointer_mouse_target->reset_num_actions_dispatched(); |
| 1727 FlushInputUntilComplete(); |
| 1728 |
| 1729 EXPECT_EQ(2, num_success_); |
| 1730 EXPECT_EQ(0, num_failure_); |
| 1731 EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 2); |
| 1732 EXPECT_TRUE( |
| 1733 pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1)); |
| 1734 |
| 1735 // Third, send a mouse move. |
| 1736 param.set_pointer_action_type( |
| 1737 SyntheticPointerActionParams::PointerActionType::MOVE); |
| 1738 param.set_position(gfx::PointF(254, 279)); |
| 1739 params.PushPointerActionParams(param); |
| 1740 gesture.reset(new SyntheticPointerAction(params)); |
| 1741 QueueSyntheticGesture(std::move(gesture)); |
| 1742 pointer_mouse_target->reset_num_actions_dispatched(); |
| 1743 FlushInputUntilComplete(); |
| 1744 |
| 1745 EXPECT_EQ(3, num_success_); |
| 1746 EXPECT_EQ(0, num_failure_); |
| 1747 EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 3); |
| 1748 EXPECT_TRUE( |
| 1749 pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1)); |
| 1750 |
| 1751 // Fourth, send a mouse release. |
| 1752 param.set_pointer_action_type( |
| 1753 SyntheticPointerActionParams::PointerActionType::RELEASE); |
| 1754 params.PushPointerActionParams(param); |
| 1755 gesture.reset(new SyntheticPointerAction(params)); |
| 1756 QueueSyntheticGesture(std::move(gesture)); |
| 1757 pointer_mouse_target->reset_num_actions_dispatched(); |
| 1758 FlushInputUntilComplete(); |
| 1759 |
| 1760 EXPECT_EQ(4, num_success_); |
| 1761 EXPECT_EQ(0, num_failure_); |
| 1762 EXPECT_EQ(pointer_mouse_target->num_actions_dispatched(), 4); |
| 1763 EXPECT_TRUE( |
| 1764 pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1)); |
| 1765 } |
| 1766 |
1474 } // namespace | 1767 } // namespace |
1475 | 1768 |
1476 } // namespace content | 1769 } // namespace content |
OLD | NEW |