blob: e7c4947619941d9404f560f2a1bf1c0cc458d8a9 [file] [log] [blame]
// Copyright 2013 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/synthetic_gesture_controller.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/time/time.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
#include "content/browser/renderer_host/input/synthetic_pointer_action.h"
#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h"
#include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
#include "content/browser/renderer_host/input/synthetic_touch_pointer.h"
#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h"
#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector2d_f.h"
using blink::WebInputEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
namespace content {
namespace {
const int kFlushInputRateInMs = 16;
const int kPointerAssumedStoppedTimeMs = 43;
const float kTouchSlopInDips = 7.0f;
const float kMinScalingSpanInDips = 27.5f;
const int kTouchPointersLength = 16;
enum TouchGestureType { TOUCH_SCROLL, TOUCH_DRAG };
class MockSyntheticGesture : public SyntheticGesture {
public:
MockSyntheticGesture(bool* finished, int num_steps)
: finished_(finished),
num_steps_(num_steps),
step_count_(0) {
*finished_ = false;
}
~MockSyntheticGesture() override {}
Result ForwardInputEvents(const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) override {
step_count_++;
if (step_count_ == num_steps_) {
*finished_ = true;
return SyntheticGesture::GESTURE_FINISHED;
} else if (step_count_ > num_steps_) {
*finished_ = true;
// Return arbitrary failure.
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
}
return SyntheticGesture::GESTURE_RUNNING;
}
protected:
bool* finished_;
int num_steps_;
int step_count_;
};
class MockSyntheticGestureTarget : public SyntheticGestureTarget {
public:
MockSyntheticGestureTarget()
: flush_requested_(false),
pointer_assumed_stopped_time_ms_(kPointerAssumedStoppedTimeMs) {}
~MockSyntheticGestureTarget() override {}
// SyntheticGestureTarget:
void DispatchInputEventToPlatform(const WebInputEvent& event) override {}
void SetNeedsFlush() override { flush_requested_ = true; }
SyntheticGestureParams::GestureSourceType
GetDefaultSyntheticGestureSourceType() const override {
return SyntheticGestureParams::TOUCH_INPUT;
}
base::TimeDelta PointerAssumedStoppedTime() const override {
return base::TimeDelta::FromMilliseconds(pointer_assumed_stopped_time_ms_);
}
void set_pointer_assumed_stopped_time_ms(int time_ms) {
pointer_assumed_stopped_time_ms_ = time_ms;
}
float GetTouchSlopInDips() const override { return kTouchSlopInDips; }
float GetMinScalingSpanInDips() const override {
return kMinScalingSpanInDips;
}
bool flush_requested() const { return flush_requested_; }
void ClearFlushRequest() { flush_requested_ = false; }
private:
bool flush_requested_;
int pointer_assumed_stopped_time_ms_;
};
class MockMoveGestureTarget : public MockSyntheticGestureTarget {
public:
MockMoveGestureTarget() : total_abs_move_distance_length_(0) {}
~MockMoveGestureTarget() override {}
gfx::Vector2dF start_to_end_distance() const {
return start_to_end_distance_;
}
float total_abs_move_distance_length() const {
return total_abs_move_distance_length_;
}
protected:
gfx::Vector2dF start_to_end_distance_;
float total_abs_move_distance_length_;
};
class MockScrollMouseTarget : public MockMoveGestureTarget {
public:
MockScrollMouseTarget() {}
~MockScrollMouseTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_EQ(event.type, WebInputEvent::MouseWheel);
const WebMouseWheelEvent& mouse_wheel_event =
static_cast<const WebMouseWheelEvent&>(event);
gfx::Vector2dF delta(mouse_wheel_event.deltaX, mouse_wheel_event.deltaY);
start_to_end_distance_ += delta;
total_abs_move_distance_length_ += delta.Length();
}
};
class MockMoveTouchTarget : public MockMoveGestureTarget {
public:
MockMoveTouchTarget() : started_(false) {}
~MockMoveTouchTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
ASSERT_EQ(touch_event.touchesLength, 1U);
if (!started_) {
ASSERT_EQ(touch_event.type, WebInputEvent::TouchStart);
start_.SetPoint(touch_event.touches[0].position.x,
touch_event.touches[0].position.y);
last_touch_point_ = gfx::PointF(start_);
started_ = true;
} else {
ASSERT_NE(touch_event.type, WebInputEvent::TouchStart);
ASSERT_NE(touch_event.type, WebInputEvent::TouchCancel);
gfx::PointF touch_point(touch_event.touches[0].position.x,
touch_event.touches[0].position.y);
gfx::Vector2dF delta = touch_point - last_touch_point_;
total_abs_move_distance_length_ += delta.Length();
if (touch_event.type == WebInputEvent::TouchEnd)
start_to_end_distance_ = touch_point - gfx::PointF(start_);
last_touch_point_ = touch_point;
}
}
protected:
gfx::Point start_;
gfx::PointF last_touch_point_;
bool started_;
};
class MockDragMouseTarget : public MockMoveGestureTarget {
public:
MockDragMouseTarget() : started_(false) {}
~MockDragMouseTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isMouseEventType(event.type));
const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event);
if (!started_) {
EXPECT_EQ(mouse_event.button, WebMouseEvent::Button::Left);
EXPECT_EQ(mouse_event.clickCount, 1);
EXPECT_EQ(mouse_event.type, WebInputEvent::MouseDown);
start_.SetPoint(mouse_event.x, mouse_event.y);
last_mouse_point_ = start_;
started_ = true;
} else {
EXPECT_EQ(mouse_event.button, WebMouseEvent::Button::Left);
ASSERT_NE(mouse_event.type, WebInputEvent::MouseDown);
gfx::PointF mouse_point(mouse_event.x, mouse_event.y);
gfx::Vector2dF delta = mouse_point - last_mouse_point_;
total_abs_move_distance_length_ += delta.Length();
if (mouse_event.type == WebInputEvent::MouseUp)
start_to_end_distance_ = mouse_point - start_;
last_mouse_point_ = mouse_point;
}
}
private:
bool started_;
gfx::PointF start_, last_mouse_point_;
};
class MockSyntheticTouchscreenPinchTouchTarget
: public MockSyntheticGestureTarget {
public:
enum ZoomDirection {
ZOOM_DIRECTION_UNKNOWN,
ZOOM_IN,
ZOOM_OUT
};
MockSyntheticTouchscreenPinchTouchTarget()
: initial_pointer_distance_(0),
last_pointer_distance_(0),
zoom_direction_(ZOOM_DIRECTION_UNKNOWN),
started_(false) {}
~MockSyntheticTouchscreenPinchTouchTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
ASSERT_EQ(touch_event.touchesLength, 2U);
if (!started_) {
ASSERT_EQ(touch_event.type, WebInputEvent::TouchStart);
start_0_ = gfx::PointF(touch_event.touches[0].position);
start_1_ = gfx::PointF(touch_event.touches[1].position);
last_pointer_distance_ = (start_0_ - start_1_).Length();
initial_pointer_distance_ = last_pointer_distance_;
EXPECT_GE(initial_pointer_distance_, GetMinScalingSpanInDips());
started_ = true;
} else {
ASSERT_NE(touch_event.type, WebInputEvent::TouchStart);
ASSERT_NE(touch_event.type, WebInputEvent::TouchCancel);
gfx::PointF current_0 = gfx::PointF(touch_event.touches[0].position);
gfx::PointF current_1 = gfx::PointF(touch_event.touches[1].position);
float pointer_distance = (current_0 - current_1).Length();
if (last_pointer_distance_ != pointer_distance) {
if (zoom_direction_ == ZOOM_DIRECTION_UNKNOWN)
zoom_direction_ =
ComputeZoomDirection(last_pointer_distance_, pointer_distance);
else
EXPECT_EQ(
zoom_direction_,
ComputeZoomDirection(last_pointer_distance_, pointer_distance));
}
last_pointer_distance_ = pointer_distance;
}
}
SyntheticGestureParams::GestureSourceType
GetDefaultSyntheticGestureSourceType() const override {
return SyntheticGestureParams::TOUCH_INPUT;
}
ZoomDirection zoom_direction() const { return zoom_direction_; }
float ComputeScaleFactor() const {
switch (zoom_direction_) {
case ZOOM_IN:
return last_pointer_distance_ /
(initial_pointer_distance_ + 2 * GetTouchSlopInDips());
case ZOOM_OUT:
return last_pointer_distance_ /
(initial_pointer_distance_ - 2 * GetTouchSlopInDips());
case ZOOM_DIRECTION_UNKNOWN:
return 1.0f;
default:
NOTREACHED();
return 0.0f;
}
}
private:
ZoomDirection ComputeZoomDirection(float last_pointer_distance,
float current_pointer_distance) {
DCHECK_NE(last_pointer_distance, current_pointer_distance);
return last_pointer_distance < current_pointer_distance ? ZOOM_IN
: ZOOM_OUT;
}
float initial_pointer_distance_;
float last_pointer_distance_;
ZoomDirection zoom_direction_;
gfx::PointF start_0_;
gfx::PointF start_1_;
bool started_;
};
class MockSyntheticTouchpadPinchTouchTarget
: public MockSyntheticGestureTarget {
public:
enum ZoomDirection { ZOOM_DIRECTION_UNKNOWN, ZOOM_IN, ZOOM_OUT };
MockSyntheticTouchpadPinchTouchTarget()
: zoom_direction_(ZOOM_DIRECTION_UNKNOWN),
started_(false),
ended_(false),
scale_factor_(1.0f) {}
~MockSyntheticTouchpadPinchTouchTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
EXPECT_TRUE(WebInputEvent::isGestureEventType(event.type));
const blink::WebGestureEvent& gesture_event =
static_cast<const blink::WebGestureEvent&>(event);
if (gesture_event.type == WebInputEvent::GesturePinchBegin) {
EXPECT_FALSE(started_);
EXPECT_FALSE(ended_);
started_ = true;
} else if (gesture_event.type == WebInputEvent::GesturePinchEnd) {
EXPECT_TRUE(started_);
EXPECT_FALSE(ended_);
ended_ = true;
} else {
EXPECT_EQ(WebInputEvent::GesturePinchUpdate, gesture_event.type);
EXPECT_TRUE(started_);
EXPECT_FALSE(ended_);
const float scale = gesture_event.data.pinchUpdate.scale;
if (scale != 1.0f) {
if (zoom_direction_ == ZOOM_DIRECTION_UNKNOWN) {
zoom_direction_ = scale > 1.0f ? ZOOM_IN : ZOOM_OUT;
} else if (zoom_direction_ == ZOOM_IN) {
EXPECT_GT(scale, 1.0f);
} else {
EXPECT_EQ(ZOOM_OUT, zoom_direction_);
EXPECT_LT(scale, 1.0f);
}
scale_factor_ *= scale;
}
}
}
SyntheticGestureParams::GestureSourceType
GetDefaultSyntheticGestureSourceType() const override {
return SyntheticGestureParams::MOUSE_INPUT;
}
ZoomDirection zoom_direction() const { return zoom_direction_; }
float scale_factor() const { return scale_factor_; }
private:
ZoomDirection zoom_direction_;
bool started_;
bool ended_;
float scale_factor_;
};
class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget {
public:
MockSyntheticTapGestureTarget() : state_(NOT_STARTED) {}
~MockSyntheticTapGestureTarget() override {}
bool GestureFinished() const { return state_ == FINISHED; }
gfx::PointF position() const { return position_; }
base::TimeDelta GetDuration() const { return stop_time_ - start_time_; }
protected:
enum GestureState {
NOT_STARTED,
STARTED,
FINISHED
};
gfx::PointF position_;
base::TimeDelta start_time_;
base::TimeDelta stop_time_;
GestureState state_;
};
class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget {
public:
MockSyntheticTapTouchTarget() {}
~MockSyntheticTapTouchTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
ASSERT_EQ(touch_event.touchesLength, 1U);
switch (state_) {
case NOT_STARTED:
EXPECT_EQ(touch_event.type, WebInputEvent::TouchStart);
position_ = gfx::PointF(touch_event.touches[0].position);
start_time_ = base::TimeDelta::FromMilliseconds(
static_cast<int64_t>(touch_event.timeStampSeconds * 1000));
state_ = STARTED;
break;
case STARTED:
EXPECT_EQ(touch_event.type, WebInputEvent::TouchEnd);
EXPECT_EQ(position_, gfx::PointF(touch_event.touches[0].position));
stop_time_ = base::TimeDelta::FromMilliseconds(
static_cast<int64_t>(touch_event.timeStampSeconds * 1000));
state_ = FINISHED;
break;
case FINISHED:
EXPECT_FALSE(true);
break;
}
}
};
class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
public:
MockSyntheticTapMouseTarget() {}
~MockSyntheticTapMouseTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isMouseEventType(event.type));
const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event);
switch (state_) {
case NOT_STARTED:
EXPECT_EQ(mouse_event.type, WebInputEvent::MouseDown);
EXPECT_EQ(mouse_event.button, WebMouseEvent::Button::Left);
EXPECT_EQ(mouse_event.clickCount, 1);
position_ = gfx::PointF(mouse_event.x, mouse_event.y);
start_time_ = base::TimeDelta::FromMilliseconds(
static_cast<int64_t>(mouse_event.timeStampSeconds * 1000));
state_ = STARTED;
break;
case STARTED:
EXPECT_EQ(mouse_event.type, WebInputEvent::MouseUp);
EXPECT_EQ(mouse_event.button, WebMouseEvent::Button::Left);
EXPECT_EQ(mouse_event.clickCount, 1);
EXPECT_EQ(position_, gfx::PointF(mouse_event.x, mouse_event.y));
stop_time_ = base::TimeDelta::FromMilliseconds(
static_cast<int64_t>(mouse_event.timeStampSeconds * 1000));
state_ = FINISHED;
break;
case FINISHED:
EXPECT_FALSE(true);
break;
}
}
};
class MockSyntheticPointerActionTarget : public MockSyntheticGestureTarget {
public:
MockSyntheticPointerActionTarget() {}
~MockSyntheticPointerActionTarget() override {}
gfx::PointF positions(int index) const { return positions_[index]; }
int indexes(int index) const { return indexes_[index]; }
WebTouchPoint::State states(int index) { return states_[index]; }
unsigned touch_length() const { return touch_length_; }
WebInputEvent::Type type() const { return type_; }
protected:
gfx::PointF positions_[kTouchPointersLength];
unsigned touch_length_;
int indexes_[kTouchPointersLength];
WebTouchPoint::State states_[kTouchPointersLength];
WebInputEvent::Type type_;
};
class MockSyntheticPointerTouchActionTarget
: public MockSyntheticPointerActionTarget {
public:
MockSyntheticPointerTouchActionTarget() {}
~MockSyntheticPointerTouchActionTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
type_ = touch_event.type;
for (size_t i = 0; i < touch_event.touchesLength; ++i) {
indexes_[i] = touch_event.touches[i].id;
positions_[i] = gfx::PointF(touch_event.touches[i].position);
states_[i] = touch_event.touches[i].state;
}
touch_length_ = touch_event.touchesLength;
}
};
class SyntheticGestureControllerTestBase {
public:
SyntheticGestureControllerTestBase() {}
~SyntheticGestureControllerTestBase() {}
protected:
template<typename MockGestureTarget>
void CreateControllerAndTarget() {
target_ = new MockGestureTarget();
controller_.reset(new SyntheticGestureController(
std::unique_ptr<SyntheticGestureTarget>(target_)));
}
void QueueSyntheticGesture(std::unique_ptr<SyntheticGesture> gesture) {
controller_->QueueSyntheticGesture(
std::move(gesture),
base::Bind(
&SyntheticGestureControllerTestBase::OnSyntheticGestureCompleted,
base::Unretained(this)));
}
void FlushInputUntilComplete() {
while (target_->flush_requested()) {
while (target_->flush_requested()) {
target_->ClearFlushRequest();
time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs);
controller_->Flush(time_);
}
controller_->OnDidFlushInput();
}
}
void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
DCHECK_NE(result, SyntheticGesture::GESTURE_RUNNING);
if (result == SyntheticGesture::GESTURE_FINISHED)
num_success_++;
else
num_failure_++;
}
base::TimeDelta GetTotalTime() const { return time_ - start_time_; }
MockSyntheticGestureTarget* target_;
std::unique_ptr<SyntheticGestureController> controller_;
base::TimeTicks start_time_;
base::TimeTicks time_;
int num_success_;
int num_failure_;
};
class SyntheticGestureControllerTest
: public SyntheticGestureControllerTestBase,
public testing::Test {
protected:
void SetUp() override {
start_time_ = base::TimeTicks::Now();
time_ = start_time_;
num_success_ = 0;
num_failure_ = 0;
}
void TearDown() override {
controller_.reset();
target_ = nullptr;
time_ = base::TimeTicks();
}
};
class SyntheticGestureControllerTestWithParam
: public SyntheticGestureControllerTestBase,
public testing::TestWithParam<bool> {
protected:
void SetUp() override {
start_time_ = base::TimeTicks::Now();
time_ = start_time_;
num_success_ = 0;
num_failure_ = 0;
}
void TearDown() override {
controller_.reset();
target_ = nullptr;
time_ = base::TimeTicks();
}
};
TEST_F(SyntheticGestureControllerTest, SingleGesture) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
bool finished = false;
std::unique_ptr<MockSyntheticGesture> gesture(
new MockSyntheticGesture(&finished, 3));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
EXPECT_TRUE(finished);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
}
TEST_F(SyntheticGestureControllerTest, GestureFailed) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
bool finished = false;
std::unique_ptr<MockSyntheticGesture> gesture(
new MockSyntheticGesture(&finished, 0));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
EXPECT_TRUE(finished);
EXPECT_EQ(1, num_failure_);
EXPECT_EQ(0, num_success_);
}
TEST_F(SyntheticGestureControllerTest, SuccessiveGestures) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
bool finished_1 = false;
std::unique_ptr<MockSyntheticGesture> gesture_1(
new MockSyntheticGesture(&finished_1, 2));
bool finished_2 = false;
std::unique_ptr<MockSyntheticGesture> gesture_2(
new MockSyntheticGesture(&finished_2, 4));
// Queue first gesture and wait for it to finish
QueueSyntheticGesture(std::move(gesture_1));
FlushInputUntilComplete();
EXPECT_TRUE(finished_1);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
// Queue second gesture.
QueueSyntheticGesture(std::move(gesture_2));
FlushInputUntilComplete();
EXPECT_TRUE(finished_2);
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
}
TEST_F(SyntheticGestureControllerTest, TwoGesturesInFlight) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
bool finished_1 = false;
std::unique_ptr<MockSyntheticGesture> gesture_1(
new MockSyntheticGesture(&finished_1, 2));
bool finished_2 = false;
std::unique_ptr<MockSyntheticGesture> gesture_2(
new MockSyntheticGesture(&finished_2, 4));
QueueSyntheticGesture(std::move(gesture_1));
QueueSyntheticGesture(std::move(gesture_2));
FlushInputUntilComplete();
EXPECT_TRUE(finished_1);
EXPECT_TRUE(finished_2);
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
}
TEST_F(SyntheticGestureControllerTest, GestureCompletedOnDidFlushInput) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
bool finished_1, finished_2;
std::unique_ptr<MockSyntheticGesture> gesture_1(
new MockSyntheticGesture(&finished_1, 2));
std::unique_ptr<MockSyntheticGesture> gesture_2(
new MockSyntheticGesture(&finished_2, 4));
QueueSyntheticGesture(std::move(gesture_1));
QueueSyntheticGesture(std::move(gesture_2));
while (target_->flush_requested()) {
target_->ClearFlushRequest();
time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs);
controller_->Flush(time_);
}
EXPECT_EQ(0, num_success_);
controller_->OnDidFlushInput();
EXPECT_EQ(1, num_success_);
while (target_->flush_requested()) {
target_->ClearFlushRequest();
time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs);
controller_->Flush(time_);
}
EXPECT_EQ(1, num_success_);
controller_->OnDidFlushInput();
EXPECT_EQ(2, num_success_);
}
gfx::Vector2d AddTouchSlopToVector(const gfx::Vector2dF& vector,
SyntheticGestureTarget* target) {
const int kTouchSlop = target->GetTouchSlopInDips();
int x = vector.x();
if (x > 0)
x += kTouchSlop;
else if (x < 0)
x -= kTouchSlop;
int y = vector.y();
if (y > 0)
y += kTouchSlop;
else if (y < 0)
y -= kTouchSlop;
return gfx::Vector2d(x, y);
}
TEST_P(SyntheticGestureControllerTestWithParam,
SingleMoveGestureTouchVertical) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
if (GetParam() == TOUCH_DRAG) {
params.add_slop = false;
}
params.start_point.SetPoint(89, 32);
params.distances.push_back(gfx::Vector2d(0, 123));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
if (GetParam() == TOUCH_SCROLL) {
EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
scroll_target->start_to_end_distance());
} else {
EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance());
}
}
TEST_P(SyntheticGestureControllerTestWithParam,
SingleScrollGestureTouchHorizontal) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
if (GetParam() == TOUCH_DRAG) {
params.add_slop = false;
}
params.start_point.SetPoint(12, -23);
params.distances.push_back(gfx::Vector2d(-234, 0));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
if (GetParam() == TOUCH_SCROLL) {
EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
scroll_target->start_to_end_distance());
} else {
EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance());
}
}
void CheckIsWithinRangeSingle(float scroll_distance,
int target_distance,
SyntheticGestureTarget* target) {
if (target_distance > 0) {
EXPECT_LE(target_distance, scroll_distance);
EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips());
} else {
EXPECT_GE(target_distance, scroll_distance);
EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips());
}
}
void CheckSingleScrollDistanceIsWithinRange(
const gfx::Vector2dF& scroll_distance,
const gfx::Vector2dF& target_distance,
SyntheticGestureTarget* target) {
CheckIsWithinRangeSingle(scroll_distance.x(), target_distance.x(), target);
CheckIsWithinRangeSingle(scroll_distance.y(), target_distance.y(), target);
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchDiagonal) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
params.start_point.SetPoint(0, 7);
params.distances.push_back(gfx::Vector2d(413, -83));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
CheckSingleScrollDistanceIsWithinRange(
scroll_target->start_to_end_distance(), params.distances[0], target_);
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchLongStop) {
CreateControllerAndTarget<MockMoveTouchTarget>();
// Create a smooth scroll with a short distance and set the pointer assumed
// stopped time high, so that the stopping should dominate the time the
// gesture is active.
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
params.start_point.SetPoint(-98, -23);
params.distances.push_back(gfx::Vector2d(21, -12));
params.prevent_fling = true;
target_->set_pointer_assumed_stopped_time_ms(543);
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
CheckSingleScrollDistanceIsWithinRange(
scroll_target->start_to_end_distance(), params.distances[0], target_);
EXPECT_GE(GetTotalTime(), target_->PointerAssumedStoppedTime());
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchFling) {
CreateControllerAndTarget<MockMoveTouchTarget>();
// Create a smooth scroll with a short distance and set the pointer assumed
// stopped time high. Disable 'prevent_fling' and check that the gesture
// finishes without waiting before it stops.
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
params.start_point.SetPoint(-89, 78);
params.distances.push_back(gfx::Vector2d(-43, 19));
params.prevent_fling = false;
target_->set_pointer_assumed_stopped_time_ms(543);
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
CheckSingleScrollDistanceIsWithinRange(
scroll_target->start_to_end_distance(), params.distances[0], target_);
EXPECT_LE(GetTotalTime(), target_->PointerAssumedStoppedTime());
}
TEST_P(SyntheticGestureControllerTestWithParam,
SingleScrollGestureTouchZeroDistance) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
if (GetParam() == TOUCH_DRAG) {
params.add_slop = false;
}
params.start_point.SetPoint(-32, 43);
params.distances.push_back(gfx::Vector2d(0, 0));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseVertical) {
CreateControllerAndTarget<MockScrollMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
params.start_point.SetPoint(432, 89);
params.distances.push_back(gfx::Vector2d(0, -234));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseHorizontal) {
CreateControllerAndTarget<MockScrollMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
params.start_point.SetPoint(90, 12);
params.distances.push_back(gfx::Vector2d(345, 0));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseDiagonal) {
CreateControllerAndTarget<MockScrollMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
params.start_point.SetPoint(90, 12);
params.distances.push_back(gfx::Vector2d(-194, 303));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouse) {
CreateControllerAndTarget<MockScrollMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
params.start_point.SetPoint(90, 12);
params.distances.push_back(gfx::Vector2d(-129, 212));
params.distances.push_back(gfx::Vector2d(8, -9));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(params.distances[0] + params.distances[1],
scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouseHorizontal) {
CreateControllerAndTarget<MockScrollMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT;
params.start_point.SetPoint(90, 12);
params.distances.push_back(gfx::Vector2d(-129, 0));
params.distances.push_back(gfx::Vector2d(79, 0));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
// This check only works for horizontal or vertical scrolls because of
// floating point precision issues with diagonal scrolls.
EXPECT_FLOAT_EQ(params.distances[0].Length() + params.distances[1].Length(),
scroll_target->total_abs_move_distance_length());
EXPECT_EQ(params.distances[0] + params.distances[1],
scroll_target->start_to_end_distance());
}
void CheckIsWithinRangeMulti(float scroll_distance,
int target_distance,
SyntheticGestureTarget* target) {
if (target_distance > 0) {
EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips());
EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips());
} else {
EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips());
EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips());
}
}
void CheckMultiScrollDistanceIsWithinRange(
const gfx::Vector2dF& scroll_distance,
const gfx::Vector2dF& target_distance,
SyntheticGestureTarget* target) {
CheckIsWithinRangeMulti(scroll_distance.x(), target_distance.x(), target);
CheckIsWithinRangeMulti(scroll_distance.y(), target_distance.y(), target);
}
TEST_F(SyntheticGestureControllerTest, MultiScrollGestureTouch) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
params.start_point.SetPoint(8, -13);
params.distances.push_back(gfx::Vector2d(234, 133));
params.distances.push_back(gfx::Vector2d(-9, 78));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
CheckMultiScrollDistanceIsWithinRange(
scroll_target->start_to_end_distance(),
params.distances[0] + params.distances[1],
target_);
}
TEST_P(SyntheticGestureControllerTestWithParam,
MultiScrollGestureTouchVertical) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::TOUCH_INPUT;
if (GetParam() == TOUCH_DRAG) {
params.add_slop = false;
}
params.start_point.SetPoint(234, -13);
params.distances.push_back(gfx::Vector2d(0, 133));
params.distances.push_back(gfx::Vector2d(0, 78));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* scroll_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
if (GetParam() == TOUCH_SCROLL) {
EXPECT_FLOAT_EQ(params.distances[0].Length() +
params.distances[1].Length() +
target_->GetTouchSlopInDips(),
scroll_target->total_abs_move_distance_length());
EXPECT_EQ(AddTouchSlopToVector(params.distances[0] + params.distances[1],
target_),
scroll_target->start_to_end_distance());
} else {
EXPECT_FLOAT_EQ(params.distances[0].Length() + params.distances[1].Length(),
scroll_target->total_abs_move_distance_length());
EXPECT_EQ(params.distances[0] + params.distances[1],
scroll_target->start_to_end_distance());
}
}
INSTANTIATE_TEST_CASE_P(Single,
SyntheticGestureControllerTestWithParam,
testing::Values(TOUCH_SCROLL, TOUCH_DRAG));
TEST_F(SyntheticGestureControllerTest, SingleDragGestureMouseDiagonal) {
CreateControllerAndTarget<MockDragMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT;
params.start_point.SetPoint(0, 7);
params.distances.push_back(gfx::Vector2d(413, -83));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* drag_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(drag_target->start_to_end_distance(), params.distances[0]);
}
TEST_F(SyntheticGestureControllerTest, SingleDragGestureMouseZeroDistance) {
CreateControllerAndTarget<MockDragMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT;
params.start_point.SetPoint(-32, 43);
params.distances.push_back(gfx::Vector2d(0, 0));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* drag_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(gfx::Vector2dF(0, 0), drag_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, MultiDragGestureMouse) {
CreateControllerAndTarget<MockDragMouseTarget>();
SyntheticSmoothMoveGestureParams params;
params.input_type = SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT;
params.start_point.SetPoint(8, -13);
params.distances.push_back(gfx::Vector2d(234, 133));
params.distances.push_back(gfx::Vector2d(-9, 78));
std::unique_ptr<SyntheticSmoothMoveGesture> gesture(
new SyntheticSmoothMoveGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockMoveGestureTarget* drag_target =
static_cast<MockMoveGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(drag_target->start_to_end_distance(),
params.distances[0] + params.distances[1]);
}
TEST_F(SyntheticGestureControllerTest,
SyntheticSmoothDragTestUsingSingleMouseDrag) {
CreateControllerAndTarget<MockDragMouseTarget>();
SyntheticSmoothDragGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.distances.push_back(gfx::Vector2d(234, 133));
params.speed_in_pixels_s = 800;
std::unique_ptr<SyntheticSmoothDragGesture> gesture(
new SyntheticSmoothDragGesture(params));
const base::TimeTicks timestamp;
gesture->ForwardInputEvents(timestamp, target_);
}
TEST_F(SyntheticGestureControllerTest,
SyntheticSmoothDragTestUsingSingleTouchDrag) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothDragGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.start_point.SetPoint(89, 32);
params.distances.push_back(gfx::Vector2d(0, 123));
params.speed_in_pixels_s = 800;
std::unique_ptr<SyntheticSmoothDragGesture> gesture(
new SyntheticSmoothDragGesture(params));
const base::TimeTicks timestamp;
gesture->ForwardInputEvents(timestamp, target_);
}
TEST_F(SyntheticGestureControllerTest,
SyntheticSmoothScrollTestUsingSingleTouchScroll) {
CreateControllerAndTarget<MockMoveTouchTarget>();
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
const base::TimeTicks timestamp;
gesture->ForwardInputEvents(timestamp, target_);
}
TEST_F(SyntheticGestureControllerTest,
SyntheticSmoothScrollTestUsingSingleMouseScroll) {
CreateControllerAndTarget<MockScrollMouseTarget>();
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.anchor.SetPoint(432, 89);
params.distances.push_back(gfx::Vector2d(0, -234));
params.speed_in_pixels_s = 800;
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
const base::TimeTicks timestamp;
gesture->ForwardInputEvents(timestamp, target_);
}
TEST_F(SyntheticGestureControllerTest,
TouchscreenTouchpadPinchGestureTouchZoomIn) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
std::unique_ptr<SyntheticTouchscreenPinchGesture> gesture(
new SyntheticTouchscreenPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTouchscreenPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchscreenPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchscreenPinchTouchTarget::ZOOM_IN);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
}
TEST_F(SyntheticGestureControllerTest,
TouchscreenTouchpadPinchGestureTouchZoomOut) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 0.4f;
params.anchor.SetPoint(-12, 93);
std::unique_ptr<SyntheticTouchscreenPinchGesture> gesture(
new SyntheticTouchscreenPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTouchscreenPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchscreenPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchscreenPinchTouchTarget::ZOOM_OUT);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
}
TEST_F(SyntheticGestureControllerTest,
TouchscreenTouchpadPinchGestureTouchNoScaling) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 1.0f;
std::unique_ptr<SyntheticTouchscreenPinchGesture> gesture(
new SyntheticTouchscreenPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTouchscreenPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchscreenPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchscreenPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN);
EXPECT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
}
TEST_F(SyntheticGestureControllerTest, TouchpadPinchGestureTouchZoomIn) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
std::unique_ptr<SyntheticTouchpadPinchGesture> gesture(
new SyntheticTouchpadPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTouchpadPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchpadPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchpadPinchTouchTarget::ZOOM_IN);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->scale_factor());
}
TEST_F(SyntheticGestureControllerTest, TouchpadPinchGestureTouchZoomOut) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 0.4f;
params.anchor.SetPoint(-12, 93);
std::unique_ptr<SyntheticTouchpadPinchGesture> gesture(
new SyntheticTouchpadPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTouchpadPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchpadPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchpadPinchTouchTarget::ZOOM_OUT);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->scale_factor());
}
TEST_F(SyntheticGestureControllerTest, TouchpadPinchGestureTouchNoScaling) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 1.0f;
std::unique_ptr<SyntheticTouchpadPinchGesture> gesture(
new SyntheticTouchpadPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTouchpadPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchpadPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchpadPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN);
EXPECT_EQ(params.scale_factor, pinch_target->scale_factor());
}
// Ensure that if SyntheticPinchGesture is instantiated with TOUCH_INPUT it
// correctly creates a touchscreen gesture.
TEST_F(SyntheticGestureControllerTest, PinchGestureExplicitTouch) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
std::unique_ptr<SyntheticPinchGesture> gesture(
new SyntheticPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
// Ensure that if SyntheticPinchGesture is instantiated with MOUSE_INPUT it
// correctly creates a touchpad gesture.
TEST_F(SyntheticGestureControllerTest, PinchGestureExplicitMouse) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
std::unique_ptr<SyntheticPinchGesture> gesture(
new SyntheticPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
// Ensure that if SyntheticPinchGesture is instantiated with DEFAULT_INPUT it
// correctly creates a touchscreen gesture for a touchscreen controller.
TEST_F(SyntheticGestureControllerTest, PinchGestureDefaultTouch) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
std::unique_ptr<SyntheticPinchGesture> gesture(
new SyntheticPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
// Ensure that if SyntheticPinchGesture is instantiated with DEFAULT_INPUT it
// correctly creates a touchpad gesture for a touchpad controller.
TEST_F(SyntheticGestureControllerTest, PinchGestureDefaultMouse) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
std::unique_ptr<SyntheticPinchGesture> gesture(
new SyntheticPinchGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
TEST_F(SyntheticGestureControllerTest, TapGestureTouch) {
CreateControllerAndTarget<MockSyntheticTapTouchTarget>();
SyntheticTapGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.duration_ms = 123;
params.position.SetPoint(87, -124);
std::unique_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTapTouchTarget* tap_target =
static_cast<MockSyntheticTapTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(tap_target->GestureFinished());
EXPECT_EQ(tap_target->position(), params.position);
EXPECT_EQ(tap_target->GetDuration().InMilliseconds(), params.duration_ms);
EXPECT_GE(GetTotalTime(),
base::TimeDelta::FromMilliseconds(params.duration_ms));
}
TEST_F(SyntheticGestureControllerTest, TapGestureMouse) {
CreateControllerAndTarget<MockSyntheticTapMouseTarget>();
SyntheticTapGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.duration_ms = 79;
params.position.SetPoint(98, 123);
std::unique_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticTapMouseTarget* tap_target =
static_cast<MockSyntheticTapMouseTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(tap_target->GestureFinished());
EXPECT_EQ(tap_target->position(), params.position);
EXPECT_EQ(tap_target->GetDuration().InMilliseconds(), params.duration_ms);
EXPECT_GE(GetTotalTime(),
base::TimeDelta::FromMilliseconds(params.duration_ms));
}
} // namespace
} // namespace content