Commit 595057cd authored by Rahul Arakeri's avatar Rahul Arakeri Committed by Commit Bot

New Windows root scroller overscroll - Part 2.

This CL refactors InputScrollElasticityController and introduces 2 new
subclasses - InputScrollElasticityControllerBezier will be used for
managing Windows based overscroll and bounce back. The other subclass
InputScrollElasticityControllerExponential will be used on Mac for the
same purpose.

The CL also allows an overscrolled root scroller to "bounce back" via
an animation based on a Bezier curve. This animation is driven by
OverscrollBounceController::Animate. The duration of this animation is
determined by how far the scroller has been stretched. At every "tick"
of the animation, the progress of the animation is determined based on
the elapsed time. Animating flings will be added in a follow up CL.

Bug: 1058071
Change-Id: Ia4278105eac5cadae191a50c25654c88a92c5a33
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2231254
Commit-Queue: Rahul Arakeri <arakeri@microsoft.com>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791431}
parent c3bd6b21
...@@ -117,7 +117,6 @@ source_set("blink_headers") { ...@@ -117,7 +117,6 @@ source_set("blink_headers") {
"platform/blame_context.h", "platform/blame_context.h",
"platform/cross_variant_mojo_util.h", "platform/cross_variant_mojo_util.h",
"platform/file_path_conversion.h", "platform/file_path_conversion.h",
"platform/input/elastic_overscroll_controller.h",
"platform/input/input_handler_proxy.h", "platform/input/input_handler_proxy.h",
"platform/input/input_handler_proxy_client.h", "platform/input/input_handler_proxy_client.h",
"platform/input/input_predictor.h", "platform/input/input_predictor.h",
......
// Copyright 2020 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.
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "cc/input/overscroll_behavior.h"
#include "third_party/blink/public/platform/web_common.h"
namespace cc {
struct InputHandlerScrollResult;
class ScrollElasticityHelper;
} // namespace cc
namespace blink {
class WebGestureEvent;
// ElasticOverscrollControllers are objects that live on the compositor thread
// which are responsible for maintaining the elastic scroll amount of the root
// scroller. They will passively observe scroll results, and if there were any
// unconsumed deltas for the root scroller (meaning that the user scrolled past
// the bounds), then they will start the overscroll and filter future events
// from reaching the intended scroller.
class BLINK_PLATFORM_EXPORT ElasticOverscrollController {
public:
static std::unique_ptr<ElasticOverscrollController> Create(
cc::ScrollElasticityHelper* helper);
virtual ~ElasticOverscrollController() = default;
virtual base::WeakPtr<ElasticOverscrollController> GetWeakPtr() = 0;
virtual void ObserveGestureEventAndResult(
const WebGestureEvent& gesture_event,
const cc::InputHandlerScrollResult& scroll_result) = 0;
virtual void Animate(base::TimeTicks time) = 0;
virtual void ReconcileStretchAndScroll() = 0;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "cc/paint/element_id.h" #include "cc/paint/element_id.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_gesture_event.h" #include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/platform/input/elastic_overscroll_controller.h"
#include "third_party/blink/public/platform/input/synchronous_input_handler_proxy.h" #include "third_party/blink/public/platform/input/synchronous_input_handler_proxy.h"
#include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_common.h"
...@@ -29,6 +28,7 @@ namespace blink { ...@@ -29,6 +28,7 @@ namespace blink {
class WebInputEventAttribution; class WebInputEventAttribution;
class WebMouseWheelEvent; class WebMouseWheelEvent;
class WebTouchEvent; class WebTouchEvent;
class ElasticOverscrollController;
} // namespace blink } // namespace blink
namespace blink { namespace blink {
...@@ -43,7 +43,6 @@ class UnifiedScrollingInputHandlerProxyTest; ...@@ -43,7 +43,6 @@ class UnifiedScrollingInputHandlerProxyTest;
} // namespace test } // namespace test
class CompositorThreadEventQueue; class CompositorThreadEventQueue;
class ElasticOverscrollController;
class EventWithCallback; class EventWithCallback;
class InputHandlerProxyClient; class InputHandlerProxyClient;
class ScrollPredictor; class ScrollPredictor;
......
...@@ -1476,6 +1476,11 @@ jumbo_component("platform") { ...@@ -1476,6 +1476,11 @@ jumbo_component("platform") {
"widget/input/compositor_thread_event_queue.cc", "widget/input/compositor_thread_event_queue.cc",
"widget/input/compositor_thread_event_queue.h", "widget/input/compositor_thread_event_queue.h",
"widget/input/elastic_overscroll_controller.cc", "widget/input/elastic_overscroll_controller.cc",
"widget/input/elastic_overscroll_controller.h",
"widget/input/elastic_overscroll_controller_bezier.cc",
"widget/input/elastic_overscroll_controller_bezier.h",
"widget/input/elastic_overscroll_controller_exponential.cc",
"widget/input/elastic_overscroll_controller_exponential.h",
"widget/input/event_with_callback.cc", "widget/input/event_with_callback.cc",
"widget/input/event_with_callback.h", "widget/input/event_with_callback.h",
"widget/input/frame_widget_input_handler_impl.cc", "widget/input/frame_widget_input_handler_impl.cc",
...@@ -1485,8 +1490,6 @@ jumbo_component("platform") { ...@@ -1485,8 +1490,6 @@ jumbo_component("platform") {
"widget/input/input_event_prediction.cc", "widget/input/input_event_prediction.cc",
"widget/input/input_event_prediction.h", "widget/input/input_event_prediction.h",
"widget/input/input_handler_proxy.cc", "widget/input/input_handler_proxy.cc",
"widget/input/input_scroll_elasticity_controller.cc",
"widget/input/input_scroll_elasticity_controller.h",
"widget/input/main_thread_event_queue.cc", "widget/input/main_thread_event_queue.cc",
"widget/input/main_thread_event_queue.h", "widget/input/main_thread_event_queue.h",
"widget/input/main_thread_event_queue_task.h", "widget/input/main_thread_event_queue_task.h",
...@@ -1494,8 +1497,6 @@ jumbo_component("platform") { ...@@ -1494,8 +1497,6 @@ jumbo_component("platform") {
"widget/input/main_thread_event_queue_task_list.h", "widget/input/main_thread_event_queue_task_list.h",
"widget/input/momentum_scroll_jank_tracker.cc", "widget/input/momentum_scroll_jank_tracker.cc",
"widget/input/momentum_scroll_jank_tracker.h", "widget/input/momentum_scroll_jank_tracker.h",
"widget/input/overscroll_bounce_controller.cc",
"widget/input/overscroll_bounce_controller.h",
"widget/input/prediction/empty_filter.cc", "widget/input/prediction/empty_filter.cc",
"widget/input/prediction/empty_filter.h", "widget/input/prediction/empty_filter.h",
"widget/input/prediction/empty_predictor.cc", "widget/input/prediction/empty_predictor.cc",
...@@ -2048,11 +2049,11 @@ jumbo_source_set("blink_platform_unittests_sources") { ...@@ -2048,11 +2049,11 @@ jumbo_source_set("blink_platform_unittests_sources") {
"widget/compositing/layer_tree_settings_unittest.cc", "widget/compositing/layer_tree_settings_unittest.cc",
"widget/compositing/layer_tree_view_unittest.cc", "widget/compositing/layer_tree_view_unittest.cc",
"widget/compositing/test/stub_layer_tree_view_delegate.h", "widget/compositing/test/stub_layer_tree_view_delegate.h",
"widget/input/elastic_overscroll_controller_bezier_unittest.cc",
"widget/input/elastic_overscroll_controller_exponential_unittest.cc",
"widget/input/input_event_prediction_unittest.cc", "widget/input/input_event_prediction_unittest.cc",
"widget/input/input_handler_proxy_unittest.cc", "widget/input/input_handler_proxy_unittest.cc",
"widget/input/input_scroll_elasticity_controller_unittest.cc",
"widget/input/main_thread_event_queue_unittest.cc", "widget/input/main_thread_event_queue_unittest.cc",
"widget/input/overscroll_bounce_controller_unittest.cc",
"widget/input/prediction/empty_filter_unittests.cc", "widget/input/prediction/empty_filter_unittests.cc",
"widget/input/prediction/filter_factory_unittests.cc", "widget/input/prediction/filter_factory_unittests.cc",
"widget/input/prediction/input_filter_unittest_helpers.cc", "widget/input/prediction/input_filter_unittest_helpers.cc",
......
...@@ -2,20 +2,16 @@ ...@@ -2,20 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "cc/input/overscroll_behavior.h" #include "cc/input/overscroll_behavior.h"
#include "cc/input/scroll_elasticity_helper.h" #include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/public/common/input/web_gesture_event.h" #include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/input/elastic_overscroll_controller.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
// InputScrollElasticityController is based on
// WebKit/Source/platform/mac/ScrollElasticityController.h
/* /*
* Copyright (C) 2011 Apple Inc. All rights reserved. * Copyright (C) 2011 Apple Inc. All rights reserved.
* *
...@@ -46,22 +42,22 @@ struct InputHandlerScrollResult; ...@@ -46,22 +42,22 @@ struct InputHandlerScrollResult;
} // namespace cc } // namespace cc
namespace blink { namespace blink {
// This serves as a base class for handling overscroll. Most of the basic
class PLATFORM_EXPORT InputScrollElasticityController // overscroll functionality is contained in this class. The customization
: public ElasticOverscrollController { // details like the stretch distance, the bounce animations etc will be
// implemented by the subclasses.
class PLATFORM_EXPORT ElasticOverscrollController {
public: public:
explicit InputScrollElasticityController(cc::ScrollElasticityHelper* helper); explicit ElasticOverscrollController(cc::ScrollElasticityHelper* helper);
~InputScrollElasticityController() override; virtual ~ElasticOverscrollController() = default;
base::WeakPtr<ElasticOverscrollController> GetWeakPtr() override;
// These methods that are "real" should only be called if the associated // These methods that are "real" should only be called if the associated event
// event is not synthetic. Otherwise, calling them will disrupt elastic // is not a synthetic phase change, e.g. generated by the MouseWheelEventQueue
// scrolling. // or FlingController. Otherwise, calling them will disrupt elastic scrolling.
void ObserveRealScrollBegin(bool enter_momentum, bool leave_momentum); void ObserveRealScrollBegin(bool enter_momentum, bool leave_momentum);
void ObserveScrollUpdate(const gfx::Vector2dF& event_delta, void ObserveScrollUpdate(const gfx::Vector2dF& event_delta,
const gfx::Vector2dF& unused_scroll_delta, const gfx::Vector2dF& unused_scroll_delta,
const base::TimeTicks event_timestamp, const base::TimeTicks& event_timestamp,
const cc::OverscrollBehavior overscroll_behavior, const cc::OverscrollBehavior overscroll_behavior,
bool has_momentum); bool has_momentum);
void ObserveRealScrollEnd(const base::TimeTicks event_timestamp); void ObserveRealScrollEnd(const base::TimeTicks event_timestamp);
...@@ -73,13 +69,45 @@ class PLATFORM_EXPORT InputScrollElasticityController ...@@ -73,13 +69,45 @@ class PLATFORM_EXPORT InputScrollElasticityController
// this class may disregard some scrolls that come in at unexpected times. // this class may disregard some scrolls that come in at unexpected times.
void ObserveGestureEventAndResult( void ObserveGestureEventAndResult(
const blink::WebGestureEvent& gesture_event, const blink::WebGestureEvent& gesture_event,
const cc::InputHandlerScrollResult& scroll_result) override; const cc::InputHandlerScrollResult& scroll_result);
void Animate(base::TimeTicks time);
void ReconcileStretchAndScroll();
static std::unique_ptr<ElasticOverscrollController> Create(
cc::ScrollElasticityHelper* helper);
protected:
virtual void DidEnterMomentumAnimatedState() = 0;
void Animate(base::TimeTicks time) override; // The parameter "delta" is the difference between the time "Animate" is
// called and momentum_animation_start_time_. Using this information, the
// stretch amount for a scroller is determined. This is how the bounce
// animation basically "ticks".
virtual gfx::Vector2d StretchAmountForTimeDelta(
const base::TimeDelta& delta) const = 0;
void ReconcileStretchAndScroll() override; // Maps the distance the user has scrolled past the boundary into the distance
// to actually scroll the elastic scroller.
virtual gfx::Vector2d StretchAmountForAccumulatedOverscroll(
const gfx::Vector2dF& accumulated_overscroll) const = 0;
// Does the inverse of StretchAmountForAccumulatedOverscroll. As in, takes in
// the bounce distance and calculates how much is actually overscrolled.
virtual gfx::Vector2d AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& stretch_amount) const = 0;
gfx::Size GetScrollBounds() const { return helper_->ScrollBounds(); }
// TODO (arakeri): Need to be cleared when we leave MomentumAnimated.
// Momentum animation state. This state is valid only while the state is
// MomentumAnimated, and is initialized in EnterStateMomentumAnimated.
gfx::Vector2dF momentum_animation_initial_stretch_;
gfx::Vector2dF momentum_animation_initial_velocity_;
private: private:
FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest,
VerifyAnimationTick);
enum State { enum State {
// The initial state, during which the overscroll amount is zero and // The initial state, during which the overscroll amount is zero and
// there are no active or momentum scroll events coming in. This state // there are no active or momentum scroll events coming in. This state
...@@ -106,8 +134,7 @@ class PLATFORM_EXPORT InputScrollElasticityController ...@@ -106,8 +134,7 @@ class PLATFORM_EXPORT InputScrollElasticityController
void UpdateVelocity(const gfx::Vector2dF& event_delta, void UpdateVelocity(const gfx::Vector2dF& event_delta,
const base::TimeTicks& event_timestamp); const base::TimeTicks& event_timestamp);
void Overscroll(const gfx::Vector2dF& input_delta, void Overscroll(const gfx::Vector2dF& overscroll_delta);
const gfx::Vector2dF& overscroll_delta);
void EnterStateMomentumAnimated( void EnterStateMomentumAnimated(
const base::TimeTicks& triggering_event_timestamp); const base::TimeTicks& triggering_event_timestamp);
void EnterStateInactive(); void EnterStateInactive();
...@@ -117,11 +144,18 @@ class PLATFORM_EXPORT InputScrollElasticityController ...@@ -117,11 +144,18 @@ class PLATFORM_EXPORT InputScrollElasticityController
// this circumstance that an overscroll in that direction may begin. // this circumstance that an overscroll in that direction may begin.
bool PinnedHorizontally(float direction) const; bool PinnedHorizontally(float direction) const;
bool PinnedVertically(float direction) const; bool PinnedVertically(float direction) const;
// Whether or not the content of the page is scrollable horizontaly (or // Whether or not the content of the page is scrollable horizontaly (or
// vertically). // vertically).
bool CanScrollHorizontally() const; bool CanScrollHorizontally() const;
bool CanScrollVertically() const; bool CanScrollVertically() const;
// This is set in response to a scroll (most likely programmatic) occuring
// while animating the momentum phase. In this case, re-set the initial
// velocity, stretch, and start time at the next frame (this is the same
// behavior as would happen if the scroll were caused by an active scroll).
bool momentum_animation_reset_at_next_frame_;
base::TimeTicks momentum_animation_start_time_;
cc::ScrollElasticityHelper* helper_; cc::ScrollElasticityHelper* helper_;
State state_; State state_;
...@@ -135,7 +169,7 @@ class PLATFORM_EXPORT InputScrollElasticityController ...@@ -135,7 +169,7 @@ class PLATFORM_EXPORT InputScrollElasticityController
// scroll delta divide by the time between input events. Track this velocity // scroll delta divide by the time between input events. Track this velocity
// in |scroll_velocity| and the previous input event timestamp for finite // in |scroll_velocity| and the previous input event timestamp for finite
// differencing in |last_scroll_event_timestamp_|. // differencing in |last_scroll_event_timestamp_|.
gfx::Vector2dF scroll_velocity; gfx::Vector2dF scroll_velocity_;
base::TimeTicks last_scroll_event_timestamp_; base::TimeTicks last_scroll_event_timestamp_;
// The force of the rubber-band spring. This is equal to the cumulative sum // The force of the rubber-band spring. This is equal to the cumulative sum
...@@ -143,25 +177,10 @@ class PLATFORM_EXPORT InputScrollElasticityController ...@@ -143,25 +177,10 @@ class PLATFORM_EXPORT InputScrollElasticityController
// reset to zero only when entering the Inactive state. // reset to zero only when entering the Inactive state.
gfx::Vector2dF stretch_scroll_force_; gfx::Vector2dF stretch_scroll_force_;
// Momentum animation state. This state is valid only while the state is
// MomentumAnimated, and is initialized in EnterStateMomentumAnimated.
base::TimeTicks momentum_animation_start_time_;
gfx::Vector2dF momentum_animation_initial_stretch_;
gfx::Vector2dF momentum_animation_initial_velocity_;
// This is set in response to a scroll (most likely programmatic) occuring
// while animating the momentum phase. In this case, re-set the initial
// velocity, stretch, and start time at the next frame (this is the same
// behavior as would happen if the scroll were caused by an active scroll).
bool momentum_animation_reset_at_next_frame_;
bool received_overscroll_update_; bool received_overscroll_update_;
cc::OverscrollBehavior overscroll_behavior_; cc::OverscrollBehavior overscroll_behavior_;
base::WeakPtrFactory<InputScrollElasticityController> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(InputScrollElasticityController);
}; };
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_
// Copyright 2020 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 "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace blink {
namespace {
// The following constants are determined experimentally.
// Used to determine how far the scroller is allowed to stretch.
constexpr double kOverscrollBoundaryMultiplier = 0.1f;
// Maximum duration for the bounce back animation.
constexpr double kBounceBackMaxDurationMilliseconds = 300.0;
// Time taken by the bounce back animation (in milliseconds) to scroll 1 px.
constexpr double kBounceBackMillisecondsPerPixel = 15.0;
// Control points for the Cubic Bezier curve.
constexpr double kBounceBackwardsX1 = 0.05;
constexpr double kBounceBackwardsY1 = 0.7;
constexpr double kBounceBackwardsX2 = 0.25;
constexpr double kBounceBackwardsY2 = 1.0;
base::TimeDelta CalculateBounceBackDuration(double bounce_back_distance) {
return base::TimeDelta::FromMillisecondsD(std::min(
kBounceBackMaxDurationMilliseconds,
kBounceBackMillisecondsPerPixel * std::abs(bounce_back_distance)));
}
} // namespace
ElasticOverscrollControllerBezier::ElasticOverscrollControllerBezier(
cc::ScrollElasticityHelper* helper)
: ElasticOverscrollController(helper),
bounce_backwards_curve_(gfx::CubicBezier(kBounceBackwardsX1,
kBounceBackwardsY1,
kBounceBackwardsX2,
kBounceBackwardsY2)) {}
// Returns the maximum amount to be overscrolled.
gfx::Vector2dF ElasticOverscrollControllerBezier::OverscrollBoundary(
const gfx::Size& scroller_bounds) const {
return gfx::Vector2dF(
scroller_bounds.width() * kOverscrollBoundaryMultiplier,
scroller_bounds.height() * kOverscrollBoundaryMultiplier);
}
void ElasticOverscrollControllerBezier::DidEnterMomentumAnimatedState() {
bounce_backwards_duration_x_ =
CalculateBounceBackDuration(momentum_animation_initial_stretch_.x());
bounce_backwards_duration_y_ =
CalculateBounceBackDuration(momentum_animation_initial_stretch_.y());
}
gfx::Vector2d ElasticOverscrollControllerBezier::StretchAmountForTimeDelta(
const base::TimeDelta& delta) const {
// Handle the case where the animation is in the bounce-back stage.
double stretch_x, stretch_y;
stretch_x = stretch_y = 0.f;
if (delta < bounce_backwards_duration_x_) {
double curve_progress = delta.InMillisecondsF() /
bounce_backwards_duration_x_.InMillisecondsF();
double progress = bounce_backwards_curve_.Solve(curve_progress);
stretch_x = momentum_animation_initial_stretch_.x() * (1 - progress);
}
if (delta < bounce_backwards_duration_y_) {
double curve_progress = delta.InMillisecondsF() /
bounce_backwards_duration_y_.InMillisecondsF();
double progress = bounce_backwards_curve_.Solve(curve_progress);
stretch_y = momentum_animation_initial_stretch_.y() * (1 - progress);
}
return gfx::ToRoundedVector2d(gfx::Vector2dF(stretch_x, stretch_y));
}
// The goal of this calculation is to map the distance the user has scrolled
// past the boundary into the distance to actually scroll the elastic scroller.
gfx::Vector2d
ElasticOverscrollControllerBezier::StretchAmountForAccumulatedOverscroll(
const gfx::Vector2dF& accumulated_overscroll) const {
// TODO(arakeri): This should change as you pinch zoom in.
const gfx::Size& scroller_bounds = GetScrollBounds();
const gfx::Vector2dF overscroll_boundary =
OverscrollBoundary(scroller_bounds);
// We use the tanh function in addition to the mapping, which gives it more of
// a spring effect. However, we want to use tanh's range from [0, 2], so we
// multiply the value we provide to tanh by 2.
// Also, it may happen that the scroller_bounds are 0 if the viewport scroll
// nodes are null (see: ScrollElasticityHelper::ScrollBounds). We therefore
// have to check in order to avoid a divide by 0.
gfx::Vector2d overbounce_distance;
if (scroller_bounds.width() > 0.f) {
overbounce_distance.set_x(
tanh(2 * accumulated_overscroll.x() / scroller_bounds.width()) *
overscroll_boundary.x());
}
if (scroller_bounds.height() > 0.f) {
overbounce_distance.set_y(
tanh(2 * accumulated_overscroll.y() / scroller_bounds.height()) *
overscroll_boundary.y());
}
return overbounce_distance;
}
// This function does the inverse of StretchAmountForAccumulatedOverscroll. As
// in, instead of taking in the amount of distance overscrolled to get the
// bounce distance, it takes in the bounce distance and calculates how much is
// actually overscrolled.
gfx::Vector2d
ElasticOverscrollControllerBezier::AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& stretch_amount) const {
const gfx::Size& scroller_bounds = GetScrollBounds();
const gfx::Vector2dF overscroll_boundary =
OverscrollBoundary(scroller_bounds);
// It may happen that the scroller_bounds are 0 if the viewport scroll
// nodes are null (see: ScrollElasticityHelper::ScrollBounds). We therefore
// have to check in order to avoid a divide by 0.
gfx::Vector2d overscrolled_amount;
if (overscroll_boundary.x() > 0.f) {
float atanh_value = atanh(stretch_amount.x() / overscroll_boundary.x());
overscrolled_amount.set_x((atanh_value / 2) * scroller_bounds.width());
}
if (overscroll_boundary.y() > 0.f) {
float atanh_value = atanh(stretch_amount.y() / overscroll_boundary.y());
overscrolled_amount.set_y((atanh_value / 2) * scroller_bounds.height());
}
return overscrolled_amount;
}
} // namespace blink
// Copyright 2020 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_BEZIER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_BEZIER_H_
#include "base/macros.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
#include "ui/gfx/geometry/cubic_bezier.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "third_party/blink/public/platform/web_common.h"
namespace blink {
// Manages scroller stretch and rebounds when overscrolling. This controller
// uses a Bezier curve.
class PLATFORM_EXPORT ElasticOverscrollControllerBezier
: public ElasticOverscrollController {
public:
explicit ElasticOverscrollControllerBezier(
cc::ScrollElasticityHelper* helper);
~ElasticOverscrollControllerBezier() override = default;
void DidEnterMomentumAnimatedState() override;
gfx::Vector2d StretchAmountForTimeDelta(
const base::TimeDelta& delta) const override;
gfx::Vector2d StretchAmountForAccumulatedOverscroll(
const gfx::Vector2dF& accumulated_overscroll) const override;
gfx::Vector2d AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& delta) const override;
gfx::Vector2dF OverscrollBoundary(const gfx::Size& scroller_bounds) const;
private:
const gfx::CubicBezier bounce_backwards_curve_;
// The following are used to track the duration of the bounce back animation.
base::TimeDelta bounce_backwards_duration_x_;
base::TimeDelta bounce_backwards_duration_y_;
DISALLOW_COPY_AND_ASSIGN(ElasticOverscrollControllerBezier);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_BEZIER_H_
// Copyright 2020 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 "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace blink {
namespace {
constexpr double kRubberbandStiffness = 20;
constexpr double kRubberbandAmplitude = 0.31f;
constexpr double kRubberbandPeriod = 1.6f;
} // namespace
ElasticOverscrollControllerExponential::ElasticOverscrollControllerExponential(
cc::ScrollElasticityHelper* helper)
: ElasticOverscrollController(helper) {}
void ElasticOverscrollControllerExponential::DidEnterMomentumAnimatedState() {}
// For these functions which compute the stretch amount, always return a
// rounded value, instead of a floating-point value. The reason for this is
// that Blink's scrolling can become erratic with fractional scroll amounts (in
// particular, if you have a scroll offset of 0.5, Blink will never actually
// bring that value back to 0, which breaks the logic used to determine if a
// layer is pinned in a direction).
gfx::Vector2d ElasticOverscrollControllerExponential::StretchAmountForTimeDelta(
const base::TimeDelta& delta) const {
// Compute the stretch amount at a given time after some initial conditions.
// Do this by first computing an intermediary position given the initial
// position, initial velocity, time elapsed, and no external forces. Then
// take the intermediary position and damp it towards zero by multiplying
// against a negative exponential.
float amplitude = kRubberbandAmplitude;
float period = kRubberbandPeriod;
float critical_dampening_factor =
expf((-delta.InSecondsF() * kRubberbandStiffness) / period);
return gfx::ToRoundedVector2d(gfx::ScaleVector2d(
momentum_animation_initial_stretch_ +
gfx::ScaleVector2d(momentum_animation_initial_velocity_,
delta.InSecondsF() * amplitude),
critical_dampening_factor));
}
gfx::Vector2d
ElasticOverscrollControllerExponential::StretchAmountForAccumulatedOverscroll(
const gfx::Vector2dF& accumulated_overscroll) const {
const float stiffness = std::max(kRubberbandStiffness, 1.0);
return gfx::ToRoundedVector2d(
gfx::ScaleVector2d(accumulated_overscroll, 1.0f / stiffness));
}
gfx::Vector2d
ElasticOverscrollControllerExponential::AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& delta) const {
return gfx::ToRoundedVector2d(
gfx::ScaleVector2d(delta, kRubberbandStiffness));
}
} // namespace blink
// Copyright 2020 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_EXPONENTIAL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_EXPONENTIAL_H_
#include "base/macros.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
namespace blink {
// Manages scroller stretch and rebounds when overscrolling. This controller
// uses an Exponential curve.
class PLATFORM_EXPORT ElasticOverscrollControllerExponential
: public ElasticOverscrollController {
public:
explicit ElasticOverscrollControllerExponential(
cc::ScrollElasticityHelper* helper);
~ElasticOverscrollControllerExponential() override = default;
void DidEnterMomentumAnimatedState() override;
gfx::Vector2d StretchAmountForTimeDelta(
const base::TimeDelta& delta) const override;
gfx::Vector2d StretchAmountForAccumulatedOverscroll(
const gfx::Vector2dF& accumulated_overscroll) const override;
gfx::Vector2d AccumulatedOverscrollForStretchAmount(
const gfx::Vector2dF& delta) const override;
DISALLOW_COPY_AND_ASSIGN(ElasticOverscrollControllerExponential);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_EXPONENTIAL_H_
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "third_party/blink/public/common/input/web_touch_event.h" #include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/platform/input/input_handler_proxy_client.h" #include "third_party/blink/public/platform/input/input_handler_proxy_client.h"
#include "third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h" #include "third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
#include "third_party/blink/renderer/platform/widget/input/event_with_callback.h" #include "third_party/blink/renderer/platform/widget/input/event_with_callback.h"
#include "third_party/blink/renderer/platform/widget/input/momentum_scroll_jank_tracker.h" #include "third_party/blink/renderer/platform/widget/input/momentum_scroll_jank_tracker.h"
#include "third_party/blink/renderer/platform/widget/input/scroll_predictor.h" #include "third_party/blink/renderer/platform/widget/input/scroll_predictor.h"
......
// Copyright 2020 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 "third_party/blink/renderer/platform/widget/input/overscroll_bounce_controller.h"
#include <algorithm>
#include <cmath>
// TODO(arakeri): This is where all the overscroll specific code will go.
namespace blink {
constexpr float kOverscrollBoundaryMultiplier = 0.1f;
OverscrollBounceController::OverscrollBounceController(
cc::ScrollElasticityHelper* helper)
: state_(kStateInactive), helper_(helper), weak_factory_(this) {}
OverscrollBounceController::~OverscrollBounceController() = default;
base::WeakPtr<ElasticOverscrollController>
OverscrollBounceController::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
void OverscrollBounceController::Animate(base::TimeTicks time) {}
// TODO(arakeri): ReconcileStretchAndScroll implementations in both the classes
// InputScrollElasticityController and OverscrollBounceController have common
// code that needs to be evaluated and moved up into the base class.
void OverscrollBounceController::ReconcileStretchAndScroll() {
const gfx::Vector2dF stretch = helper_->StretchAmount();
if (stretch.IsZero())
return;
const gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
const gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
float scroll_adjustment_x = 0;
if (stretch.x() < 0.f)
scroll_adjustment_x = scroll_offset.x();
else if (stretch.x() > 0.f)
scroll_adjustment_x = max_scroll_offset.x() - scroll_offset.x();
float scroll_adjustment_y = 0;
if (stretch.y() < 0.f)
scroll_adjustment_y = scroll_offset.y();
else if (stretch.y() > 0.f)
scroll_adjustment_y = max_scroll_offset.y() - scroll_offset.y();
if (state_ == kStateActiveScroll) {
// During an active scroll, we want to reduce |accumulated_scroll_delta_| by
// the amount that was scrolled (but we don't want to over-consume, so limit
// it by the amount of |accumulated_scroll_delta_|).
scroll_adjustment_x = std::copysign(
std::min(std::abs(accumulated_scroll_delta_.x()), scroll_adjustment_x),
stretch.x());
scroll_adjustment_y = std::copysign(
std::min(std::abs(accumulated_scroll_delta_.y()), scroll_adjustment_y),
stretch.y());
accumulated_scroll_delta_ -=
gfx::Vector2dF(scroll_adjustment_x, scroll_adjustment_y);
helper_->SetStretchAmount(OverscrollBounceDistance(
accumulated_scroll_delta_, helper_->ScrollBounds()));
}
helper_->ScrollBy(gfx::Vector2dF(scroll_adjustment_x, scroll_adjustment_y));
}
// Returns the maximum amount to be overscrolled.
gfx::Vector2dF OverscrollBounceController::OverscrollBoundary(
const gfx::Size& scroller_bounds) const {
return gfx::Vector2dF(
scroller_bounds.width() * kOverscrollBoundaryMultiplier,
scroller_bounds.height() * kOverscrollBoundaryMultiplier);
}
// The goal of this calculation is to map the distance the user has scrolled
// past the boundary into the distance to actually scroll the elastic scroller.
gfx::Vector2d OverscrollBounceController::OverscrollBounceDistance(
const gfx::Vector2dF& distance_overscrolled,
const gfx::Size& scroller_bounds) const {
// TODO(arakeri): This should change as you pinch zoom in.
gfx::Vector2dF overscroll_boundary = OverscrollBoundary(scroller_bounds);
// We use the tanh function in addition to the mapping, which gives it more of
// a spring effect. However, we want to use tanh's range from [0, 2], so we
// multiply the value we provide to tanh by 2.
// Also, it may happen that the scroller_bounds are 0 if the viewport scroll
// nodes are null (see: ScrollElasticityHelper::ScrollBounds). We therefore
// have to check in order to avoid a divide by 0.
gfx::Vector2d overbounce_distance;
if (scroller_bounds.width() > 0.f) {
overbounce_distance.set_x(
tanh(2 * distance_overscrolled.x() / scroller_bounds.width()) *
overscroll_boundary.x());
}
if (scroller_bounds.height() > 0.f) {
overbounce_distance.set_y(
tanh(2 * distance_overscrolled.y() / scroller_bounds.height()) *
overscroll_boundary.y());
}
return overbounce_distance;
}
void OverscrollBounceController::EnterStateActiveScroll() {
state_ = kStateActiveScroll;
}
void OverscrollBounceController::ObserveRealScrollBegin(
const blink::WebGestureEvent& gesture_event) {
if (gesture_event.data.scroll_begin.inertial_phase ==
blink::WebGestureEvent::InertialPhaseState::kNonMomentum &&
gesture_event.data.scroll_begin.delta_hint_units ==
ui::ScrollGranularity::kScrollByPrecisePixel) {
EnterStateActiveScroll();
}
}
void OverscrollBounceController::ObserveRealScrollEnd() {
state_ = kStateInactive;
}
void OverscrollBounceController::OverscrollIfNecessary(
const gfx::Vector2dF& overscroll_delta) {
accumulated_scroll_delta_ += overscroll_delta;
gfx::Vector2d overbounce_distance = OverscrollBounceDistance(
accumulated_scroll_delta_, helper_->ScrollBounds());
helper_->SetStretchAmount(overbounce_distance);
}
void OverscrollBounceController::ObserveScrollUpdate(
const gfx::Vector2dF& unused_scroll_delta) {
if (state_ == kStateInactive)
return;
if (state_ == kStateActiveScroll) {
// TODO(arakeri): Implement animate back.
OverscrollIfNecessary(unused_scroll_delta);
}
}
void OverscrollBounceController::ObserveGestureEventAndResult(
const blink::WebGestureEvent& gesture_event,
const cc::InputHandlerScrollResult& scroll_result) {
switch (gesture_event.GetType()) {
case blink::WebInputEvent::Type::kGestureScrollBegin: {
if (gesture_event.data.scroll_begin.synthetic)
return;
ObserveRealScrollBegin(gesture_event);
break;
}
case blink::WebInputEvent::Type::kGestureScrollUpdate: {
gfx::Vector2dF event_delta(-gesture_event.data.scroll_update.delta_x,
-gesture_event.data.scroll_update.delta_y);
ObserveScrollUpdate(scroll_result.unused_scroll_delta);
break;
}
case blink::WebInputEvent::Type::kGestureScrollEnd: {
ObserveRealScrollEnd();
break;
}
default:
break;
}
}
} // namespace blink
// Copyright 2020 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_OVERSCROLL_BOUNCE_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_OVERSCROLL_BOUNCE_CONTROLLER_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "cc/input/input_handler.h"
#include "cc/input/overscroll_behavior.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/platform/input/elastic_overscroll_controller.h"
namespace blink {
// The overbounce version of elastic overscrolling mimics Windows style
// overscroll animations.
class BLINK_PLATFORM_EXPORT OverscrollBounceController
: public ElasticOverscrollController {
public:
explicit OverscrollBounceController(cc::ScrollElasticityHelper* helper);
~OverscrollBounceController() override;
base::WeakPtr<ElasticOverscrollController> GetWeakPtr() override;
void ObserveGestureEventAndResult(
const blink::WebGestureEvent& gesture_event,
const cc::InputHandlerScrollResult& scroll_result) override;
void Animate(base::TimeTicks time) override;
void ReconcileStretchAndScroll() override;
gfx::Vector2d OverscrollBounceDistance(
const gfx::Vector2dF& distance_overscrolled,
const gfx::Size& scroller_bounds) const;
private:
void ObserveRealScrollBegin(const blink::WebGestureEvent& gesture_event);
void ObserveRealScrollEnd();
gfx::Vector2dF OverscrollBoundary(const gfx::Size& scroller_bounds) const;
void EnterStateActiveScroll();
void OverscrollIfNecessary(const gfx::Vector2dF& overscroll_delta);
void ObserveScrollUpdate(const gfx::Vector2dF& unused_scroll_delta);
enum State {
// The initial state, during which the overscroll amount is zero.
kStateInactive,
// ActiveScroll indicates that this controller is listening to future GSU
// events, and those events may or may not update the overscroll amount.
// This occurs when the user is actively panning either via a touchscreen or
// touchpad, or is an active fling that has not triggered an overscroll.
kStateActiveScroll,
};
State state_;
cc::ScrollElasticityHelper* helper_;
// This is the accumulated raw delta in pixels that's been overscrolled. It
// will be fed into a tanh function (ranging [0, 2]) that decides the stretch
// bounds.
gfx::Vector2dF accumulated_scroll_delta_;
base::WeakPtrFactory<OverscrollBounceController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(OverscrollBounceController);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_OVERSCROLL_BOUNCE_CONTROLLER_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is a fork of the input_scroll_elasticity_controller_unittest.cc.
#include "third_party/blink/renderer/platform/widget/input/overscroll_bounce_controller.h"
#include "cc/input/input_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
namespace blink {
namespace test {
class MockScrollElasticityHelper : public cc::ScrollElasticityHelper {
public:
MockScrollElasticityHelper() = default;
~MockScrollElasticityHelper() override = default;
// cc::ScrollElasticityHelper implementation:
gfx::Size ScrollBounds() const override { return gfx::Size(1000, 1000); }
bool IsUserScrollable() const override { return false; }
gfx::Vector2dF StretchAmount() const override { return stretch_amount_; }
void SetStretchAmount(const gfx::Vector2dF& stretch_amount) override {
stretch_amount_ = stretch_amount;
}
void ScrollBy(const gfx::Vector2dF& delta) override {
scroll_offset_ += gfx::ScrollOffset(delta);
}
void RequestOneBeginFrame() override {}
gfx::ScrollOffset ScrollOffset() const override { return scroll_offset_; }
gfx::ScrollOffset MaxScrollOffset() const override {
return max_scroll_offset_;
}
void SetScrollOffsetAndMaxScrollOffset(
const gfx::ScrollOffset& scroll_offset,
const gfx::ScrollOffset& max_scroll_offset) {
scroll_offset_ = scroll_offset;
max_scroll_offset_ = max_scroll_offset;
}
private:
gfx::Vector2dF stretch_amount_;
gfx::ScrollOffset scroll_offset_, max_scroll_offset_;
};
class OverscrollBounceControllerTest : public testing::Test {
public:
OverscrollBounceControllerTest() : controller_(&helper_) {}
~OverscrollBounceControllerTest() override = default;
void SetUp() override {}
void SendGestureScrollBegin(
WebGestureEvent::InertialPhaseState inertialPhase) {
WebGestureEvent event(WebInputEvent::Type::kGestureScrollBegin,
WebInputEvent::kNoModifiers, base::TimeTicks(),
WebGestureDevice::kTouchpad);
event.data.scroll_begin.inertial_phase = inertialPhase;
controller_.ObserveGestureEventAndResult(event,
cc::InputHandlerScrollResult());
}
void SendGestureScrollUpdate(
WebGestureEvent::InertialPhaseState inertialPhase,
const gfx::Vector2dF& scroll_delta,
const gfx::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;
controller_.ObserveGestureEventAndResult(event, scroll_result);
}
void SendGestureScrollEnd() {
WebGestureEvent event(WebInputEvent::Type::kGestureScrollEnd,
WebInputEvent::kNoModifiers, base::TimeTicks(),
WebGestureDevice::kTouchpad);
controller_.ObserveGestureEventAndResult(event,
cc::InputHandlerScrollResult());
}
MockScrollElasticityHelper helper_;
OverscrollBounceController controller_;
};
// Tests the bounds of the overscroll and that the "StretchAmount" returns back
// to 0 once the overscroll is done.
TEST_F(OverscrollBounceControllerTest, VerifyOverscrollStretch) {
// Test vertical overscroll.
SendGestureScrollBegin(WebGestureEvent::InertialPhaseState::kNonMomentum);
gfx::Vector2dF delta(0, -50);
EXPECT_EQ(gfx::Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(WebGestureEvent::InertialPhaseState::kNonMomentum,
delta, gfx::Vector2dF(0, -100));
EXPECT_EQ(gfx::Vector2dF(0, -19), helper_.StretchAmount());
SendGestureScrollUpdate(WebGestureEvent::InertialPhaseState::kNonMomentum,
delta, gfx::Vector2dF(0, 100));
EXPECT_EQ(gfx::Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollEnd();
// Test horizontal overscroll.
SendGestureScrollBegin(WebGestureEvent::InertialPhaseState::kNonMomentum);
delta = gfx::Vector2dF(-50, 0);
EXPECT_EQ(gfx::Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollUpdate(WebGestureEvent::InertialPhaseState::kNonMomentum,
delta, gfx::Vector2dF(-100, 0));
EXPECT_EQ(gfx::Vector2dF(-19, 0), helper_.StretchAmount());
SendGestureScrollUpdate(WebGestureEvent::InertialPhaseState::kNonMomentum,
delta, gfx::Vector2dF(100, 0));
EXPECT_EQ(gfx::Vector2dF(0, 0), helper_.StretchAmount());
SendGestureScrollEnd();
}
// Verify that ReconcileStretchAndScroll reduces the overscrolled delta.
TEST_F(OverscrollBounceControllerTest, ReconcileStretchAndScroll) {
// Test overscroll in both directions.
gfx::Vector2dF delta(0, -50);
SendGestureScrollBegin(WebGestureEvent::InertialPhaseState::kNonMomentum);
helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 8),
gfx::ScrollOffset(100, 100));
SendGestureScrollUpdate(WebGestureEvent::InertialPhaseState::kNonMomentum,
delta, gfx::Vector2dF(-100, -100));
EXPECT_EQ(gfx::Vector2dF(-19, -19), helper_.StretchAmount());
controller_.ReconcileStretchAndScroll();
EXPECT_EQ(gfx::Vector2dF(-18, -18), helper_.StretchAmount());
// Adjustment of gfx::ScrollOffset(-5, -8) should bring back the
// scroll_offset_ to 0.
EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(0, 0));
}
// Tests if the overscrolled delta maps correctly to the actual amount that the
// scroller gets stretched.
TEST_F(OverscrollBounceControllerTest, VerifyOverscrollBounceDistance) {
gfx::Vector2dF overscroll_bounce_distance(
controller_.OverscrollBounceDistance(gfx::Vector2dF(0, -100),
helper_.ScrollBounds()));
EXPECT_EQ(overscroll_bounce_distance.y(), -19);
overscroll_bounce_distance = controller_.OverscrollBounceDistance(
gfx::Vector2dF(-100, 0), helper_.ScrollBounds());
EXPECT_EQ(overscroll_bounce_distance.x(), -19);
}
} // namespace test
} // namespace blink
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/scheduler/web_widget_scheduler.h" #include "third_party/blink/public/platform/scheduler/web_widget_scheduler.h"
#include "third_party/blink/renderer/platform/widget/frame_widget.h" #include "third_party/blink/renderer/platform/widget/frame_widget.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
#include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h" #include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
#include "third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h" #include "third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h" #include "third_party/blink/renderer/platform/widget/widget_base.h"
......
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