MD Downloads: prevent search text from overlapping with the cancel search (X)
[chromium-blink-merge.git] / ui / touch_selection / longpress_drag_selector_unittest.cc
blob885943957b65b6f075e2538509ed9f52e642c3f2
1 // Copyright 2014 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 "ui/touch_selection/longpress_drag_selector.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/events/test/motion_event_test_utils.h"
10 using ui::test::MockMotionEvent;
12 namespace ui {
13 namespace {
15 const double kSlop = 10.;
17 } // namespace
19 class LongPressDragSelectorTest : public testing::Test,
20 public LongPressDragSelectorClient {
21 public:
22 LongPressDragSelectorTest()
23 : dragging_(false), active_state_changed_(false) {}
25 ~LongPressDragSelectorTest() override {}
27 void SetSelection(const gfx::PointF& start, const gfx::PointF& end) {
28 selection_start_ = start;
29 selection_end_ = end;
32 bool GetAndResetActiveStateChanged() {
33 bool active_state_changed = active_state_changed_;
34 active_state_changed_ = false;
35 return active_state_changed;
38 bool IsDragging() const { return dragging_; }
39 const gfx::PointF& DragPosition() const { return drag_position_; }
41 // LongPressDragSelectorClient implementation.
42 void OnDragBegin(const TouchSelectionDraggable& handler,
43 const gfx::PointF& drag_position) override {
44 dragging_ = true;
45 drag_position_ = drag_position;
48 void OnDragUpdate(const TouchSelectionDraggable& handler,
49 const gfx::PointF& drag_position) override {
50 drag_position_ = drag_position;
53 void OnDragEnd(const TouchSelectionDraggable& handler) override {
54 dragging_ = false;
57 bool IsWithinTapSlop(const gfx::Vector2dF& delta) const override {
58 return delta.LengthSquared() < (kSlop * kSlop);
61 void OnLongPressDragActiveStateChanged() override {
62 active_state_changed_ = true;
65 gfx::PointF GetSelectionStart() const override { return selection_start_; }
67 gfx::PointF GetSelectionEnd() const override { return selection_end_; }
69 private:
70 bool dragging_;
71 bool active_state_changed_;
72 gfx::PointF drag_position_;
74 gfx::PointF selection_start_;
75 gfx::PointF selection_end_;
78 TEST_F(LongPressDragSelectorTest, BasicDrag) {
79 LongPressDragSelector selector(this);
80 MockMotionEvent event;
82 // Start a touch sequence.
83 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
84 EXPECT_FALSE(GetAndResetActiveStateChanged());
86 // Activate a longpress-triggered selection.
87 gfx::PointF selection_start(0, 10);
88 gfx::PointF selection_end(10, 10);
89 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
90 EXPECT_TRUE(GetAndResetActiveStateChanged());
92 // Motion should not be consumed until a selection is detected.
93 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
94 SetSelection(selection_start, selection_end);
95 selector.OnSelectionActivated();
96 EXPECT_FALSE(IsDragging());
98 // Initiate drag motion. Note that the first move event after activation is
99 // used to initialize the drag start anchor.
100 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
101 EXPECT_FALSE(IsDragging());
103 // The first slop exceeding motion will start the drag. As the motion is
104 // downward, the end selection point should be moved.
105 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
106 EXPECT_TRUE(IsDragging());
107 EXPECT_EQ(selection_end, DragPosition());
109 // Subsequent motion will extend the selection.
110 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
111 EXPECT_TRUE(IsDragging());
112 EXPECT_EQ(selection_end + gfx::Vector2dF(0, kSlop), DragPosition());
113 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 3)));
114 EXPECT_TRUE(IsDragging());
115 EXPECT_EQ(selection_end + gfx::Vector2dF(0, kSlop * 2), DragPosition());
117 // Release the touch sequence, ending the drag. The selector will never
118 // consume the start/end events, only move events after a longpress.
119 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
120 EXPECT_FALSE(IsDragging());
121 EXPECT_TRUE(GetAndResetActiveStateChanged());
124 TEST_F(LongPressDragSelectorTest, BasicReverseDrag) {
125 LongPressDragSelector selector(this);
126 MockMotionEvent event;
128 // Start a touch sequence.
129 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
130 EXPECT_FALSE(GetAndResetActiveStateChanged());
132 // Activate a longpress-triggered selection.
133 gfx::PointF selection_start(0, 10);
134 gfx::PointF selection_end(10, 10);
135 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
136 EXPECT_TRUE(GetAndResetActiveStateChanged());
137 SetSelection(selection_start, selection_end);
138 selector.OnSelectionActivated();
139 EXPECT_FALSE(IsDragging());
141 // Initiate drag motion.
142 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 5, 0)));
143 EXPECT_FALSE(IsDragging());
145 // As the initial motion is leftward, toward the selection start, the
146 // selection start should be the drag point.
147 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, -kSlop, 0)));
148 EXPECT_TRUE(IsDragging());
149 EXPECT_EQ(selection_start, DragPosition());
151 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop)));
152 EXPECT_TRUE(IsDragging());
153 EXPECT_EQ(selection_start + gfx::Vector2dF(kSlop, -kSlop), DragPosition());
155 // Release the touch sequence, ending the drag.
156 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
157 EXPECT_FALSE(IsDragging());
158 EXPECT_TRUE(GetAndResetActiveStateChanged());
161 TEST_F(LongPressDragSelectorTest, NoActiveTouch) {
162 LongPressDragSelector selector(this);
163 MockMotionEvent event;
165 // Activate a longpress-triggered selection.
166 gfx::PointF selection_start(0, 10);
167 gfx::PointF selection_end(10, 10);
168 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
169 SetSelection(selection_start, selection_end);
170 selector.OnSelectionActivated();
171 EXPECT_FALSE(GetAndResetActiveStateChanged());
172 EXPECT_FALSE(IsDragging());
174 // Start a new touch sequence; it shouldn't initiate selection drag as there
175 // was no active touch sequence when the longpress selection started.
176 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
177 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
178 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
179 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
180 EXPECT_FALSE(IsDragging());
181 EXPECT_EQ(gfx::PointF(), DragPosition());
184 TEST_F(LongPressDragSelectorTest, NoLongPress) {
185 LongPressDragSelector selector(this);
186 MockMotionEvent event;
188 // Start a touch sequence.
189 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
190 EXPECT_FALSE(GetAndResetActiveStateChanged());
192 // Activate a selection without a preceding longpress.
193 gfx::PointF selection_start(0, 10);
194 gfx::PointF selection_end(10, 10);
195 SetSelection(selection_start, selection_end);
196 selector.OnSelectionActivated();
197 EXPECT_FALSE(GetAndResetActiveStateChanged());
198 EXPECT_FALSE(IsDragging());
200 // Touch movement should not initiate selection drag.
201 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
202 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
203 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
204 EXPECT_FALSE(IsDragging());
205 EXPECT_EQ(gfx::PointF(), DragPosition());
208 TEST_F(LongPressDragSelectorTest, NoValidLongPress) {
209 LongPressDragSelector selector(this);
210 MockMotionEvent event;
212 // Start a touch sequence.
213 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
214 EXPECT_FALSE(GetAndResetActiveStateChanged());
216 gfx::PointF selection_start(0, 10);
217 gfx::PointF selection_end(10, 10);
218 SetSelection(selection_start, selection_end);
220 // Activate a longpress-triggered selection, but at a time before the current
221 // touch down event.
222 selector.OnLongPressEvent(
223 event.GetEventTime() - base::TimeDelta::FromSeconds(1), gfx::PointF());
224 selector.OnSelectionActivated();
225 EXPECT_FALSE(GetAndResetActiveStateChanged());
226 EXPECT_FALSE(IsDragging());
228 // Activate a longpress-triggered selection, but at a place different than the
229 // current touch down event.
230 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF(kSlop, 0));
231 selector.OnSelectionActivated();
232 EXPECT_FALSE(GetAndResetActiveStateChanged());
233 EXPECT_FALSE(IsDragging());
235 // Touch movement should not initiate selection drag.
236 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
237 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
238 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
239 EXPECT_FALSE(IsDragging());
240 EXPECT_EQ(gfx::PointF(), DragPosition());
243 TEST_F(LongPressDragSelectorTest, NoSelection) {
244 LongPressDragSelector selector(this);
245 MockMotionEvent event;
247 // Start a touch sequence.
248 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
249 EXPECT_FALSE(GetAndResetActiveStateChanged());
251 // Trigger a longpress. This will notify the client that detection is active,
252 // but until there's a longpress no drag selection should occur.
253 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
254 EXPECT_TRUE(GetAndResetActiveStateChanged());
255 EXPECT_FALSE(IsDragging());
257 // Touch movement should not initiate selection drag, as there is no active
258 // selection.
259 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
260 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
261 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
262 EXPECT_FALSE(IsDragging());
263 EXPECT_EQ(gfx::PointF(), DragPosition());
265 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
266 EXPECT_TRUE(GetAndResetActiveStateChanged());
269 TEST_F(LongPressDragSelectorTest, NoDragMotion) {
270 LongPressDragSelector selector(this);
271 MockMotionEvent event;
273 // Start a touch sequence.
274 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
275 EXPECT_FALSE(GetAndResetActiveStateChanged());
277 // Activate a longpress-triggered selection.
278 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
279 EXPECT_TRUE(GetAndResetActiveStateChanged());
280 gfx::PointF selection_start(0, 10);
281 gfx::PointF selection_end(10, 10);
282 SetSelection(selection_start, selection_end);
283 selector.OnSelectionActivated();
284 EXPECT_FALSE(IsDragging());
286 // Touch movement within the slop region should not initiate selection drag.
287 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
288 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop / 2)));
289 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop / 2)));
290 EXPECT_FALSE(IsDragging());
291 EXPECT_EQ(gfx::PointF(), DragPosition());
293 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
294 EXPECT_TRUE(GetAndResetActiveStateChanged());
297 TEST_F(LongPressDragSelectorTest, SelectionDeactivated) {
298 LongPressDragSelector selector(this);
299 MockMotionEvent event;
301 // Start a touch sequence.
302 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
303 EXPECT_FALSE(GetAndResetActiveStateChanged());
305 // Activate a longpress-triggered selection.
306 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
307 EXPECT_TRUE(GetAndResetActiveStateChanged());
308 gfx::PointF selection_start(0, 10);
309 gfx::PointF selection_end(10, 10);
310 SetSelection(selection_start, selection_end);
311 selector.OnSelectionActivated();
312 EXPECT_FALSE(IsDragging());
314 // Start a drag selection.
315 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
316 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
317 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
318 EXPECT_TRUE(IsDragging());
320 // Clearing the selection should force an end to the drag.
321 selector.OnSelectionDeactivated();
322 EXPECT_TRUE(GetAndResetActiveStateChanged());
323 EXPECT_FALSE(IsDragging());
325 // Subsequent motion should not be consumed.
326 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
327 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop)));
328 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2)));
329 EXPECT_FALSE(IsDragging());
330 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
333 TEST_F(LongPressDragSelectorTest, DragFast) {
334 LongPressDragSelector selector(this);
335 MockMotionEvent event;
337 // Start a touch sequence.
338 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0)));
339 EXPECT_FALSE(GetAndResetActiveStateChanged());
341 // Activate a longpress-triggered selection.
342 gfx::PointF selection_start(0, 10);
343 gfx::PointF selection_end(10, 10);
344 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF());
345 EXPECT_TRUE(GetAndResetActiveStateChanged());
346 SetSelection(selection_start, selection_end);
347 selector.OnSelectionActivated();
348 EXPECT_FALSE(IsDragging());
350 // Initiate drag motion.
351 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 15, 5)));
352 EXPECT_FALSE(IsDragging());
354 // As the initial motion exceeds both endpoints, the closer bound should
355 // be used for dragging, in this case the selection end.
356 EXPECT_TRUE(selector.WillHandleTouchEvent(
357 event.MovePoint(0, 15.f + kSlop * 2.f, 5.f + kSlop)));
358 EXPECT_TRUE(IsDragging());
359 EXPECT_EQ(selection_end, DragPosition());
361 // Release the touch sequence, ending the drag.
362 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint()));
363 EXPECT_FALSE(IsDragging());
364 EXPECT_TRUE(GetAndResetActiveStateChanged());
367 } // namespace ui