Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: content/browser/renderer_host/input/touch_selection_controller_unittest.cc

Issue 759433002: Reland: Move TouchSelectionController from content to ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Excluded ui/touch_selection from Windows GN build Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "content/browser/renderer_host/input/touch_selection_controller.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 content {
13 namespace {
14
15 const int kDefaultTapTimeoutMs = 200;
16 const float kDefaulTapSlop = 10.f;
17
18 class MockTouchHandleDrawable : public TouchHandleDrawable {
19 public:
20 explicit MockTouchHandleDrawable(bool* contains_point)
21 : intersects_rect_(contains_point) {}
22 ~MockTouchHandleDrawable() override {}
23 void SetEnabled(bool enabled) override {}
24 void SetOrientation(TouchHandleOrientation orientation) override {}
25 void SetAlpha(float alpha) override {}
26 void SetFocus(const gfx::PointF& position) override {}
27 bool IntersectsWith(const gfx::RectF& rect) const override {
28 return *intersects_rect_;
29 }
30
31 private:
32 bool* intersects_rect_;
33 };
34
35 } // namespace
36
37 class TouchSelectionControllerTest : public testing::Test,
38 public TouchSelectionControllerClient {
39 public:
40 TouchSelectionControllerTest()
41 : last_event_(SELECTION_CLEARED),
42 caret_moved_(false),
43 selection_moved_(false),
44 selection_points_swapped_(false),
45 needs_animate_(false),
46 animation_enabled_(true),
47 dragging_enabled_(false) {}
48
49 ~TouchSelectionControllerTest() override {}
50
51 // testing::Test implementation.
52 void SetUp() override {
53 controller_.reset(new TouchSelectionController(
54 this,
55 base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs),
56 kDefaulTapSlop));
57 }
58
59 void TearDown() override { controller_.reset(); }
60
61 // TouchSelectionControllerClient implementation.
62
63 bool SupportsAnimation() const override { return animation_enabled_; }
64
65 void SetNeedsAnimate() override { needs_animate_ = true; }
66
67 void MoveCaret(const gfx::PointF& position) override {
68 caret_moved_ = true;
69 caret_position_ = position;
70 }
71
72 void SelectBetweenCoordinates(const gfx::PointF& base,
73 const gfx::PointF& extent) override {
74 if (base == selection_end_ && extent == selection_start_)
75 selection_points_swapped_ = true;
76
77 selection_start_ = base;
78 selection_end_ = extent;
79 }
80
81 virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) override {
82 selection_moved_ = true;
83 selection_end_ = extent;
84 }
85
86 void OnSelectionEvent(SelectionEventType event,
87 const gfx::PointF& end_position) override {
88 last_event_ = event;
89 last_event_start_ = end_position;
90 }
91
92 scoped_ptr<TouchHandleDrawable> CreateDrawable() override {
93 return scoped_ptr<TouchHandleDrawable>(
94 new MockTouchHandleDrawable(&dragging_enabled_));
95 }
96
97 void SetAnimationEnabled(bool enabled) { animation_enabled_ = enabled; }
98 void SetDraggingEnabled(bool enabled) { dragging_enabled_ = enabled; }
99
100 void ClearSelection() {
101 controller_->OnSelectionBoundsChanged(cc::ViewportSelectionBound(),
102 cc::ViewportSelectionBound());
103 }
104
105 void ClearInsertion() { ClearSelection(); }
106
107 void ChangeInsertion(const gfx::RectF& rect, bool visible) {
108 cc::ViewportSelectionBound bound;
109 bound.type = cc::SELECTION_BOUND_CENTER;
110 bound.edge_top = rect.origin();
111 bound.edge_bottom = rect.bottom_left();
112 bound.visible = visible;
113 controller_->OnSelectionBoundsChanged(bound, bound);
114 }
115
116 void ChangeSelection(const gfx::RectF& start_rect,
117 bool start_visible,
118 const gfx::RectF& end_rect,
119 bool end_visible) {
120 cc::ViewportSelectionBound start_bound, end_bound;
121 start_bound.type = cc::SELECTION_BOUND_LEFT;
122 end_bound.type = cc::SELECTION_BOUND_RIGHT;
123 start_bound.edge_top = start_rect.origin();
124 start_bound.edge_bottom = start_rect.bottom_left();
125 end_bound.edge_top = end_rect.origin();
126 end_bound.edge_bottom = end_rect.bottom_left();
127 start_bound.visible = start_visible;
128 end_bound.visible = end_visible;
129 controller_->OnSelectionBoundsChanged(start_bound, end_bound);
130 }
131
132 void Animate() {
133 base::TimeTicks now = base::TimeTicks::Now();
134 while (needs_animate_) {
135 needs_animate_ = controller_->Animate(now);
136 now += base::TimeDelta::FromMilliseconds(16);
137 }
138 }
139
140 bool GetAndResetNeedsAnimate() {
141 bool needs_animate = needs_animate_;
142 Animate();
143 return needs_animate;
144 }
145
146 bool GetAndResetCaretMoved() {
147 bool moved = caret_moved_;
148 caret_moved_ = false;
149 return moved;
150 }
151
152 bool GetAndResetSelectionMoved() {
153 bool moved = selection_moved_;
154 selection_moved_ = false;
155 return moved;
156 }
157
158 bool GetAndResetSelectionPointsSwapped() {
159 bool swapped = selection_points_swapped_;
160 selection_points_swapped_ = false;
161 return swapped;
162 }
163
164 const gfx::PointF& GetLastCaretPosition() const { return caret_position_; }
165 const gfx::PointF& GetLastSelectionStart() const { return selection_start_; }
166 const gfx::PointF& GetLastSelectionEnd() const { return selection_end_; }
167 SelectionEventType GetLastEventType() const { return last_event_; }
168 const gfx::PointF& GetLastEventAnchor() const { return last_event_start_; }
169
170 TouchSelectionController& controller() { return *controller_; }
171
172 private:
173 gfx::PointF last_event_start_;
174 gfx::PointF caret_position_;
175 gfx::PointF selection_start_;
176 gfx::PointF selection_end_;
177 SelectionEventType last_event_;
178 bool caret_moved_;
179 bool selection_moved_;
180 bool selection_points_swapped_;
181 bool needs_animate_;
182 bool animation_enabled_;
183 bool dragging_enabled_;
184 scoped_ptr<TouchSelectionController> controller_;
185 };
186
187 TEST_F(TouchSelectionControllerTest, InsertionBasic) {
188 gfx::RectF insertion_rect(5, 5, 0, 10);
189 bool visible = true;
190
191 // Insertion events are ignored until automatic showing is enabled.
192 ChangeInsertion(insertion_rect, visible);
193 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
194 controller().OnTapEvent();
195
196 // Insertion events are ignored until the selection region is marked editable.
197 ChangeInsertion(insertion_rect, visible);
198 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
199
200 controller().OnTapEvent();
201 controller().OnSelectionEditable(true);
202 ChangeInsertion(insertion_rect, visible);
203 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
204 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
205
206 insertion_rect.Offset(1, 0);
207 ChangeInsertion(insertion_rect, visible);
208 EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
209 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
210
211 insertion_rect.Offset(0, 1);
212 ChangeInsertion(insertion_rect, visible);
213 EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
214 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
215
216 ClearInsertion();
217 EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
218 }
219
220 TEST_F(TouchSelectionControllerTest, InsertionClearedWhenNoLongerEditable) {
221 gfx::RectF insertion_rect(5, 5, 0, 10);
222 bool visible = true;
223 controller().OnTapEvent();
224 controller().OnSelectionEditable(true);
225
226 ChangeInsertion(insertion_rect, visible);
227 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
228 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
229
230 controller().OnSelectionEditable(false);
231 EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
232 }
233
234 TEST_F(TouchSelectionControllerTest, InsertionStaysHiddenIfEmptyRegionTapped) {
235 gfx::RectF insertion_rect(5, 5, 0, 10);
236 bool visible = true;
237 controller().OnSelectionEditable(true);
238
239 // Taps should be ignored if they're in an empty editable region.
240 controller().OnTapEvent();
241 controller().OnSelectionEmpty(true);
242 ChangeInsertion(insertion_rect, visible);
243 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
244
245 // Once the region becomes editable, taps should show the insertion handle.
246 controller().OnTapEvent();
247 controller().OnSelectionEmpty(false);
248 ChangeInsertion(insertion_rect, visible);
249 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
250 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
251
252 // Reset the selection.
253 controller().HideAndDisallowShowingAutomatically();
254 EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
255
256 // Long-pressing should show the handle even if the editable region is empty.
257 insertion_rect.Offset(2, -2);
258 controller().OnLongPressEvent();
259 controller().OnSelectionEmpty(true);
260 ChangeInsertion(insertion_rect, visible);
261 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
262 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
263
264 // Single Tap on an empty edit field should clear insertion handle.
265 controller().OnTapEvent();
266 EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
267 }
268
269 TEST_F(TouchSelectionControllerTest, InsertionAppearsAfterTapFollowingTyping) {
270 gfx::RectF insertion_rect(5, 5, 0, 10);
271 bool visible = true;
272
273 // Simulate the user tapping an empty text field.
274 controller().OnTapEvent();
275 controller().OnSelectionEditable(true);
276 controller().OnSelectionEmpty(true);
277 ChangeInsertion(insertion_rect, visible);
278 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
279
280 // Simulate the cursor moving while a user is typing.
281 insertion_rect.Offset(10, 0);
282 controller().OnSelectionEmpty(false);
283 ChangeInsertion(insertion_rect, visible);
284 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
285
286 // If the user taps the *same* position as the cursor at the end of the text
287 // entry, the handle should appear.
288 controller().OnTapEvent();
289 ChangeInsertion(insertion_rect, visible);
290 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
291 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
292 }
293
294 TEST_F(TouchSelectionControllerTest, InsertionToSelectionTransition) {
295 controller().OnLongPressEvent();
296 controller().OnSelectionEditable(true);
297
298 gfx::RectF start_rect(5, 5, 0, 10);
299 gfx::RectF end_rect(50, 5, 0, 10);
300 bool visible = true;
301
302 ChangeInsertion(start_rect, visible);
303 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
304 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
305
306 ChangeSelection(start_rect, visible, end_rect, visible);
307 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
308 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
309
310 ChangeInsertion(end_rect, visible);
311 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
312 EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
313
314 controller().HideAndDisallowShowingAutomatically();
315 EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
316
317 controller().OnTapEvent();
318 ChangeInsertion(end_rect, visible);
319 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
320 EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
321 }
322
323 TEST_F(TouchSelectionControllerTest, InsertionDragged) {
324 base::TimeTicks event_time = base::TimeTicks::Now();
325 controller().OnTapEvent();
326 controller().OnSelectionEditable(true);
327
328 // The touch sequence should not be handled if insertion is not active.
329 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
330 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
331
332 float line_height = 10.f;
333 gfx::RectF start_rect(10, 0, 0, line_height);
334 bool visible = true;
335 ChangeInsertion(start_rect, visible);
336 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
337 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
338
339 // The touch sequence should be handled only if the drawable reports a hit.
340 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
341 SetDraggingEnabled(true);
342 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
343 EXPECT_FALSE(GetAndResetCaretMoved());
344
345 // The MoveCaret() result should reflect the movement.
346 // The reported position is offset from the center of |start_rect|.
347 gfx::PointF start_offset = start_rect.CenterPoint();
348 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 5);
349 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
350 EXPECT_TRUE(GetAndResetCaretMoved());
351 EXPECT_EQ(start_offset + gfx::Vector2dF(0, 5), GetLastCaretPosition());
352
353 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 5, 5);
354 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
355 EXPECT_TRUE(GetAndResetCaretMoved());
356 EXPECT_EQ(start_offset + gfx::Vector2dF(5, 5), GetLastCaretPosition());
357
358 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 10, 10);
359 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
360 EXPECT_TRUE(GetAndResetCaretMoved());
361 EXPECT_EQ(start_offset + gfx::Vector2dF(10, 10), GetLastCaretPosition());
362
363 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
364 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
365 EXPECT_FALSE(GetAndResetCaretMoved());
366
367 // Once the drag is complete, no more touch events should be consumed until
368 // the next ACTION_DOWN.
369 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
370 }
371
372 TEST_F(TouchSelectionControllerTest, InsertionTapped) {
373 base::TimeTicks event_time = base::TimeTicks::Now();
374 controller().OnTapEvent();
375 controller().OnSelectionEditable(true);
376 SetDraggingEnabled(true);
377
378 gfx::RectF start_rect(10, 0, 0, 10);
379 bool visible = true;
380 ChangeInsertion(start_rect, visible);
381 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
382
383 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
384 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
385 //TODO(AKV): this test case has to be modified once crbug.com/394093 is fixed.
386 EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
387
388 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
389 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
390 EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
391
392 // Reset the insertion.
393 ClearInsertion();
394 controller().OnTapEvent();
395 ChangeInsertion(start_rect, visible);
396 ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
397
398 // No tap should be signalled if the time between DOWN and UP was too long.
399 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
400 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
401 event = MockMotionEvent(MockMotionEvent::ACTION_UP,
402 event_time + base::TimeDelta::FromSeconds(1),
403 0,
404 0);
405 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
406 EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
407
408 // Reset the insertion.
409 ClearInsertion();
410 controller().OnTapEvent();
411 ChangeInsertion(start_rect, visible);
412 ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
413
414 // No tap should be signalled if the drag was too long.
415 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
416 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
417 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 100, 0);
418 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
419 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 100, 0);
420 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
421 EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
422
423 // Reset the insertion.
424 ClearInsertion();
425 controller().OnTapEvent();
426 ChangeInsertion(start_rect, visible);
427 ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
428
429 // No tap should be signalled if the touch sequence is cancelled.
430 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
431 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
432 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
433 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
434 EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
435 }
436
437 TEST_F(TouchSelectionControllerTest, InsertionNotResetByRepeatedTapOrPress) {
438 base::TimeTicks event_time = base::TimeTicks::Now();
439 controller().OnTapEvent();
440 controller().OnSelectionEditable(true);
441 SetDraggingEnabled(true);
442
443 gfx::RectF anchor_rect(10, 0, 0, 10);
444 bool visible = true;
445 ChangeInsertion(anchor_rect, visible);
446 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
447 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
448
449 // Tapping again shouldn't reset the active insertion point.
450 controller().OnTapEvent();
451 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
452 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
453 EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
454 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
455
456 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
457 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
458 EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
459 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
460
461 anchor_rect.Offset(5, 15);
462 ChangeInsertion(anchor_rect, visible);
463 EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
464 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
465
466 // Pressing shouldn't reset the active insertion point.
467 controller().OnLongPressEvent();
468 controller().OnSelectionEmpty(true);
469 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
470 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
471 EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
472 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
473
474 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
475 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
476 EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
477 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
478 }
479
480 TEST_F(TouchSelectionControllerTest, SelectionBasic) {
481 gfx::RectF start_rect(5, 5, 0, 10);
482 gfx::RectF end_rect(50, 5, 0, 10);
483 bool visible = true;
484
485 // Selection events are ignored until automatic showing is enabled.
486 ChangeSelection(start_rect, visible, end_rect, visible);
487 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
488
489 controller().OnLongPressEvent();
490 ChangeSelection(start_rect, visible, end_rect, visible);
491 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
492 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
493
494 start_rect.Offset(1, 0);
495 ChangeSelection(start_rect, visible, end_rect, visible);
496 // Selection movement does not currently trigger a separate event.
497 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
498
499 ClearSelection();
500 EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
501 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
502 }
503
504 TEST_F(TouchSelectionControllerTest, SelectionRepeatedLongPress) {
505 gfx::RectF start_rect(5, 5, 0, 10);
506 gfx::RectF end_rect(50, 5, 0, 10);
507 bool visible = true;
508
509 controller().OnLongPressEvent();
510 ChangeSelection(start_rect, visible, end_rect, visible);
511 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
512 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
513
514 // A long press triggering a new selection should re-send the SELECTION_SHOWN
515 // event notification.
516 start_rect.Offset(10, 10);
517 controller().OnLongPressEvent();
518 ChangeSelection(start_rect, visible, end_rect, visible);
519 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
520 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
521 }
522
523 TEST_F(TouchSelectionControllerTest, SelectionDragged) {
524 base::TimeTicks event_time = base::TimeTicks::Now();
525 controller().OnLongPressEvent();
526
527 // The touch sequence should not be handled if selection is not active.
528 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
529 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
530
531 float line_height = 10.f;
532 gfx::RectF start_rect(0, 0, 0, line_height);
533 gfx::RectF end_rect(50, 0, 0, line_height);
534 bool visible = true;
535 ChangeSelection(start_rect, visible, end_rect, visible);
536 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
537 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
538
539 // The touch sequence should be handled only if the drawable reports a hit.
540 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
541 SetDraggingEnabled(true);
542 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
543 EXPECT_FALSE(GetAndResetSelectionMoved());
544
545 // The SelectBetweenCoordinates() result should reflect the movement. Note
546 // that the start coordinate will always reflect the "fixed" handle's
547 // position, in this case the position from |end_rect|.
548 // Note that the reported position is offset from the center of the
549 // input rects (i.e., the middle of the corresponding text line).
550 gfx::PointF fixed_offset = end_rect.CenterPoint();
551 gfx::PointF start_offset = start_rect.CenterPoint();
552 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 5);
553 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
554 EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
555 EXPECT_TRUE(GetAndResetSelectionMoved());
556 EXPECT_EQ(fixed_offset, GetLastSelectionStart());
557 EXPECT_EQ(start_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
558
559 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 5, 5);
560 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
561 EXPECT_TRUE(GetAndResetSelectionMoved());
562 EXPECT_EQ(fixed_offset, GetLastSelectionStart());
563 EXPECT_EQ(start_offset + gfx::Vector2dF(5, 5), GetLastSelectionEnd());
564
565 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 10, 5);
566 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
567 EXPECT_TRUE(GetAndResetSelectionMoved());
568 EXPECT_EQ(fixed_offset, GetLastSelectionStart());
569 EXPECT_EQ(start_offset + gfx::Vector2dF(10, 5), GetLastSelectionEnd());
570
571 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
572 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
573 EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
574 EXPECT_FALSE(GetAndResetSelectionMoved());
575
576 // Once the drag is complete, no more touch events should be consumed until
577 // the next ACTION_DOWN.
578 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
579 }
580
581 TEST_F(TouchSelectionControllerTest, SelectionDraggedWithOverlap) {
582 base::TimeTicks event_time = base::TimeTicks::Now();
583 controller().OnLongPressEvent();
584
585 float line_height = 10.f;
586 gfx::RectF start_rect(0, 0, 0, line_height);
587 gfx::RectF end_rect(50, 0, 0, line_height);
588 bool visible = true;
589 ChangeSelection(start_rect, visible, end_rect, visible);
590 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
591 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
592
593 // The ACTION_DOWN should lock to the closest handle.
594 gfx::PointF end_offset = end_rect.CenterPoint();
595 gfx::PointF fixed_offset = start_rect.CenterPoint();
596 float touch_down_x = (end_offset.x() + fixed_offset.x()) / 2 + 1.f;
597 MockMotionEvent event(
598 MockMotionEvent::ACTION_DOWN, event_time, touch_down_x, 0);
599 SetDraggingEnabled(true);
600 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
601 EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
602 EXPECT_FALSE(GetAndResetSelectionMoved());
603
604 // Even though the ACTION_MOVE is over the start handle, it should continue
605 // targetting the end handle that consumed the ACTION_DOWN.
606 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 0);
607 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
608 EXPECT_TRUE(GetAndResetSelectionMoved());
609 EXPECT_EQ(fixed_offset, GetLastSelectionStart());
610 EXPECT_EQ(end_offset - gfx::Vector2dF(touch_down_x, 0),
611 GetLastSelectionEnd());
612
613 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
614 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
615 EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
616 EXPECT_FALSE(GetAndResetSelectionMoved());
617 }
618
619 TEST_F(TouchSelectionControllerTest, SelectionDraggedToSwitchBaseAndExtent) {
620 base::TimeTicks event_time = base::TimeTicks::Now();
621 controller().OnLongPressEvent();
622
623 float line_height = 10.f;
624 gfx::RectF start_rect(50, line_height, 0, line_height);
625 gfx::RectF end_rect(100, line_height, 0, line_height);
626 bool visible = true;
627 ChangeSelection(start_rect, visible, end_rect, visible);
628 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
629 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
630
631 SetDraggingEnabled(true);
632
633 // Move the extent, not triggering a swap of points.
634 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time,
635 end_rect.x(), end_rect.bottom());
636 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
637 EXPECT_FALSE(GetAndResetSelectionMoved());
638 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
639
640 gfx::PointF base_offset = start_rect.CenterPoint();
641 gfx::PointF extent_offset = end_rect.CenterPoint();
642 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
643 end_rect.x(), end_rect.bottom() + 5);
644 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
645 EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
646 EXPECT_TRUE(GetAndResetSelectionMoved());
647 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
648 EXPECT_EQ(base_offset, GetLastSelectionStart());
649 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
650
651 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
652 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
653 EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
654 EXPECT_FALSE(GetAndResetSelectionMoved());
655
656 end_rect += gfx::Vector2dF(0, 5);
657 ChangeSelection(start_rect, visible, end_rect, visible);
658
659 // Move the base, triggering a swap of points.
660 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
661 start_rect.x(), start_rect.bottom());
662 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
663 EXPECT_FALSE(GetAndResetSelectionMoved());
664 EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
665
666 base_offset = end_rect.CenterPoint();
667 extent_offset = start_rect.CenterPoint();
668 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
669 start_rect.x(), start_rect.bottom() + 5);
670 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
671 EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
672 EXPECT_TRUE(GetAndResetSelectionMoved());
673 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
674 EXPECT_EQ(base_offset, GetLastSelectionStart());
675 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
676
677 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
678 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
679 EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
680 EXPECT_FALSE(GetAndResetSelectionMoved());
681
682 start_rect += gfx::Vector2dF(0, 5);
683 ChangeSelection(start_rect, visible, end_rect, visible);
684
685 // Move the same point again, not triggering a swap of points.
686 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
687 start_rect.x(), start_rect.bottom());
688 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
689 EXPECT_FALSE(GetAndResetSelectionMoved());
690 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
691
692 base_offset = end_rect.CenterPoint();
693 extent_offset = start_rect.CenterPoint();
694 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
695 start_rect.x(), start_rect.bottom() + 5);
696 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
697 EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
698 EXPECT_TRUE(GetAndResetSelectionMoved());
699 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
700 EXPECT_EQ(base_offset, GetLastSelectionStart());
701 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
702
703 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
704 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
705 EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
706 EXPECT_FALSE(GetAndResetSelectionMoved());
707
708 start_rect += gfx::Vector2dF(0, 5);
709 ChangeSelection(start_rect, visible, end_rect, visible);
710
711 // Move the base, triggering a swap of points.
712 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
713 end_rect.x(), end_rect.bottom());
714 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
715 EXPECT_FALSE(GetAndResetSelectionMoved());
716 EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
717
718 base_offset = start_rect.CenterPoint();
719 extent_offset = end_rect.CenterPoint();
720 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
721 end_rect.x(), end_rect.bottom() + 5);
722 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
723 EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
724 EXPECT_TRUE(GetAndResetSelectionMoved());
725 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
726 EXPECT_EQ(base_offset, GetLastSelectionStart());
727 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
728
729 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
730 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
731 EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
732 EXPECT_FALSE(GetAndResetSelectionMoved());
733 }
734
735 TEST_F(TouchSelectionControllerTest, Animation) {
736 controller().OnTapEvent();
737 controller().OnSelectionEditable(true);
738
739 gfx::RectF insertion_rect(5, 5, 0, 10);
740
741 bool visible = true;
742 ChangeInsertion(insertion_rect, visible);
743 EXPECT_FALSE(GetAndResetNeedsAnimate());
744
745 visible = false;
746 ChangeInsertion(insertion_rect, visible);
747 EXPECT_TRUE(GetAndResetNeedsAnimate());
748
749 visible = true;
750 ChangeInsertion(insertion_rect, visible);
751 EXPECT_TRUE(GetAndResetNeedsAnimate());
752
753 // If the handles are explicity hidden, no animation should be triggered.
754 controller().HideAndDisallowShowingAutomatically();
755 EXPECT_FALSE(GetAndResetNeedsAnimate());
756
757 // If the client doesn't support animation, no animation should be triggered.
758 SetAnimationEnabled(false);
759 controller().OnTapEvent();
760 visible = true;
761 ChangeInsertion(insertion_rect, visible);
762 EXPECT_FALSE(GetAndResetNeedsAnimate());
763 }
764
765 TEST_F(TouchSelectionControllerTest, TemporarilyHidden) {
766 controller().OnTapEvent();
767 controller().OnSelectionEditable(true);
768
769 gfx::RectF insertion_rect(5, 5, 0, 10);
770
771 bool visible = true;
772 ChangeInsertion(insertion_rect, visible);
773 EXPECT_FALSE(GetAndResetNeedsAnimate());
774
775 controller().SetTemporarilyHidden(true);
776 EXPECT_TRUE(GetAndResetNeedsAnimate());
777
778 visible = false;
779 ChangeInsertion(insertion_rect, visible);
780 EXPECT_FALSE(GetAndResetNeedsAnimate());
781
782 visible = true;
783 ChangeInsertion(insertion_rect, visible);
784 EXPECT_FALSE(GetAndResetNeedsAnimate());
785
786 controller().SetTemporarilyHidden(false);
787 EXPECT_TRUE(GetAndResetNeedsAnimate());
788 }
789
790 TEST_F(TouchSelectionControllerTest, SelectionClearOnTap) {
791 gfx::RectF start_rect(5, 5, 0, 10);
792 gfx::RectF end_rect(50, 5, 0, 10);
793 bool visible = true;
794
795 controller().OnLongPressEvent();
796 ChangeSelection(start_rect, visible, end_rect, visible);
797
798 // Selection should not be cleared if the selection bounds have not changed.
799 controller().OnTapEvent();
800 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
801 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
802
803 controller().OnTapEvent();
804 ClearSelection();
805 EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
806 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
807 }
808
809 TEST_F(TouchSelectionControllerTest, AllowShowingFromCurrentSelection) {
810 gfx::RectF start_rect(5, 5, 0, 10);
811 gfx::RectF end_rect(50, 5, 0, 10);
812 bool visible = true;
813
814 // The selection should not have be activated, as it wasn't yet allowed.
815 ChangeSelection(start_rect, visible, end_rect, visible);
816 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
817
818 // Now explicitly allow showing from the previously supplied bounds.
819 controller().AllowShowingFromCurrentSelection();
820 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
821 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
822
823 // Repeated calls to show from the current selection should be ignored.
824 controller().AllowShowingFromCurrentSelection();
825 EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
826 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
827
828 // Trying to show from an empty selection will have no result.
829 ClearSelection();
830 EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
831 controller().AllowShowingFromCurrentSelection();
832 EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
833
834 // Showing the insertion handle should also be supported.
835 controller().OnSelectionEditable(true);
836 controller().OnSelectionEmpty(false);
837 controller().HideAndDisallowShowingAutomatically();
838 gfx::RectF insertion_rect(5, 5, 0, 10);
839 ChangeInsertion(insertion_rect, visible);
840 controller().AllowShowingFromCurrentSelection();
841 EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
842 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
843 }
844
845 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698