| Index: content/browser/renderer_host/input/touch_handle_unittest.cc
|
| diff --git a/content/browser/renderer_host/input/touch_handle_unittest.cc b/content/browser/renderer_host/input/touch_handle_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bdbfca587c0710efe6d44cacbcd684b1210a70a6
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/input/touch_handle_unittest.cc
|
| @@ -0,0 +1,375 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/renderer_host/input/touch_handle.h"
|
| +
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "ui/events/test/mock_motion_event.h"
|
| +#include "ui/gfx/geometry/rect_f.h"
|
| +
|
| +using ui::test::MockMotionEvent;
|
| +
|
| +namespace content {
|
| +namespace {
|
| +
|
| +const float kDefaultDrawableSize = 10.f;
|
| +
|
| +struct MockDrawableData {
|
| + MockDrawableData()
|
| + : orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
|
| + alpha(0.f),
|
| + visible(false),
|
| + rect(0, 0, kDefaultDrawableSize, kDefaultDrawableSize) {}
|
| + TouchHandleOrientation orientation;
|
| + float alpha;
|
| + bool visible;
|
| + gfx::RectF rect;
|
| +};
|
| +
|
| +class MockTouchHandleDrawable : public TouchHandleDrawable {
|
| + public:
|
| + explicit MockTouchHandleDrawable(MockDrawableData& data) : data_(data) {}
|
| + virtual ~MockTouchHandleDrawable() {}
|
| +
|
| + virtual void SetOrientation(TouchHandleOrientation orientation) OVERRIDE {
|
| + data_.orientation = orientation;
|
| + }
|
| +
|
| + virtual void SetAlpha(float alpha) OVERRIDE { data_.alpha = alpha; }
|
| +
|
| + virtual void SetFocus(const gfx::PointF& position) OVERRIDE {
|
| + // Anchor focus to the top left of the rect (regardless of orientation).
|
| + data_.rect.set_origin(position);
|
| + }
|
| +
|
| + virtual void SetVisible(bool visible) OVERRIDE { data_.visible = visible; }
|
| +
|
| + virtual bool ContainsPoint(const gfx::PointF& point) const OVERRIDE {
|
| + return data_.rect.Contains(point);
|
| + }
|
| +
|
| + private:
|
| + MockDrawableData& data_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +class TouchHandleTest : public testing::Test, public TouchHandleClient {
|
| + public:
|
| + TouchHandleTest()
|
| + : dragging_(false),
|
| + dragged_(false),
|
| + tapped_(false),
|
| + needs_animate_(false) {}
|
| +
|
| + virtual ~TouchHandleTest() {}
|
| +
|
| + // TouchHandleClient implementation.
|
| + virtual void OnHandleDragBegin(const TouchHandle& handle) OVERRIDE {
|
| + dragging_ = true;
|
| + }
|
| +
|
| + virtual void OnHandleDragUpdate(const TouchHandle& handle,
|
| + const gfx::PointF& new_position) OVERRIDE {
|
| + dragged_ = true;
|
| + drag_position_ = new_position;
|
| + }
|
| +
|
| + virtual void OnHandleDragEnd(const TouchHandle& handle) OVERRIDE {
|
| + dragging_ = false;
|
| + }
|
| +
|
| + virtual void OnHandleTapped(const TouchHandle& handle) OVERRIDE {
|
| + tapped_ = true;
|
| + }
|
| +
|
| + virtual void SetNeedsAnimate() OVERRIDE { needs_animate_ = true; }
|
| +
|
| + virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() OVERRIDE {
|
| + return scoped_ptr<TouchHandleDrawable>(
|
| + new MockTouchHandleDrawable(drawable_data_));
|
| + }
|
| +
|
| + void Animate(TouchHandle& handle) {
|
| + needs_animate_ = false;
|
| + base::TimeTicks now = base::TimeTicks::Now();
|
| + while (handle.Animate(now))
|
| + now += base::TimeDelta::FromMilliseconds(16);
|
| + }
|
| +
|
| + bool GetAndResetHandleDragged() {
|
| + bool dragged = dragged_;
|
| + dragged_ = false;
|
| + return dragged;
|
| + }
|
| +
|
| + bool GetAndResetHandleTapped() {
|
| + bool tapped = tapped_;
|
| + tapped_ = false;
|
| + return tapped;
|
| + }
|
| +
|
| + bool IsDragging() const { return dragging_; }
|
| + const gfx::PointF& DragPosition() const { return drag_position_; }
|
| + bool NeedsAnimate() const { return needs_animate_; }
|
| +
|
| + const MockDrawableData& drawable() { return drawable_data_; }
|
| +
|
| + private:
|
| + gfx::PointF drag_position_;
|
| + bool dragging_;
|
| + bool dragged_;
|
| + bool tapped_;
|
| + bool needs_animate_;
|
| +
|
| + MockDrawableData drawable_data_;
|
| +};
|
| +
|
| +TEST_F(TouchHandleTest, Visibility) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| + EXPECT_FALSE(drawable().visible);
|
| +
|
| + handle.SetVisible(true);
|
| + EXPECT_TRUE(drawable().visible);
|
| + EXPECT_EQ(1.f, drawable().alpha);
|
| +
|
| + handle.SetVisible(false);
|
| + EXPECT_FALSE(drawable().visible);
|
| +
|
| + handle.SetVisible(true);
|
| + EXPECT_TRUE(drawable().visible);
|
| + EXPECT_EQ(1.f, drawable().alpha);
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, VisibilityAnimation) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| + ASSERT_FALSE(NeedsAnimate());
|
| + ASSERT_FALSE(drawable().visible);
|
| + ASSERT_EQ(0.f, drawable().alpha);
|
| +
|
| + handle.SetVisibleAnimated(true);
|
| + EXPECT_TRUE(NeedsAnimate());
|
| + EXPECT_TRUE(drawable().visible);
|
| + EXPECT_EQ(0.f, drawable().alpha);
|
| +
|
| + Animate(handle);
|
| + EXPECT_TRUE(drawable().visible);
|
| + EXPECT_EQ(1.f, drawable().alpha);
|
| +
|
| + ASSERT_FALSE(NeedsAnimate());
|
| + handle.SetVisibleAnimated(false);
|
| + EXPECT_TRUE(NeedsAnimate());
|
| + EXPECT_TRUE(drawable().visible);
|
| + EXPECT_EQ(1.f, drawable().alpha);
|
| +
|
| + Animate(handle);
|
| + EXPECT_FALSE(drawable().visible);
|
| + EXPECT_EQ(0.f, drawable().alpha);
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, Orientation) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| + EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
|
| +
|
| + handle.SetOrientation(TOUCH_HANDLE_LEFT);
|
| + EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
|
| +
|
| + handle.SetOrientation(TOUCH_HANDLE_RIGHT);
|
| + EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
|
| +
|
| + handle.SetOrientation(TOUCH_HANDLE_CENTER);
|
| + EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, Position) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| +
|
| + gfx::PointF position;
|
| + EXPECT_EQ(gfx::PointF(), drawable().rect.origin());
|
| +
|
| + position = gfx::PointF(7.3, -3.7);
|
| + handle.SetPosition(position);
|
| + EXPECT_EQ(position, drawable().rect.origin());
|
| +
|
| + position = gfx::PointF(-7.3, 3.7);
|
| + handle.SetPosition(position);
|
| + EXPECT_EQ(position, drawable().rect.origin());
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, PositionNotUpdatedWhileFading) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| +
|
| + handle.SetVisible(true);
|
| + ASSERT_TRUE(drawable().visible);
|
| + ASSERT_FALSE(NeedsAnimate());
|
| +
|
| + gfx::PointF visible_position(7.3, -3.7);
|
| + handle.SetPosition(visible_position);
|
| + ASSERT_EQ(visible_position, drawable().rect.origin());
|
| +
|
| + handle.SetVisibleAnimated(false);
|
| + ASSERT_TRUE(NeedsAnimate());
|
| +
|
| + gfx::PointF invisible_position(3.7, -3.7);
|
| + handle.SetPosition(invisible_position);
|
| + EXPECT_NE(invisible_position, drawable().rect.origin());
|
| + EXPECT_EQ(visible_position, drawable().rect.origin());
|
| + EXPECT_TRUE(NeedsAnimate());
|
| +
|
| + Animate(handle);
|
| + EXPECT_NE(invisible_position, drawable().rect.origin());
|
| + EXPECT_EQ(visible_position, drawable().rect.origin());
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, Hide) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| +
|
| + handle.SetVisible(true);
|
| + EXPECT_TRUE(drawable().visible);
|
| +
|
| + handle.Hide();
|
| + EXPECT_FALSE(drawable().visible);
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, Drag) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| +
|
| + base::TimeTicks event_time = base::TimeTicks::Now();
|
| + const float kOffset = kDefaultDrawableSize / 2.f;
|
| +
|
| + // The handle must be visible to trigger drag.
|
| + MockMotionEvent event(
|
| + MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
|
| + EXPECT_FALSE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(IsDragging());
|
| + handle.SetVisible(true);
|
| +
|
| + // ACTION_DOWN must fall within the drawable region to trigger drag.
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 50, 50);
|
| + EXPECT_FALSE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(IsDragging());
|
| +
|
| + // Only ACTION_DOWN will trigger drag.
|
| + event = MockMotionEvent(
|
| + MockMotionEvent::ACTION_MOVE, event_time, kOffset, kOffset);
|
| + EXPECT_FALSE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(IsDragging());
|
| +
|
| + // Start the drag.
|
| + event = MockMotionEvent(
|
| + MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(IsDragging());
|
| +
|
| + event = MockMotionEvent(
|
| + MockMotionEvent::ACTION_MOVE, event_time, kOffset + 10, kOffset + 15);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(GetAndResetHandleDragged());
|
| + EXPECT_TRUE(IsDragging());
|
| + EXPECT_EQ(gfx::PointF(10, 15), DragPosition());
|
| +
|
| + event = MockMotionEvent(
|
| + MockMotionEvent::ACTION_MOVE, event_time, kOffset - 10, kOffset - 15);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(GetAndResetHandleDragged());
|
| + EXPECT_TRUE(IsDragging());
|
| + EXPECT_EQ(gfx::PointF(-10, -15), DragPosition());
|
| +
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_UP);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(GetAndResetHandleDragged());
|
| + EXPECT_FALSE(IsDragging());
|
| +
|
| + // Non-ACTION_DOWN events after the drag has terminated should not be handled.
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL);
|
| + EXPECT_FALSE(handle.WillHandleTouchEvent(event));
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, DragDefersOrientationChange) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_RIGHT);
|
| + ASSERT_EQ(drawable().orientation, TOUCH_HANDLE_RIGHT);
|
| + handle.SetVisible(true);
|
| +
|
| + MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(IsDragging());
|
| +
|
| + // Orientation changes will be deferred until the drag ends.
|
| + handle.SetOrientation(TOUCH_HANDLE_LEFT);
|
| + EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
|
| +
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(GetAndResetHandleDragged());
|
| + EXPECT_TRUE(IsDragging());
|
| + EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
|
| +
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_UP);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(GetAndResetHandleDragged());
|
| + EXPECT_FALSE(IsDragging());
|
| + EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, DragDefersFade) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| + handle.SetVisible(true);
|
| +
|
| + MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(IsDragging());
|
| +
|
| + // Fade will be deferred until the drag ends.
|
| + handle.SetVisibleAnimated(false);
|
| + EXPECT_FALSE(NeedsAnimate());
|
| + EXPECT_TRUE(drawable().visible);
|
| + EXPECT_EQ(1.f, drawable().alpha);
|
| +
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(NeedsAnimate());
|
| + EXPECT_TRUE(drawable().visible);
|
| +
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_UP);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(IsDragging());
|
| + EXPECT_TRUE(NeedsAnimate());
|
| +
|
| + Animate(handle);
|
| + EXPECT_FALSE(drawable().visible);
|
| + EXPECT_EQ(0.f, drawable().alpha);
|
| +}
|
| +
|
| +TEST_F(TouchHandleTest, Tap) {
|
| + TouchHandle handle(this, TOUCH_HANDLE_CENTER);
|
| + handle.SetVisible(true);
|
| +
|
| + base::TimeTicks event_time = base::TimeTicks::Now();
|
| +
|
| + // ACTION_CANCEL shouldn't trigger a tap.
|
| + MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + event_time += base::TimeDelta::FromMilliseconds(50);
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(GetAndResetHandleTapped());
|
| +
|
| + // Long press shouldn't trigger a tap.
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + event_time += base::TimeDelta::FromMilliseconds(500);
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_FALSE(GetAndResetHandleTapped());
|
| +
|
| + // Only a brief tap should trigger a tap.
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + event_time += base::TimeDelta::FromMilliseconds(50);
|
| + event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
|
| + EXPECT_TRUE(handle.WillHandleTouchEvent(event));
|
| + EXPECT_TRUE(GetAndResetHandleTapped());
|
| +}
|
| +
|
| +} // namespace content
|
|
|