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

Side by Side Diff: content/browser/renderer_host/input/touch_handle_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_handle.h"
6
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/events/test/motion_event_test_utils.h"
9 #include "ui/gfx/geometry/rect_f.h"
10
11 using ui::test::MockMotionEvent;
12
13 namespace content {
14 namespace {
15
16 const int kDefaultTapTimeoutMs = 200;
17 const float kDefaultTapSlop = 10.f;
18 const float kDefaultDrawableSize = 10.f;
19
20 struct MockDrawableData {
21 MockDrawableData()
22 : orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
23 alpha(0.f),
24 enabled(false),
25 visible(false),
26 rect(0, 0, kDefaultDrawableSize, kDefaultDrawableSize) {}
27 TouchHandleOrientation orientation;
28 float alpha;
29 bool enabled;
30 bool visible;
31 gfx::RectF rect;
32 };
33
34 class MockTouchHandleDrawable : public TouchHandleDrawable {
35 public:
36 explicit MockTouchHandleDrawable(MockDrawableData* data) : data_(data) {}
37 ~MockTouchHandleDrawable() override {}
38
39 void SetEnabled(bool enabled) override { data_->enabled = enabled; }
40
41 void SetOrientation(TouchHandleOrientation orientation) override {
42 data_->orientation = orientation;
43 }
44
45 void SetAlpha(float alpha) override {
46 data_->alpha = alpha;
47 data_->visible = alpha > 0;
48 }
49
50 void SetFocus(const gfx::PointF& position) override {
51 // Anchor focus to the top left of the rect (regardless of orientation).
52 data_->rect.set_origin(position);
53 }
54
55 bool IntersectsWith(const gfx::RectF& rect) const override {
56 return data_->rect.Intersects(rect);
57 }
58
59 private:
60 MockDrawableData* data_;
61 };
62
63 } // namespace
64
65 class TouchHandleTest : public testing::Test, public TouchHandleClient {
66 public:
67 TouchHandleTest()
68 : dragging_(false),
69 dragged_(false),
70 tapped_(false),
71 needs_animate_(false) {}
72
73 ~TouchHandleTest() override {}
74
75 // TouchHandleClient implementation.
76 void OnHandleDragBegin(const TouchHandle& handle) override {
77 dragging_ = true;
78 }
79
80 void OnHandleDragUpdate(const TouchHandle& handle,
81 const gfx::PointF& new_position) override {
82 dragged_ = true;
83 drag_position_ = new_position;
84 }
85
86 void OnHandleDragEnd(const TouchHandle& handle) override {
87 dragging_ = false;
88 }
89
90 void OnHandleTapped(const TouchHandle& handle) override { tapped_ = true; }
91
92 void SetNeedsAnimate() override { needs_animate_ = true; }
93
94 scoped_ptr<TouchHandleDrawable> CreateDrawable() override {
95 return scoped_ptr<TouchHandleDrawable>(
96 new MockTouchHandleDrawable(&drawable_data_));
97 }
98
99 base::TimeDelta GetTapTimeout() const override {
100 return base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs);
101 }
102
103 float GetTapSlop() const override { return kDefaultTapSlop; }
104
105 void Animate(TouchHandle& handle) {
106 needs_animate_ = false;
107 base::TimeTicks now = base::TimeTicks::Now();
108 while (handle.Animate(now))
109 now += base::TimeDelta::FromMilliseconds(16);
110 }
111
112 bool GetAndResetHandleDragged() {
113 bool dragged = dragged_;
114 dragged_ = false;
115 return dragged;
116 }
117
118 bool GetAndResetHandleTapped() {
119 bool tapped = tapped_;
120 tapped_ = false;
121 return tapped;
122 }
123
124 bool GetAndResetNeedsAnimate() {
125 bool needs_animate = needs_animate_;
126 needs_animate_ = false;
127 return needs_animate;
128 }
129
130 bool IsDragging() const { return dragging_; }
131 const gfx::PointF& DragPosition() const { return drag_position_; }
132 bool NeedsAnimate() const { return needs_animate_; }
133
134 const MockDrawableData& drawable() { return drawable_data_; }
135
136 private:
137 gfx::PointF drag_position_;
138 bool dragging_;
139 bool dragged_;
140 bool tapped_;
141 bool needs_animate_;
142
143 MockDrawableData drawable_data_;
144 };
145
146 TEST_F(TouchHandleTest, Visibility) {
147 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
148 EXPECT_FALSE(drawable().visible);
149
150 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
151 EXPECT_TRUE(drawable().visible);
152 EXPECT_EQ(1.f, drawable().alpha);
153
154 handle.SetVisible(false, TouchHandle::ANIMATION_NONE);
155 EXPECT_FALSE(drawable().visible);
156
157 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
158 EXPECT_TRUE(drawable().visible);
159 EXPECT_EQ(1.f, drawable().alpha);
160 }
161
162 TEST_F(TouchHandleTest, VisibilityAnimation) {
163 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
164 ASSERT_FALSE(NeedsAnimate());
165 ASSERT_FALSE(drawable().visible);
166 ASSERT_EQ(0.f, drawable().alpha);
167
168 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
169 EXPECT_TRUE(NeedsAnimate());
170 EXPECT_FALSE(drawable().visible);
171 EXPECT_EQ(0.f, drawable().alpha);
172
173 Animate(handle);
174 EXPECT_TRUE(drawable().visible);
175 EXPECT_EQ(1.f, drawable().alpha);
176
177 ASSERT_FALSE(NeedsAnimate());
178 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
179 EXPECT_TRUE(NeedsAnimate());
180 EXPECT_TRUE(drawable().visible);
181 EXPECT_EQ(1.f, drawable().alpha);
182
183 Animate(handle);
184 EXPECT_FALSE(drawable().visible);
185 EXPECT_EQ(0.f, drawable().alpha);
186
187 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
188 EXPECT_EQ(1.f, drawable().alpha);
189 EXPECT_FALSE(GetAndResetNeedsAnimate());
190 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
191 EXPECT_EQ(1.f, drawable().alpha);
192 EXPECT_TRUE(GetAndResetNeedsAnimate());
193 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
194 EXPECT_EQ(1.f, drawable().alpha);
195 EXPECT_FALSE(GetAndResetNeedsAnimate());
196 }
197
198 TEST_F(TouchHandleTest, Orientation) {
199 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
200 EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
201
202 handle.SetOrientation(TOUCH_HANDLE_LEFT);
203 EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
204
205 handle.SetOrientation(TOUCH_HANDLE_RIGHT);
206 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
207
208 handle.SetOrientation(TOUCH_HANDLE_CENTER);
209 EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
210 }
211
212 TEST_F(TouchHandleTest, Position) {
213 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
214 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
215
216 gfx::PointF position;
217 EXPECT_EQ(gfx::PointF(), drawable().rect.origin());
218
219 position = gfx::PointF(7.3f, -3.7f);
220 handle.SetPosition(position);
221 EXPECT_EQ(position, drawable().rect.origin());
222
223 position = gfx::PointF(-7.3f, 3.7f);
224 handle.SetPosition(position);
225 EXPECT_EQ(position, drawable().rect.origin());
226 }
227
228 TEST_F(TouchHandleTest, PositionNotUpdatedWhileFadingOrInvisible) {
229 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
230
231 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
232 ASSERT_TRUE(drawable().visible);
233 ASSERT_FALSE(NeedsAnimate());
234
235 gfx::PointF old_position(7.3f, -3.7f);
236 handle.SetPosition(old_position);
237 ASSERT_EQ(old_position, drawable().rect.origin());
238
239 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
240 ASSERT_TRUE(NeedsAnimate());
241
242 gfx::PointF new_position(3.7f, -3.7f);
243 handle.SetPosition(new_position);
244 EXPECT_EQ(old_position, drawable().rect.origin());
245 EXPECT_TRUE(NeedsAnimate());
246
247 // While the handle is fading, the new position should not take affect.
248 base::TimeTicks now = base::TimeTicks::Now();
249 while (handle.Animate(now)) {
250 EXPECT_EQ(old_position, drawable().rect.origin());
251 now += base::TimeDelta::FromMilliseconds(16);
252 }
253
254 // Even after the animation terminates, the new position will not be pushed.
255 EXPECT_EQ(old_position, drawable().rect.origin());
256
257 // As soon as the handle becomes visible, the new position will be pushed.
258 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
259 EXPECT_EQ(new_position, drawable().rect.origin());
260 }
261
262 TEST_F(TouchHandleTest, Enabled) {
263 // A newly created handle defaults to enabled.
264 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
265 EXPECT_TRUE(drawable().enabled);
266
267 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
268 EXPECT_TRUE(GetAndResetNeedsAnimate());
269 EXPECT_EQ(0.f, drawable().alpha);
270 handle.SetEnabled(false);
271 EXPECT_FALSE(drawable().enabled);
272
273 // Dragging should not be allowed while the handle is disabled.
274 base::TimeTicks event_time = base::TimeTicks::Now();
275 const float kOffset = kDefaultDrawableSize / 2.f;
276 MockMotionEvent event(
277 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
278 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
279
280 // Disabling mid-animation should cancel the animation.
281 handle.SetEnabled(true);
282 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
283 EXPECT_TRUE(drawable().visible);
284 EXPECT_TRUE(GetAndResetNeedsAnimate());
285 handle.SetEnabled(false);
286 EXPECT_FALSE(drawable().enabled);
287 EXPECT_FALSE(drawable().visible);
288 EXPECT_FALSE(handle.Animate(base::TimeTicks::Now()));
289
290 // Disabling mid-drag should cancel the drag.
291 handle.SetEnabled(true);
292 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
293 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
294 EXPECT_TRUE(IsDragging());
295 handle.SetEnabled(false);
296 EXPECT_FALSE(IsDragging());
297 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
298 }
299
300 TEST_F(TouchHandleTest, Drag) {
301 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
302
303 base::TimeTicks event_time = base::TimeTicks::Now();
304 const float kOffset = kDefaultDrawableSize / 2.f;
305
306 // The handle must be visible to trigger drag.
307 MockMotionEvent event(
308 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
309 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
310 EXPECT_FALSE(IsDragging());
311 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
312
313 // ACTION_DOWN must fall within the drawable region to trigger drag.
314 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 50, 50);
315 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
316 EXPECT_FALSE(IsDragging());
317
318 // Only ACTION_DOWN will trigger drag.
319 event = MockMotionEvent(
320 MockMotionEvent::ACTION_MOVE, event_time, kOffset, kOffset);
321 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
322 EXPECT_FALSE(IsDragging());
323
324 // Start the drag.
325 event = MockMotionEvent(
326 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
327 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
328 EXPECT_TRUE(IsDragging());
329
330 event = MockMotionEvent(
331 MockMotionEvent::ACTION_MOVE, event_time, kOffset + 10, kOffset + 15);
332 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
333 EXPECT_TRUE(GetAndResetHandleDragged());
334 EXPECT_TRUE(IsDragging());
335 EXPECT_EQ(gfx::PointF(10, 15), DragPosition());
336
337 event = MockMotionEvent(
338 MockMotionEvent::ACTION_MOVE, event_time, kOffset - 10, kOffset - 15);
339 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
340 EXPECT_TRUE(GetAndResetHandleDragged());
341 EXPECT_TRUE(IsDragging());
342 EXPECT_EQ(gfx::PointF(-10, -15), DragPosition());
343
344 event = MockMotionEvent(MockMotionEvent::ACTION_UP);
345 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
346 EXPECT_FALSE(GetAndResetHandleDragged());
347 EXPECT_FALSE(IsDragging());
348
349 // Non-ACTION_DOWN events after the drag has terminated should not be handled.
350 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL);
351 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
352 }
353
354 TEST_F(TouchHandleTest, DragDefersOrientationChange) {
355 TouchHandle handle(this, TOUCH_HANDLE_RIGHT);
356 ASSERT_EQ(drawable().orientation, TOUCH_HANDLE_RIGHT);
357 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
358
359 MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
360 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
361 EXPECT_TRUE(IsDragging());
362
363 // Orientation changes will be deferred until the drag ends.
364 handle.SetOrientation(TOUCH_HANDLE_LEFT);
365 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
366
367 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
368 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
369 EXPECT_TRUE(GetAndResetHandleDragged());
370 EXPECT_TRUE(IsDragging());
371 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
372
373 event = MockMotionEvent(MockMotionEvent::ACTION_UP);
374 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
375 EXPECT_FALSE(GetAndResetHandleDragged());
376 EXPECT_FALSE(IsDragging());
377 EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
378 }
379
380 TEST_F(TouchHandleTest, DragDefersFade) {
381 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
382 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
383
384 MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
385 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
386 EXPECT_TRUE(IsDragging());
387
388 // Fade will be deferred until the drag ends.
389 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
390 EXPECT_FALSE(NeedsAnimate());
391 EXPECT_TRUE(drawable().visible);
392 EXPECT_EQ(1.f, drawable().alpha);
393
394 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
395 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
396 EXPECT_FALSE(NeedsAnimate());
397 EXPECT_TRUE(drawable().visible);
398
399 event = MockMotionEvent(MockMotionEvent::ACTION_UP);
400 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
401 EXPECT_FALSE(IsDragging());
402 EXPECT_TRUE(NeedsAnimate());
403
404 Animate(handle);
405 EXPECT_FALSE(drawable().visible);
406 EXPECT_EQ(0.f, drawable().alpha);
407 }
408
409 TEST_F(TouchHandleTest, DragTargettingUsesTouchSize) {
410 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
411 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
412
413 base::TimeTicks event_time = base::TimeTicks::Now();
414 const float kTouchSize = 24.f;
415 const float kOffset = kDefaultDrawableSize + kTouchSize / 2.001f;
416
417 MockMotionEvent event(
418 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
419 event.SetTouchMajor(0.f);
420 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
421 EXPECT_FALSE(IsDragging());
422
423 event.SetTouchMajor(kTouchSize / 2.f);
424 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
425 EXPECT_FALSE(IsDragging());
426
427 event.SetTouchMajor(kTouchSize);
428 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
429 EXPECT_TRUE(IsDragging());
430
431 event.SetTouchMajor(kTouchSize * 2.f);
432 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
433 EXPECT_TRUE(IsDragging());
434
435 // Ensure a touch size of 0 can still register a hit.
436 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN,
437 event_time,
438 kDefaultDrawableSize / 2.f,
439 kDefaultDrawableSize / 2.f);
440 event.SetTouchMajor(0);
441 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
442 EXPECT_TRUE(IsDragging());
443 }
444
445 TEST_F(TouchHandleTest, Tap) {
446 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
447 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
448
449 base::TimeTicks event_time = base::TimeTicks::Now();
450
451 // ACTION_CANCEL shouldn't trigger a tap.
452 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
453 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
454 event_time += base::TimeDelta::FromMilliseconds(50);
455 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
456 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
457 EXPECT_FALSE(GetAndResetHandleTapped());
458
459 // Long press shouldn't trigger a tap.
460 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
461 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
462 event_time += 2 * GetTapTimeout();
463 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
464 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
465 EXPECT_FALSE(GetAndResetHandleTapped());
466
467 // Only a brief tap within the slop region should trigger a tap.
468 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
469 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
470 event_time += GetTapTimeout() / 2;
471 event = MockMotionEvent(
472 MockMotionEvent::ACTION_MOVE, event_time, kDefaultTapSlop / 2.f, 0);
473 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
474 event = MockMotionEvent(
475 MockMotionEvent::ACTION_UP, event_time, kDefaultTapSlop / 2.f, 0);
476 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
477 EXPECT_TRUE(GetAndResetHandleTapped());
478
479 // Moving beyond the slop region shouldn't trigger a tap.
480 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
481 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
482 event_time += GetTapTimeout() / 2;
483 event = MockMotionEvent(
484 MockMotionEvent::ACTION_MOVE, event_time, kDefaultTapSlop * 2.f, 0);
485 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
486 event = MockMotionEvent(
487 MockMotionEvent::ACTION_UP, event_time, kDefaultTapSlop * 2.f, 0);
488 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
489 EXPECT_FALSE(GetAndResetHandleTapped());
490 }
491
492 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/input/touch_handle.cc ('k') | content/browser/renderer_host/input/touch_selection_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698