| 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
|
|
|