Commit 12bb4250 authored by Rahul Arakeri's avatar Rahul Arakeri Committed by Commit Bot

New Windows root scroller overscroll - Part 3.

This CL implements the bounce forwards animation for when user performs
a fling. When the scroller reaches the bounds, the residual velocity
determines the extent of the overscroll. This then gets applied to the
scroller followed by the usual bounce back animation.

Bug: 1058071
Change-Id: Id14cfff5e99843bd9849d7122058dc16d929e74c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2337940
Commit-Queue: Rahul Arakeri <arakeri@microsoft.com>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795630}
parent c1577e45
......@@ -96,7 +96,8 @@ class PLATFORM_EXPORT ElasticOverscrollController {
virtual gfx::Vector2d AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& stretch_amount) const = 0;
gfx::Size GetScrollBounds() const { return helper_->ScrollBounds(); }
gfx::Size scroll_bounds() const { return helper_->ScrollBounds(); }
gfx::Vector2dF scroll_velocity() const { return scroll_velocity_; }
// TODO (arakeri): Need to be cleared when we leave MomentumAnimated.
// Momentum animation state. This state is valid only while the state is
......@@ -106,7 +107,9 @@ class PLATFORM_EXPORT ElasticOverscrollController {
private:
FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest,
VerifyAnimationTick);
VerifyBackwardAnimationTick);
FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest,
VerifyForwardAnimationTick);
enum State {
// The initial state, during which the overscroll amount is zero and
......
......@@ -33,11 +33,24 @@ class PLATFORM_EXPORT ElasticOverscrollControllerBezier
gfx::Vector2d AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& delta) const override;
gfx::Vector2dF OverscrollBoundary(const gfx::Size& scroller_bounds) const;
double StretchAmountForForwardBounce(
const base::TimeDelta& delta,
const base::TimeDelta& bounce_forwards_duration,
const double velocity,
const double initial_stretch,
const double bounce_forwards_distance) const;
double StretchAmountForBackwardBounce(
const base::TimeDelta& delta,
const base::TimeDelta& bounce_backwards_duration,
const double bounce_forwards_distance) const;
private:
const gfx::CubicBezier bounce_backwards_curve_;
const gfx::CubicBezier bounce_forwards_curve_;
base::TimeDelta bounce_forwards_duration_x_;
base::TimeDelta bounce_forwards_duration_y_;
gfx::Vector2dF bounce_forwards_distance_;
// The following are used to track the duration of the bounce back animation.
const gfx::CubicBezier bounce_backwards_curve_;
base::TimeDelta bounce_backwards_duration_x_;
base::TimeDelta bounce_backwards_duration_y_;
DISALLOW_COPY_AND_ASSIGN(ElasticOverscrollControllerBezier);
......
......@@ -70,15 +70,11 @@ class ElasticOverscrollControllerBezierTest : public testing::Test {
}
void SendGestureScrollUpdate(PhaseState inertialPhase,
const Vector2dF& scroll_delta,
const Vector2dF& unused_scroll_delta) {
blink::WebGestureEvent event(WebInputEvent::Type::kGestureScrollUpdate,
WebInputEvent::kNoModifiers, base::TimeTicks(),
blink::WebGestureDevice::kTouchpad);
event.data.scroll_update.inertial_phase = inertialPhase;
event.data.scroll_update.delta_x = -scroll_delta.x();
event.data.scroll_update.delta_y = -scroll_delta.y();
cc::InputHandlerScrollResult scroll_result;
scroll_result.did_overscroll_root = !unused_scroll_delta.IsZero();
scroll_result.unused_scroll_delta = unused_scroll_delta;
......@@ -103,22 +99,18 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyOverscrollStretch) {
// Test vertical overscroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -10),
Vector2dF(0, -100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -100));
EXPECT_EQ(Vector2dF(0, -19), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, 10),
Vector2dF(0, 100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, 100));
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollEnd();
// Test horizontal overscroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-10, 0),
Vector2dF(-100, 0));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-100, 0));
EXPECT_EQ(Vector2dF(-19, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(10, 0),
Vector2dF(100, 0));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(100, 0));
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollEnd();
}
......@@ -129,8 +121,7 @@ TEST_F(ElasticOverscrollControllerBezierTest, ReconcileStretchAndScroll) {
SendGestureScrollBegin(PhaseState::kNonMomentum);
helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
gfx::ScrollOffset(100, 100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -50),
Vector2dF(0, -100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -100));
EXPECT_EQ(Vector2dF(0, -19), helper_.StretchAmount());
helper_.ScrollBy(Vector2dF(0, 1));
controller_.ReconcileStretchAndScroll();
......@@ -144,8 +135,7 @@ TEST_F(ElasticOverscrollControllerBezierTest, ReconcileStretchAndScroll) {
SendGestureScrollBegin(PhaseState::kNonMomentum);
helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
gfx::ScrollOffset(100, 100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-50, 0),
Vector2dF(-100, 0));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-100, 0));
EXPECT_EQ(Vector2dF(-19, 0), helper_.StretchAmount());
helper_.ScrollBy(Vector2dF(1, 0));
controller_.ReconcileStretchAndScroll();
......@@ -168,13 +158,12 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyOverscrollBounceDistance) {
// successfully created, the call to OverscrollBounceController::Animate should
// tick the animation as expected. When the stretch amount is near 0, the
// scroller should treat the bounce as "completed".
TEST_F(ElasticOverscrollControllerBezierTest, VerifyAnimationTick) {
TEST_F(ElasticOverscrollControllerBezierTest, VerifyBackwardAnimationTick) {
// Test vertical overscroll.
EXPECT_EQ(controller_.state_, ElasticOverscrollController::kStateInactive);
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -50),
Vector2dF(0, -100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -100));
// This signals that the finger has lifted off which triggers the bounce back
// animation.
......@@ -200,8 +189,7 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyAnimationTick) {
// Test horizontal overscroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-25, 0),
Vector2dF(-80, 0));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(-80, 0));
SendGestureScrollEnd(now);
// Frame 2.
......@@ -220,14 +208,40 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyAnimationTick) {
EXPECT_EQ(controller_.state_, ElasticOverscrollController::kStateInactive);
}
// Tests that the bounce forward animation ticks as expected.
TEST_F(ElasticOverscrollControllerBezierTest, VerifyForwardAnimationTick) {
EXPECT_EQ(controller_.state_, ElasticOverscrollController::kStateInactive);
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -100));
controller_.scroll_velocity_ = gfx::Vector2dF(0.f, -500.f);
// This signals that the finger has lifted off which triggers a fling.
const base::TimeTicks now = base::TimeTicks::Now();
SendGestureScrollEnd(now);
const int SAMPLES = 7;
const int frames[SAMPLES] = {1, 2, 3, 4, 5, 8, 19};
const int stretch_amount[SAMPLES] = {-33, -40, -43, -40, -26, -11, 0};
for (int i = 0; i < SAMPLES; i++) {
controller_.Animate(now +
base::TimeDelta::FromMilliseconds(frames[i] * 16));
EXPECT_EQ(controller_.state_,
(stretch_amount[i] == 0
? ElasticOverscrollController::kStateInactive
: ElasticOverscrollController::kStateMomentumAnimated));
ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), stretch_amount[i]);
}
}
// Tests initiating a scroll when a bounce back animation is in progress works
// as expected.
TEST_F(ElasticOverscrollControllerBezierTest, VerifyScrollDuringBounceBack) {
// Test vertical overscroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
EXPECT_EQ(Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(),
Vector2dF(0, -100));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -100));
// This signals that the finger has lifted off which triggers the bounce back
// animation.
......@@ -245,8 +259,7 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyScrollDuringBounceBack) {
// While the animation is still ticking, initiate a scroll.
SendGestureScrollBegin(PhaseState::kNonMomentum);
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(),
Vector2dF(0, -50));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -50));
ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -13);
}
......@@ -258,8 +271,7 @@ TEST_F(ElasticOverscrollControllerBezierTest, VerifyAnimationNotCreated) {
// state_ is kStateActiveScroll. unused_delta is 0 so overscroll should not
// take place.
Vector2dF delta(-25, -50);
SendGestureScrollUpdate(PhaseState::kNonMomentum, delta, Vector2dF(0, 0));
SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, 0));
// This signals that the finger has lifted off which triggers the bounce back
// animation.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment