blob: e488714cf57c312eeb4c14eec314a3df775e16e5 [file] [log] [blame]
// Copyright 2015 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/web_contents/aura/overscroll_window_delegate.h"
#include "base/macros.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/public/browser/overscroll_configuration.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/window.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/test/event_generator.h"
namespace content {
namespace {
const int kTestDisplayWidth = 800;
const int kTestWindowWidth = 600;
}
class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
public OverscrollControllerDelegate {
public:
OverscrollWindowDelegateTest()
: window_(nullptr),
overscroll_complete_(false),
overscroll_started_(false),
mode_changed_(false),
current_mode_(OVERSCROLL_NONE),
touch_start_threshold_(content::GetOverscrollConfig(
OverscrollConfig::THRESHOLD_START_TOUCHSCREEN)),
touch_complete_threshold_(content::GetOverscrollConfig(
OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN)) {}
~OverscrollWindowDelegateTest() override {}
void Reset() {
overscroll_complete_ = false;
overscroll_started_ = false;
mode_changed_ = false;
current_mode_ = OVERSCROLL_NONE;
window_.reset(CreateNormalWindow(
0, root_window(), new OverscrollWindowDelegate(this, gfx::Image())));
window_->SetBounds(gfx::Rect(0, 0, kTestWindowWidth, kTestWindowWidth));
}
// Accessors.
aura::Window* window() { return window_.get(); }
bool overscroll_complete() { return overscroll_complete_; }
bool overscroll_started() { return overscroll_started_; }
bool mode_changed() { return mode_changed_; }
OverscrollMode current_mode() { return current_mode_; }
float touch_start_threshold() { return touch_start_threshold_; }
float touch_complete_threshold() {
return kTestDisplayWidth * touch_complete_threshold_;
}
protected:
// aura::test::AuraTestBase:
void SetUp() override {
aura::test::AuraTestBase::SetUp();
Reset();
ui::GestureConfiguration::GetInstance()
->set_max_touch_move_in_pixels_for_click(0);
}
void TearDown() override {
window_.reset();
aura::test::AuraTestBase::TearDown();
}
private:
// OverscrollControllerDelegate:
gfx::Size GetDisplaySize() const override {
return gfx::Size(kTestDisplayWidth, kTestDisplayWidth);
}
void OnOverscrollBehaviorUpdate(
cc::OverscrollBehavior overscroll_behavior) override {}
bool OnOverscrollUpdate(float delta_x, float delta_y) override {
return true;
}
void OnOverscrollComplete(OverscrollMode overscroll_mode) override {
overscroll_complete_ = true;
}
void OnOverscrollModeChange(OverscrollMode old_mode,
OverscrollMode new_mode,
OverscrollSource source) override {
mode_changed_ = true;
current_mode_ = new_mode;
if (current_mode_ != OVERSCROLL_NONE)
overscroll_started_ = true;
}
base::Optional<float> GetMaxOverscrollDelta() const override {
return base::nullopt;
}
// Window in which the overscroll window delegate is installed.
std::unique_ptr<aura::Window> window_;
// State flags.
bool overscroll_complete_;
bool overscroll_started_;
bool mode_changed_;
OverscrollMode current_mode_;
// Config defined constants.
const float touch_start_threshold_;
const float touch_complete_threshold_;
DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegateTest);
};
// Tests that the basic overscroll gesture works and sends updates to the
// delegate.
TEST_F(OverscrollWindowDelegateTest, BasicOverscroll) {
ui::test::EventGenerator generator(root_window());
// Start an OVERSCROLL_EAST gesture.
generator.GestureScrollSequence(
gfx::Point(0, 0), gfx::Point(touch_complete_threshold() + 1, 10),
base::TimeDelta::FromMilliseconds(10), 10);
EXPECT_TRUE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_EAST);
EXPECT_TRUE(overscroll_complete());
Reset();
// Start an OVERSCROLL_WEST gesture.
generator.GestureScrollSequence(gfx::Point(touch_complete_threshold() + 1, 0),
gfx::Point(0, 0),
base::TimeDelta::FromMilliseconds(10), 10);
EXPECT_TRUE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_WEST);
EXPECT_TRUE(overscroll_complete());
}
// Verifies that the OverscrollWindowDelegate direction is set correctly during
// an overscroll.
TEST_F(OverscrollWindowDelegateTest, BasicOverscrollModes) {
ui::test::EventGenerator generator(root_window());
OverscrollWindowDelegate* delegate =
static_cast<OverscrollWindowDelegate*>(window()->delegate());
// Start pressing a touch, but do not start the gesture yet.
generator.MoveTouch(gfx::Point(0, 0));
generator.PressTouch();
EXPECT_EQ(delegate->overscroll_mode_, OVERSCROLL_NONE);
// Slide the touch to the right.
generator.MoveTouch(gfx::Point(touch_complete_threshold() + 1, 0));
EXPECT_EQ(delegate->overscroll_mode_, OVERSCROLL_EAST);
// Complete the gesture.
generator.ReleaseTouch();
EXPECT_EQ(delegate->overscroll_mode_, OVERSCROLL_NONE);
EXPECT_TRUE(overscroll_complete());
// Start another overscroll.
generator.MoveTouch(gfx::Point(touch_complete_threshold() + 1, 0));
generator.PressTouch();
EXPECT_EQ(delegate->overscroll_mode_, OVERSCROLL_NONE);
// Slide the touch to the left.
generator.MoveTouch(gfx::Point(0, 0));
EXPECT_EQ(delegate->overscroll_mode_, OVERSCROLL_WEST);
// Complete the gesture.
generator.ReleaseTouch();
EXPECT_EQ(delegate->overscroll_mode_, OVERSCROLL_NONE);
EXPECT_TRUE(overscroll_complete());
// Generate a mouse events which normally cancel the overscroll. Confirm
// that superfluous mode changed events are not dispatched.
Reset();
generator.PressLeftButton();
generator.MoveMouseTo(gfx::Point(10, 10));
EXPECT_FALSE(mode_changed());
}
// Tests that the overscroll does not start until the gesture gets past a
// particular threshold.
TEST_F(OverscrollWindowDelegateTest, OverscrollThreshold) {
ui::test::EventGenerator generator(root_window());
// Start an OVERSCROLL_EAST gesture.
generator.GestureScrollSequence(gfx::Point(0, 0),
gfx::Point(touch_start_threshold(), 0),
base::TimeDelta::FromMilliseconds(10), 10);
EXPECT_FALSE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_NONE);
EXPECT_FALSE(overscroll_complete());
Reset();
// Start an OVERSCROLL_WEST gesture.
generator.GestureScrollSequence(gfx::Point(touch_start_threshold(), 0),
gfx::Point(0, 0),
base::TimeDelta::FromMilliseconds(10), 10);
EXPECT_FALSE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_NONE);
EXPECT_FALSE(overscroll_complete());
}
// Tests that the overscroll is aborted if the gesture does not get past the
// completion threshold.
TEST_F(OverscrollWindowDelegateTest, AbortOverscrollThreshold) {
ui::test::EventGenerator generator(root_window());
// Start an OVERSCROLL_EAST gesture.
generator.GestureScrollSequence(gfx::Point(0, 0),
gfx::Point(touch_start_threshold() + 1, 0),
base::TimeDelta::FromMilliseconds(10), 10);
EXPECT_TRUE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_NONE);
EXPECT_FALSE(overscroll_complete());
Reset();
// Start an OVERSCROLL_WEST gesture.
generator.GestureScrollSequence(gfx::Point(touch_start_threshold() + 1, 0),
gfx::Point(0, 0),
base::TimeDelta::FromMilliseconds(10), 10);
EXPECT_TRUE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_NONE);
EXPECT_FALSE(overscroll_complete());
}
// Tests that the overscroll is aborted if the delegate receives some other
// event.
TEST_F(OverscrollWindowDelegateTest, EventAbortsOverscroll) {
ui::test::EventGenerator generator(root_window());
// Start an OVERSCROLL_EAST gesture, without releasing touch.
generator.set_current_location(gfx::Point(0, 0));
generator.PressTouch();
int touch_x = touch_start_threshold() + 1;
generator.MoveTouch(gfx::Point(touch_x, 0));
EXPECT_TRUE(overscroll_started());
EXPECT_EQ(current_mode(), OVERSCROLL_EAST);
EXPECT_FALSE(overscroll_complete());
// Dispatch a mouse event, the overscroll should be cancelled.
generator.PressLeftButton();
EXPECT_EQ(current_mode(), OVERSCROLL_NONE);
EXPECT_FALSE(overscroll_complete());
// We should be able to restart the overscroll without lifting the finger.
generator.MoveTouch(gfx::Point(touch_x + touch_start_threshold() + 1, 0));
EXPECT_EQ(current_mode(), OVERSCROLL_EAST);
EXPECT_FALSE(overscroll_complete());
}
} // namespace content