OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "ui/touch_selection/longpress_drag_selector.h" | |
6 | |
7 #include "testing/gtest/include/gtest/gtest.h" | |
8 #include "ui/events/test/motion_event_test_utils.h" | |
9 | |
10 using ui::test::MockMotionEvent; | |
11 | |
12 namespace ui { | |
13 namespace { | |
14 | |
15 const double kSlop = 10.; | |
16 | |
17 } // namespace | |
18 | |
19 class LongPressDragSelectorTest : public testing::Test, | |
20 public LongPressDragSelectorClient { | |
21 public: | |
22 LongPressDragSelectorTest() | |
23 : dragging_(false), active_state_changed_(false) {} | |
24 | |
25 ~LongPressDragSelectorTest() override {} | |
26 | |
27 void SetSelection(const gfx::PointF& start, const gfx::PointF& end) { | |
28 selection_start_ = start; | |
29 selection_end_ = end; | |
30 } | |
31 | |
32 bool GetAndResetActiveStateChanged() { | |
33 bool active_state_changed = active_state_changed_; | |
34 active_state_changed_ = false; | |
35 return active_state_changed; | |
36 } | |
37 | |
38 bool IsDragging() const { return dragging_; } | |
39 const gfx::PointF& DragPosition() const { return drag_position_; } | |
40 | |
41 // LongPressDragSelectorClient implementation. | |
42 void OnDragBegin(const TouchSelectionDraggable& handler, | |
43 const gfx::PointF& drag_position) override { | |
44 dragging_ = true; | |
45 drag_position_ = drag_position; | |
46 } | |
47 | |
48 void OnDragUpdate(const TouchSelectionDraggable& handler, | |
49 const gfx::PointF& drag_position) override { | |
50 drag_position_ = drag_position; | |
51 } | |
52 | |
53 void OnDragEnd(const TouchSelectionDraggable& handler) override { | |
54 dragging_ = false; | |
55 } | |
56 | |
57 bool IsWithinTapSlop(const gfx::Vector2dF& delta) const override { | |
58 return delta.LengthSquared() < (kSlop * kSlop); | |
59 } | |
60 | |
61 void OnLongPressDragActiveStateChanged() override { | |
62 active_state_changed_ = true; | |
63 } | |
64 | |
65 gfx::PointF GetSelectionStart() const override { return selection_start_; } | |
66 | |
67 gfx::PointF GetSelectionEnd() const override { return selection_end_; } | |
68 | |
69 private: | |
70 bool dragging_; | |
71 bool active_state_changed_; | |
72 gfx::PointF drag_position_; | |
73 | |
74 gfx::PointF selection_start_; | |
75 gfx::PointF selection_end_; | |
76 }; | |
77 | |
78 TEST_F(LongPressDragSelectorTest, BasicDrag) { | |
79 LongPressDragSelector selector(this); | |
80 MockMotionEvent event; | |
81 | |
82 // Start a touch sequence. | |
83 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
84 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
85 | |
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()); | |
91 | |
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()); | |
97 | |
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()); | |
102 | |
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()); | |
108 | |
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()); | |
116 | |
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()); | |
122 } | |
123 | |
124 TEST_F(LongPressDragSelectorTest, BasicReverseDrag) { | |
125 LongPressDragSelector selector(this); | |
126 MockMotionEvent event; | |
127 | |
128 // Start a touch sequence. | |
129 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
130 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
131 | |
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()); | |
140 | |
141 // Initiate drag motion. | |
142 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
143 EXPECT_FALSE(IsDragging()); | |
144 | |
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()); | |
150 | |
151 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop))); | |
152 EXPECT_TRUE(IsDragging()); | |
153 EXPECT_EQ(selection_start + gfx::Vector2dF(kSlop, -kSlop), DragPosition()); | |
mfomitchev
2015/05/14 21:58:32
Sorry, I don't get it: we've moved by (-kSlop, -kS
jdduke (slow)
2015/05/14 22:19:28
Hmm, maybe switching from x to y coordinate is con
mfomitchev
2015/05/14 22:33:57
AH, right. For some reason I was reading this as r
| |
154 | |
155 // Release the touch sequence, ending the drag. | |
156 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
157 EXPECT_FALSE(IsDragging()); | |
158 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
159 } | |
160 | |
161 TEST_F(LongPressDragSelectorTest, NoActiveTouch) { | |
162 LongPressDragSelector selector(this); | |
163 MockMotionEvent event; | |
164 | |
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()); | |
173 | |
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()); | |
182 } | |
183 | |
184 TEST_F(LongPressDragSelectorTest, NoLongPress) { | |
185 LongPressDragSelector selector(this); | |
186 MockMotionEvent event; | |
187 | |
188 // Start a touch sequence. | |
189 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
190 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
191 | |
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()); | |
199 | |
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()); | |
206 } | |
207 | |
208 TEST_F(LongPressDragSelectorTest, NoValidLongPress) { | |
209 LongPressDragSelector selector(this); | |
210 MockMotionEvent event; | |
211 | |
212 // Start a touch sequence. | |
213 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
214 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
215 | |
216 gfx::PointF selection_start(0, 10); | |
217 gfx::PointF selection_end(10, 10); | |
218 SetSelection(selection_start, selection_end); | |
219 | |
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()); | |
227 | |
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()); | |
234 | |
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()); | |
241 } | |
242 | |
243 TEST_F(LongPressDragSelectorTest, NoSelection) { | |
244 LongPressDragSelector selector(this); | |
245 MockMotionEvent event; | |
246 | |
247 // Start a touch sequence. | |
248 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
249 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
250 | |
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()); | |
256 | |
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()); | |
264 | |
265 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
266 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
267 } | |
268 | |
269 TEST_F(LongPressDragSelectorTest, NoDragMotion) { | |
270 LongPressDragSelector selector(this); | |
271 MockMotionEvent event; | |
272 | |
273 // Start a touch sequence. | |
274 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
275 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
276 | |
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()); | |
285 | |
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()); | |
292 | |
293 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
294 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
295 } | |
296 | |
297 TEST_F(LongPressDragSelectorTest, SelectionDeactivated) { | |
298 LongPressDragSelector selector(this); | |
299 MockMotionEvent event; | |
300 | |
301 // Start a touch sequence. | |
302 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
303 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
304 | |
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()); | |
313 | |
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()); | |
319 | |
320 // Clearing the selection should force an end to the drag. | |
321 selector.OnSelectionDeactivated(); | |
322 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
323 EXPECT_FALSE(IsDragging()); | |
324 | |
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())); | |
331 } | |
332 | |
333 } // namespace ui | |
OLD | NEW |