Index: ui/touch_selection/touch_selection_controller_unittest.cc |
diff --git a/ui/touch_selection/touch_selection_controller_unittest.cc b/ui/touch_selection/touch_selection_controller_unittest.cc |
index 48e65a94f46119e611c04415f8e6a8cad3ea79ad..9003c4fb5e14ed900bf5bcbeb79e6c25d29554db 100644 |
--- a/ui/touch_selection/touch_selection_controller_unittest.cc |
+++ b/ui/touch_selection/touch_selection_controller_unittest.cc |
@@ -43,6 +43,21 @@ class MockTouchHandleDrawable : public TouchHandleDrawable { |
} // namespace |
+class TouchSelectionControllerTestApi { |
+ public: |
+ explicit TouchSelectionControllerTestApi(TouchSelectionController* controller) |
+ : controller_(controller) {} |
+ ~TouchSelectionControllerTestApi() {} |
+ |
+ bool GetStartVisible() const { return controller_->GetStartVisible(); } |
+ bool GetEndVisible() const { return controller_->GetEndVisible(); } |
+ |
+ private: |
+ TouchSelectionController* controller_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerTestApi); |
+}; |
+ |
class TouchSelectionControllerTest : public testing::Test, |
public TouchSelectionControllerClient { |
public: |
@@ -59,15 +74,7 @@ class TouchSelectionControllerTest : public testing::Test, |
// testing::Test implementation. |
void SetUp() override { |
- // Default touch selection controller is created with |
- // |show_on_tap_for_empty_editable| flag set to false. Use |
- // |AllowShowingOnTapForEmptyEditable()| function to override it. |
- bool show_on_tap_for_empty_editable = false; |
- controller_.reset(new TouchSelectionController( |
- this, |
- base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs), |
- kDefaulTapSlop, |
- show_on_tap_for_empty_editable)); |
+ controller_.reset(new TouchSelectionController(this, DefaultConfig())); |
} |
void TearDown() override { controller_.reset(); } |
@@ -109,12 +116,15 @@ class TouchSelectionControllerTest : public testing::Test, |
} |
void AllowShowingOnTapForEmptyEditable() { |
- bool show_on_tap_for_empty_editable = true; |
- controller_.reset(new TouchSelectionController( |
- this, |
- base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs), |
- kDefaulTapSlop, |
- show_on_tap_for_empty_editable)); |
+ TouchSelectionController::Config config = DefaultConfig(); |
+ config.show_on_tap_for_empty_editable = true; |
+ controller_.reset(new TouchSelectionController(this, config)); |
+ } |
+ |
+ void EnableLongPressDragSelection() { |
+ TouchSelectionController::Config config = DefaultConfig(); |
+ config.enable_longpress_drag_selection = true; |
+ controller_.reset(new TouchSelectionController(this, config)); |
} |
void SetAnimationEnabled(bool enabled) { animation_enabled_ = enabled; } |
@@ -150,7 +160,8 @@ class TouchSelectionControllerTest : public testing::Test, |
} |
void OnLongPressEvent() { |
- ASSERT_FALSE(controller().WillHandleLongPressEvent(kIgnoredPoint)); |
+ ASSERT_FALSE(controller().WillHandleLongPressEvent(base::TimeTicks(), |
+ kIgnoredPoint)); |
} |
void OnTapEvent() { |
@@ -207,6 +218,19 @@ class TouchSelectionControllerTest : public testing::Test, |
TouchSelectionController& controller() { return *controller_; } |
private: |
+ TouchSelectionController::Config DefaultConfig() { |
+ // Both |show_on_tap_for_empty_editable| and |
+ // |enable_longpress_drag_selection| are set to false by default, and should |
+ // be overriden for explicit testing. |
+ TouchSelectionController::Config config; |
+ config.tap_timeout = |
+ base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs); |
+ config.tap_slop = kDefaulTapSlop; |
+ config.show_on_tap_for_empty_editable = false; |
+ config.enable_longpress_drag_selection = false; |
+ return config; |
+ } |
+ |
gfx::PointF last_event_start_; |
gfx::PointF last_event_end_; |
gfx::PointF caret_position_; |
@@ -903,6 +927,8 @@ TEST_F(TouchSelectionControllerTest, Animation) { |
} |
TEST_F(TouchSelectionControllerTest, TemporarilyHidden) { |
+ TouchSelectionControllerTestApi test_controller(&controller()); |
+ |
OnTapEvent(); |
controller().OnSelectionEditable(true); |
@@ -911,20 +937,27 @@ TEST_F(TouchSelectionControllerTest, TemporarilyHidden) { |
bool visible = true; |
ChangeInsertion(insertion_rect, visible); |
EXPECT_FALSE(GetAndResetNeedsAnimate()); |
+ EXPECT_TRUE(test_controller.GetStartVisible()); |
+ EXPECT_TRUE(test_controller.GetEndVisible()); |
controller().SetTemporarilyHidden(true); |
EXPECT_TRUE(GetAndResetNeedsAnimate()); |
+ EXPECT_FALSE(test_controller.GetStartVisible()); |
+ EXPECT_FALSE(test_controller.GetEndVisible()); |
visible = false; |
ChangeInsertion(insertion_rect, visible); |
EXPECT_FALSE(GetAndResetNeedsAnimate()); |
+ EXPECT_FALSE(test_controller.GetStartVisible()); |
visible = true; |
ChangeInsertion(insertion_rect, visible); |
EXPECT_FALSE(GetAndResetNeedsAnimate()); |
+ EXPECT_FALSE(test_controller.GetStartVisible()); |
controller().SetTemporarilyHidden(false); |
EXPECT_TRUE(GetAndResetNeedsAnimate()); |
+ EXPECT_TRUE(test_controller.GetStartVisible()); |
} |
TEST_F(TouchSelectionControllerTest, SelectionClearOnTap) { |
@@ -1043,12 +1076,146 @@ TEST_F(TouchSelectionControllerTest, HandlesShowOnLongPressInsideRect) { |
EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
// A point outside the rect should not be handled. |
- EXPECT_FALSE(controller().WillHandleLongPressEvent(outer_point)); |
+ EXPECT_FALSE( |
+ controller().WillHandleLongPressEvent(base::TimeTicks(), outer_point)); |
EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
// A point inside the rect should be handled. |
- EXPECT_TRUE(controller().WillHandleLongPressEvent(inner_point)); |
+ EXPECT_TRUE( |
+ controller().WillHandleLongPressEvent(base::TimeTicks(), inner_point)); |
+ EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); |
+} |
+ |
+TEST_F(TouchSelectionControllerTest, LongPressDrag) { |
+ EnableLongPressDragSelection(); |
+ TouchSelectionControllerTestApi test_controller(&controller()); |
+ |
+ gfx::RectF start_rect(-50, 0, 0, 10); |
+ gfx::RectF end_rect(50, 0, 0, 10); |
+ bool visible = true; |
+ |
+ // Start a touch sequence. |
+ MockMotionEvent event; |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ |
+ // Activate a longpress-triggered selection. |
+ OnLongPressEvent(); |
+ ChangeSelection(start_rect, visible, end_rect, visible); |
EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); |
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventStart()); |
+ |
+ // The handles should remain invisible while the touch release and longpress |
+ // drag gesture are pending. |
+ EXPECT_FALSE(test_controller.GetStartVisible()); |
+ EXPECT_FALSE(test_controller.GetEndVisible()); |
+ |
+ // The selection coordinates should reflect the drag movement. |
+ gfx::PointF fixed_offset = start_rect.CenterPoint(); |
+ gfx::PointF end_offset = end_rect.CenterPoint(); |
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
+ |
+ EXPECT_TRUE( |
+ controller().WillHandleTouchEvent(event.MovePoint(0, 0, kDefaulTapSlop))); |
+ EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED)); |
+ EXPECT_EQ(fixed_offset, GetLastSelectionStart()); |
+ EXPECT_EQ(end_offset, GetLastSelectionEnd()); |
+ |
+ // Movement after the start of drag will be relative to the moved endpoint. |
+ EXPECT_TRUE(controller().WillHandleTouchEvent( |
+ event.MovePoint(0, 0, 2 * kDefaulTapSlop))); |
+ EXPECT_TRUE(GetAndResetSelectionMoved()); |
+ EXPECT_EQ(end_offset + gfx::Vector2dF(0, kDefaulTapSlop), |
+ GetLastSelectionEnd()); |
+ |
+ EXPECT_TRUE(controller().WillHandleTouchEvent( |
+ event.MovePoint(0, kDefaulTapSlop, 2 * kDefaulTapSlop))); |
+ EXPECT_TRUE(GetAndResetSelectionMoved()); |
+ EXPECT_EQ(end_offset + gfx::Vector2dF(kDefaulTapSlop, kDefaulTapSlop), |
+ GetLastSelectionEnd()); |
+ |
+ EXPECT_TRUE(controller().WillHandleTouchEvent( |
+ event.MovePoint(0, 2 * kDefaulTapSlop, 2 * kDefaulTapSlop))); |
+ EXPECT_TRUE(GetAndResetSelectionMoved()); |
+ EXPECT_EQ(end_offset + gfx::Vector2dF(2 * kDefaulTapSlop, kDefaulTapSlop), |
+ GetLastSelectionEnd()); |
+ |
+ // The handles should still be hidden. |
+ EXPECT_FALSE(test_controller.GetStartVisible()); |
+ EXPECT_FALSE(test_controller.GetEndVisible()); |
+ |
+ // Releasing the touch sequence should end the drag and show the handles. |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED)); |
+ EXPECT_TRUE(test_controller.GetStartVisible()); |
+ EXPECT_TRUE(test_controller.GetEndVisible()); |
+} |
+ |
+TEST_F(TouchSelectionControllerTest, LongPressNoDrag) { |
+ EnableLongPressDragSelection(); |
+ TouchSelectionControllerTestApi test_controller(&controller()); |
+ |
+ gfx::RectF start_rect(-50, 0, 0, 10); |
+ gfx::RectF end_rect(50, 0, 0, 10); |
+ bool visible = true; |
+ |
+ // Start a touch sequence. |
+ MockMotionEvent event; |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ |
+ // Activate a longpress-triggered selection. |
+ OnLongPressEvent(); |
+ ChangeSelection(start_rect, visible, end_rect, visible); |
+ EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); |
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventStart()); |
+ |
+ // The handles should remain invisible while the touch release and longpress |
+ // drag gesture are pending. |
+ EXPECT_FALSE(test_controller.GetStartVisible()); |
+ EXPECT_FALSE(test_controller.GetEndVisible()); |
+ |
+ // If no drag movement occurs, the handles should reappear after the touch |
+ // is released. |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
+ EXPECT_TRUE(test_controller.GetStartVisible()); |
+ EXPECT_TRUE(test_controller.GetEndVisible()); |
+} |
+ |
+TEST_F(TouchSelectionControllerTest, NoLongPressDragIfDisabled) { |
+ // The TouchSelectionController disables longpress drag selection by default. |
+ TouchSelectionControllerTestApi test_controller(&controller()); |
+ |
+ gfx::RectF start_rect(-50, 0, 0, 10); |
+ gfx::RectF end_rect(50, 0, 0, 10); |
+ bool visible = true; |
+ |
+ // Start a touch sequence. |
+ MockMotionEvent event; |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ |
+ // Activate a longpress-triggered selection. |
+ OnLongPressEvent(); |
+ ChangeSelection(start_rect, visible, end_rect, visible); |
+ EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); |
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventStart()); |
+ EXPECT_TRUE(test_controller.GetStartVisible()); |
+ EXPECT_TRUE(test_controller.GetEndVisible()); |
+ |
+ // Subsequent motion of the same touch sequence after longpress shouldn't |
+ // trigger drag selection. |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
+ |
+ EXPECT_FALSE(controller().WillHandleTouchEvent( |
+ event.MovePoint(0, 0, kDefaulTapSlop * 10))); |
+ EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
+ |
+ // Releasing the touch sequence should have no effect. |
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_THAT(GetAndResetEvents(), IsEmpty()); |
+ EXPECT_TRUE(test_controller.GetStartVisible()); |
+ EXPECT_TRUE(test_controller.GetEndVisible()); |
} |
TEST_F(TouchSelectionControllerTest, RectBetweenBounds) { |