Index: ui/touch_selection/longpress_drag_selector_unittest.cc |
diff --git a/ui/touch_selection/longpress_drag_selector_unittest.cc b/ui/touch_selection/longpress_drag_selector_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8c126d8022bfd51019d1d573b55e665ca1c3a541 |
--- /dev/null |
+++ b/ui/touch_selection/longpress_drag_selector_unittest.cc |
@@ -0,0 +1,333 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/touch_selection/longpress_drag_selector.h" |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "ui/events/test/motion_event_test_utils.h" |
+ |
+using ui::test::MockMotionEvent; |
+ |
+namespace ui { |
+namespace { |
+ |
+const double kSlop = 10.; |
+ |
+} // namespace |
+ |
+class LongPressDragSelectorTest : public testing::Test, |
+ public LongPressDragSelectorClient { |
+ public: |
+ LongPressDragSelectorTest() |
+ : dragging_(false), active_state_changed_(false) {} |
+ |
+ ~LongPressDragSelectorTest() override {} |
+ |
+ void SetSelection(const gfx::PointF& start, const gfx::PointF& end) { |
+ selection_start_ = start; |
+ selection_end_ = end; |
+ } |
+ |
+ bool GetAndResetActiveStateChanged() { |
+ bool active_state_changed = active_state_changed_; |
+ active_state_changed_ = false; |
+ return active_state_changed; |
+ } |
+ |
+ bool IsDragging() const { return dragging_; } |
+ const gfx::PointF& DragPosition() const { return drag_position_; } |
+ |
+ // LongPressDragSelectorClient implementation. |
+ void OnDragBegin(const TouchSelectionDraggable& handler, |
+ const gfx::PointF& drag_position) override { |
+ dragging_ = true; |
+ drag_position_ = drag_position; |
+ } |
+ |
+ void OnDragUpdate(const TouchSelectionDraggable& handler, |
+ const gfx::PointF& drag_position) override { |
+ drag_position_ = drag_position; |
+ } |
+ |
+ void OnDragEnd(const TouchSelectionDraggable& handler) override { |
+ dragging_ = false; |
+ } |
+ |
+ bool IsWithinTapSlop(const gfx::Vector2dF& delta) const override { |
+ return delta.LengthSquared() < (kSlop * kSlop); |
+ } |
+ |
+ void OnLongPressDragActiveStateChanged() override { |
+ active_state_changed_ = true; |
+ } |
+ |
+ gfx::PointF GetSelectionStart() const override { return selection_start_; } |
+ |
+ gfx::PointF GetSelectionEnd() const override { return selection_end_; } |
+ |
+ private: |
+ bool dragging_; |
+ bool active_state_changed_; |
+ gfx::PointF drag_position_; |
+ |
+ gfx::PointF selection_start_; |
+ gfx::PointF selection_end_; |
+}; |
+ |
+TEST_F(LongPressDragSelectorTest, BasicDrag) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ // Activate a longpress-triggered selection. |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+ |
+ // Motion should not be consumed until a selection is detected. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ SetSelection(selection_start, selection_end); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Initiate drag motion. Note that the first move event after activation is |
+ // used to initialize the drag start anchor. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // The first slop exceeding motion will start the drag. As the motion is |
+ // downward, the end selection point should be moved. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_TRUE(IsDragging()); |
+ EXPECT_EQ(selection_end, DragPosition()); |
+ |
+ // Subsequent motion will extend the selection. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_TRUE(IsDragging()); |
+ EXPECT_EQ(selection_end + gfx::Vector2dF(0, kSlop), DragPosition()); |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 3))); |
+ EXPECT_TRUE(IsDragging()); |
+ EXPECT_EQ(selection_end + gfx::Vector2dF(0, kSlop * 2), DragPosition()); |
+ |
+ // Release the touch sequence, ending the drag. The selector will never |
+ // consume the start/end events, only move events after a longpress. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, BasicReverseDrag) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ // Activate a longpress-triggered selection. |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+ SetSelection(selection_start, selection_end); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Initiate drag motion. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // As the initial motion is leftward, toward the selection start, the |
+ // selection start should be the drag point. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, -kSlop, 0))); |
+ EXPECT_TRUE(IsDragging()); |
+ EXPECT_EQ(selection_start, DragPosition()); |
+ |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop))); |
+ EXPECT_TRUE(IsDragging()); |
+ EXPECT_EQ(selection_start + gfx::Vector2dF(kSlop, -kSlop), DragPosition()); |
+ |
+ // Release the touch sequence, ending the drag. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, NoActiveTouch) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Activate a longpress-triggered selection. |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); |
+ SetSelection(selection_start, selection_end); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Start a new touch sequence; it shouldn't initiate selection drag as there |
+ // was no active touch sequence when the longpress selection started. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_EQ(gfx::PointF(), DragPosition()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, NoLongPress) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ // Activate a selection without a preceding longpress. |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ SetSelection(selection_start, selection_end); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Touch movement should not initiate selection drag. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_EQ(gfx::PointF(), DragPosition()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, NoValidLongPress) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ SetSelection(selection_start, selection_end); |
+ |
+ // Activate a longpress-triggered selection, but at a time before the current |
+ // touch down event. |
+ selector.OnLongPressEvent( |
+ event.GetEventTime() - base::TimeDelta::FromSeconds(1), gfx::PointF()); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Activate a longpress-triggered selection, but at a place different than the |
+ // current touch down event. |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF(kSlop, 0)); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Touch movement should not initiate selection drag. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_EQ(gfx::PointF(), DragPosition()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, NoSelection) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ // Trigger a longpress. This will notify the client that detection is active, |
+ // but until there's a longpress no drag selection should occur. |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Touch movement should not initiate selection drag, as there is no active |
+ // selection. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_EQ(gfx::PointF(), DragPosition()); |
+ |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, NoDragMotion) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ // Activate a longpress-triggered selection. |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ SetSelection(selection_start, selection_end); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Touch movement within the slop region should not initiate selection drag. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop / 2))); |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop / 2))); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_EQ(gfx::PointF(), DragPosition()); |
+ |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+} |
+ |
+TEST_F(LongPressDragSelectorTest, SelectionDeactivated) { |
+ LongPressDragSelector selector(this); |
+ MockMotionEvent event; |
+ |
+ // Start a touch sequence. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); |
+ EXPECT_FALSE(GetAndResetActiveStateChanged()); |
+ |
+ // Activate a longpress-triggered selection. |
+ selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+ gfx::PointF selection_start(0, 10); |
+ gfx::PointF selection_end(10, 10); |
+ SetSelection(selection_start, selection_end); |
+ selector.OnSelectionActivated(); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Start a drag selection. |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_TRUE(IsDragging()); |
+ |
+ // Clearing the selection should force an end to the drag. |
+ selector.OnSelectionDeactivated(); |
+ EXPECT_TRUE(GetAndResetActiveStateChanged()); |
+ EXPECT_FALSE(IsDragging()); |
+ |
+ // Subsequent motion should not be consumed. |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); |
+ EXPECT_FALSE(IsDragging()); |
+ EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); |
+} |
+ |
+} // namespace ui |