Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / input / touch_handle_unittest.cc
blob87d3a8c68a3764fcae480ecbfa3827f97cc17e83
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 "content/browser/renderer_host/input/touch_handle.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/events/test/mock_motion_event.h"
9 #include "ui/gfx/geometry/rect_f.h"
11 using ui::test::MockMotionEvent;
13 namespace content {
14 namespace {
16 const float kDefaultDrawableSize = 10.f;
18 struct MockDrawableData {
19 MockDrawableData()
20 : orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
21 alpha(0.f),
22 enabled(false),
23 visible(false),
24 rect(0, 0, kDefaultDrawableSize, kDefaultDrawableSize) {}
25 TouchHandleOrientation orientation;
26 float alpha;
27 bool enabled;
28 bool visible;
29 gfx::RectF rect;
32 class MockTouchHandleDrawable : public TouchHandleDrawable {
33 public:
34 explicit MockTouchHandleDrawable(MockDrawableData* data) : data_(data) {}
35 virtual ~MockTouchHandleDrawable() {}
37 virtual void SetEnabled(bool enabled) OVERRIDE { data_->enabled = enabled; }
39 virtual void SetOrientation(TouchHandleOrientation orientation) OVERRIDE {
40 data_->orientation = orientation;
43 virtual void SetAlpha(float alpha) OVERRIDE { data_->alpha = alpha; }
45 virtual void SetFocus(const gfx::PointF& position) OVERRIDE {
46 // Anchor focus to the top left of the rect (regardless of orientation).
47 data_->rect.set_origin(position);
50 virtual void SetVisible(bool visible) OVERRIDE { data_->visible = visible; }
52 virtual bool IntersectsWith(const gfx::RectF& rect) const OVERRIDE {
53 return data_->rect.Intersects(rect);
56 private:
57 MockDrawableData* data_;
60 } // namespace
62 class TouchHandleTest : public testing::Test, public TouchHandleClient {
63 public:
64 TouchHandleTest()
65 : dragging_(false),
66 dragged_(false),
67 tapped_(false),
68 needs_animate_(false) {}
70 virtual ~TouchHandleTest() {}
72 // TouchHandleClient implementation.
73 virtual void OnHandleDragBegin(const TouchHandle& handle) OVERRIDE {
74 dragging_ = true;
77 virtual void OnHandleDragUpdate(const TouchHandle& handle,
78 const gfx::PointF& new_position) OVERRIDE {
79 dragged_ = true;
80 drag_position_ = new_position;
83 virtual void OnHandleDragEnd(const TouchHandle& handle) OVERRIDE {
84 dragging_ = false;
87 virtual void OnHandleTapped(const TouchHandle& handle) OVERRIDE {
88 tapped_ = true;
91 virtual void SetNeedsAnimate() OVERRIDE { needs_animate_ = true; }
93 virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() OVERRIDE {
94 return scoped_ptr<TouchHandleDrawable>(
95 new MockTouchHandleDrawable(&drawable_data_));
98 void Animate(TouchHandle& handle) {
99 needs_animate_ = false;
100 base::TimeTicks now = base::TimeTicks::Now();
101 while (handle.Animate(now))
102 now += base::TimeDelta::FromMilliseconds(16);
105 bool GetAndResetHandleDragged() {
106 bool dragged = dragged_;
107 dragged_ = false;
108 return dragged;
111 bool GetAndResetHandleTapped() {
112 bool tapped = tapped_;
113 tapped_ = false;
114 return tapped;
117 bool GetAndResetNeedsAnimate() {
118 bool needs_animate = needs_animate_;
119 needs_animate_ = false;
120 return needs_animate;
123 bool IsDragging() const { return dragging_; }
124 const gfx::PointF& DragPosition() const { return drag_position_; }
125 bool NeedsAnimate() const { return needs_animate_; }
127 const MockDrawableData& drawable() { return drawable_data_; }
129 private:
130 gfx::PointF drag_position_;
131 bool dragging_;
132 bool dragged_;
133 bool tapped_;
134 bool needs_animate_;
136 MockDrawableData drawable_data_;
139 TEST_F(TouchHandleTest, Visibility) {
140 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
141 EXPECT_FALSE(drawable().visible);
143 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
144 EXPECT_TRUE(drawable().visible);
145 EXPECT_EQ(1.f, drawable().alpha);
147 handle.SetVisible(false, TouchHandle::ANIMATION_NONE);
148 EXPECT_FALSE(drawable().visible);
150 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
151 EXPECT_TRUE(drawable().visible);
152 EXPECT_EQ(1.f, drawable().alpha);
155 TEST_F(TouchHandleTest, VisibilityAnimation) {
156 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
157 ASSERT_FALSE(NeedsAnimate());
158 ASSERT_FALSE(drawable().visible);
159 ASSERT_EQ(0.f, drawable().alpha);
161 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
162 EXPECT_TRUE(NeedsAnimate());
163 EXPECT_TRUE(drawable().visible);
164 EXPECT_EQ(0.f, drawable().alpha);
166 Animate(handle);
167 EXPECT_TRUE(drawable().visible);
168 EXPECT_EQ(1.f, drawable().alpha);
170 ASSERT_FALSE(NeedsAnimate());
171 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
172 EXPECT_TRUE(NeedsAnimate());
173 EXPECT_TRUE(drawable().visible);
174 EXPECT_EQ(1.f, drawable().alpha);
176 Animate(handle);
177 EXPECT_FALSE(drawable().visible);
178 EXPECT_EQ(0.f, drawable().alpha);
180 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
181 EXPECT_EQ(1.f, drawable().alpha);
182 EXPECT_FALSE(GetAndResetNeedsAnimate());
183 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
184 EXPECT_EQ(1.f, drawable().alpha);
185 EXPECT_TRUE(GetAndResetNeedsAnimate());
186 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
187 EXPECT_EQ(1.f, drawable().alpha);
188 EXPECT_FALSE(GetAndResetNeedsAnimate());
191 TEST_F(TouchHandleTest, Orientation) {
192 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
193 EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
195 handle.SetOrientation(TOUCH_HANDLE_LEFT);
196 EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
198 handle.SetOrientation(TOUCH_HANDLE_RIGHT);
199 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
201 handle.SetOrientation(TOUCH_HANDLE_CENTER);
202 EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
205 TEST_F(TouchHandleTest, Position) {
206 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
207 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
209 gfx::PointF position;
210 EXPECT_EQ(gfx::PointF(), drawable().rect.origin());
212 position = gfx::PointF(7.3f, -3.7f);
213 handle.SetPosition(position);
214 EXPECT_EQ(position, drawable().rect.origin());
216 position = gfx::PointF(-7.3f, 3.7f);
217 handle.SetPosition(position);
218 EXPECT_EQ(position, drawable().rect.origin());
221 TEST_F(TouchHandleTest, PositionNotUpdatedWhileFadingOrInvisible) {
222 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
224 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
225 ASSERT_TRUE(drawable().visible);
226 ASSERT_FALSE(NeedsAnimate());
228 gfx::PointF old_position(7.3f, -3.7f);
229 handle.SetPosition(old_position);
230 ASSERT_EQ(old_position, drawable().rect.origin());
232 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
233 ASSERT_TRUE(NeedsAnimate());
235 gfx::PointF new_position(3.7f, -3.7f);
236 handle.SetPosition(new_position);
237 EXPECT_EQ(old_position, drawable().rect.origin());
238 EXPECT_TRUE(NeedsAnimate());
240 // While the handle is fading, the new position should not take affect.
241 base::TimeTicks now = base::TimeTicks::Now();
242 while (handle.Animate(now)) {
243 EXPECT_EQ(old_position, drawable().rect.origin());
244 now += base::TimeDelta::FromMilliseconds(16);
247 // Even after the animation terminates, the new position will not be pushed.
248 EXPECT_EQ(old_position, drawable().rect.origin());
250 // As soon as the handle becomes visible, the new position will be pushed.
251 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
252 EXPECT_EQ(new_position, drawable().rect.origin());
255 TEST_F(TouchHandleTest, Enabled) {
256 // A newly created handle defaults to enabled.
257 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
258 EXPECT_TRUE(drawable().enabled);
260 handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
261 EXPECT_TRUE(GetAndResetNeedsAnimate());
262 EXPECT_EQ(0.f, drawable().alpha);
263 handle.SetEnabled(false);
264 EXPECT_FALSE(drawable().enabled);
266 // Dragging should not be allowed while the handle is disabled.
267 base::TimeTicks event_time = base::TimeTicks::Now();
268 const float kOffset = kDefaultDrawableSize / 2.f;
269 MockMotionEvent event(
270 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
271 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
273 // Disabling mid-animation should cancel the animation.
274 handle.SetEnabled(true);
275 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
276 EXPECT_TRUE(drawable().visible);
277 EXPECT_TRUE(GetAndResetNeedsAnimate());
278 handle.SetEnabled(false);
279 EXPECT_FALSE(drawable().enabled);
280 EXPECT_FALSE(drawable().visible);
281 EXPECT_FALSE(handle.Animate(base::TimeTicks::Now()));
283 // Disabling mid-drag should cancel the drag.
284 handle.SetEnabled(true);
285 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
286 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
287 EXPECT_TRUE(IsDragging());
288 handle.SetEnabled(false);
289 EXPECT_FALSE(IsDragging());
290 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
293 TEST_F(TouchHandleTest, Drag) {
294 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
296 base::TimeTicks event_time = base::TimeTicks::Now();
297 const float kOffset = kDefaultDrawableSize / 2.f;
299 // The handle must be visible to trigger drag.
300 MockMotionEvent event(
301 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
302 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
303 EXPECT_FALSE(IsDragging());
304 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
306 // ACTION_DOWN must fall within the drawable region to trigger drag.
307 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 50, 50);
308 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
309 EXPECT_FALSE(IsDragging());
311 // Only ACTION_DOWN will trigger drag.
312 event = MockMotionEvent(
313 MockMotionEvent::ACTION_MOVE, event_time, kOffset, kOffset);
314 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
315 EXPECT_FALSE(IsDragging());
317 // Start the drag.
318 event = MockMotionEvent(
319 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
320 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
321 EXPECT_TRUE(IsDragging());
323 event = MockMotionEvent(
324 MockMotionEvent::ACTION_MOVE, event_time, kOffset + 10, kOffset + 15);
325 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
326 EXPECT_TRUE(GetAndResetHandleDragged());
327 EXPECT_TRUE(IsDragging());
328 EXPECT_EQ(gfx::PointF(10, 15), DragPosition());
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());
337 event = MockMotionEvent(MockMotionEvent::ACTION_UP);
338 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
339 EXPECT_FALSE(GetAndResetHandleDragged());
340 EXPECT_FALSE(IsDragging());
342 // Non-ACTION_DOWN events after the drag has terminated should not be handled.
343 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL);
344 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
347 TEST_F(TouchHandleTest, DragDefersOrientationChange) {
348 TouchHandle handle(this, TOUCH_HANDLE_RIGHT);
349 ASSERT_EQ(drawable().orientation, TOUCH_HANDLE_RIGHT);
350 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
352 MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
353 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
354 EXPECT_TRUE(IsDragging());
356 // Orientation changes will be deferred until the drag ends.
357 handle.SetOrientation(TOUCH_HANDLE_LEFT);
358 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
360 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
361 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
362 EXPECT_TRUE(GetAndResetHandleDragged());
363 EXPECT_TRUE(IsDragging());
364 EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
366 event = MockMotionEvent(MockMotionEvent::ACTION_UP);
367 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
368 EXPECT_FALSE(GetAndResetHandleDragged());
369 EXPECT_FALSE(IsDragging());
370 EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
373 TEST_F(TouchHandleTest, DragDefersFade) {
374 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
375 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
377 MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
378 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
379 EXPECT_TRUE(IsDragging());
381 // Fade will be deferred until the drag ends.
382 handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
383 EXPECT_FALSE(NeedsAnimate());
384 EXPECT_TRUE(drawable().visible);
385 EXPECT_EQ(1.f, drawable().alpha);
387 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
388 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
389 EXPECT_FALSE(NeedsAnimate());
390 EXPECT_TRUE(drawable().visible);
392 event = MockMotionEvent(MockMotionEvent::ACTION_UP);
393 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
394 EXPECT_FALSE(IsDragging());
395 EXPECT_TRUE(NeedsAnimate());
397 Animate(handle);
398 EXPECT_FALSE(drawable().visible);
399 EXPECT_EQ(0.f, drawable().alpha);
402 TEST_F(TouchHandleTest, DragTargettingUsesTouchSize) {
403 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
404 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
406 base::TimeTicks event_time = base::TimeTicks::Now();
407 const float kTouchSize = 24.f;
408 const float kOffset = kDefaultDrawableSize + kTouchSize / 2.001f;
410 MockMotionEvent event(
411 MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
412 event.SetTouchMajor(0.f);
413 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
414 EXPECT_FALSE(IsDragging());
416 event.SetTouchMajor(kTouchSize / 2.f);
417 EXPECT_FALSE(handle.WillHandleTouchEvent(event));
418 EXPECT_FALSE(IsDragging());
420 event.SetTouchMajor(kTouchSize);
421 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
422 EXPECT_TRUE(IsDragging());
424 event.SetTouchMajor(kTouchSize * 2.f);
425 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
426 EXPECT_TRUE(IsDragging());
428 // Ensure a touch size of 0 can still register a hit.
429 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN,
430 event_time,
431 kDefaultDrawableSize / 2.f,
432 kDefaultDrawableSize / 2.f);
433 event.SetTouchMajor(0);
434 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
435 EXPECT_TRUE(IsDragging());
438 TEST_F(TouchHandleTest, Tap) {
439 TouchHandle handle(this, TOUCH_HANDLE_CENTER);
440 handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
442 base::TimeTicks event_time = base::TimeTicks::Now();
444 // ACTION_CANCEL shouldn't trigger a tap.
445 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
446 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
447 event_time += base::TimeDelta::FromMilliseconds(50);
448 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
449 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
450 EXPECT_FALSE(GetAndResetHandleTapped());
452 // Long press shouldn't trigger a tap.
453 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
454 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
455 event_time += base::TimeDelta::FromMilliseconds(500);
456 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
457 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
458 EXPECT_FALSE(GetAndResetHandleTapped());
460 // Only a brief tap should trigger a tap.
461 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
462 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
463 event_time += base::TimeDelta::FromMilliseconds(50);
464 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
465 EXPECT_TRUE(handle.WillHandleTouchEvent(event));
466 EXPECT_TRUE(GetAndResetHandleTapped());
469 } // namespace content