Commit e86044fc authored by Sandra Sun's avatar Sandra Sun Committed by Commit Bot

End the snap fling within 1 pixel of destination.

The scroll offsets returned from blink are only integers. However,
if the target snap offset is fractional, it will never reach the
destination and will oscillate between the two closest integers until it
reaches the maximum time duration.

In this patch, we end the snap fling if we've reached the 1-pixel range
of the destination.

Bug: 866517
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I185fd4267c626e1f4e561e9bd92a962c8f289d38
Reviewed-on: https://chromium-review.googlesource.com/1159088Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Commit-Queue: Sandra Sun <sunyunjia@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584119}
parent 87a4d2bd
......@@ -4,6 +4,7 @@
#include "cc/input/snap_fling_curve.h"
#include <algorithm>
#include <cmath>
#include "build/build_config.h"
......@@ -43,6 +44,11 @@ double CalculateFirstDelta(double distance, double frames) {
return distance * (1 - kRatio) / (1 - std::pow(kRatio, frames));
}
bool IsWithinOnePixel(gfx::Vector2dF actual, gfx::Vector2dF target) {
return std::abs(actual.x() - target.x()) < 1 &&
std::abs(actual.y() - target.y()) < 1;
}
} // namespace
gfx::Vector2dF SnapFlingCurve::EstimateDisplacement(
......@@ -71,16 +77,7 @@ SnapFlingCurve::SnapFlingCurve(const gfx::Vector2dF& start_offset,
SnapFlingCurve::~SnapFlingCurve() = default;
double SnapFlingCurve::GetCurrentCurveDistance(base::TimeTicks time_stamp) {
double current_distance = GetDistanceFromDisplacement(current_displacement_);
base::TimeDelta current_time = time_stamp - start_time_;
// Finishes the curve if the time elapsed is longer than |duration_|, or the
// remaining distance is less than 1.
if (current_time >= duration_ || current_distance >= total_distance_ - 1) {
return total_distance_;
}
double SnapFlingCurve::GetCurrentCurveDistance(base::TimeDelta current_time) {
double current_frame = current_time.InMillisecondsF() / kMsPerFrame + 1;
double sum =
first_delta_ * (1 - std::pow(kRatio, current_frame)) / (1 - kRatio);
......@@ -93,13 +90,15 @@ gfx::Vector2dF SnapFlingCurve::GetScrollDelta(base::TimeTicks time_stamp) {
// The the snap offset may never be reached due to clamping or other factors.
// To avoid a never ending snap curve, we force the curve to end if the time
// has passed a maximum Duration.
if (time_stamp - start_time_ > kMaximumSnapDuration) {
// has passed |duration_| or the remaining displacement is less than 1.
base::TimeDelta current_time = time_stamp - start_time_;
if (current_time >= std::min(duration_, kMaximumSnapDuration) ||
IsWithinOnePixel(current_displacement_, total_displacement_)) {
is_finished_ = true;
return total_displacement_ - current_displacement_;
}
double new_distance = GetCurrentCurveDistance(time_stamp);
double new_distance = GetCurrentCurveDistance(current_time);
gfx::Vector2dF new_displacement(new_distance * ratio_x_,
new_distance * ratio_y_);
......@@ -108,8 +107,6 @@ gfx::Vector2dF SnapFlingCurve::GetScrollDelta(base::TimeTicks time_stamp) {
void SnapFlingCurve::UpdateCurrentOffset(const gfx::Vector2dF& current_offset) {
current_displacement_ = current_offset - start_offset_;
if (current_displacement_ == total_displacement_)
is_finished_ = true;
}
bool SnapFlingCurve::IsFinished() const {
......
......@@ -41,8 +41,8 @@ class CC_EXPORT SnapFlingCurve {
base::TimeDelta duration() const { return duration_; }
private:
// Returns the curve's current distance at |time_stamp|.
double GetCurrentCurveDistance(base::TimeTicks time_stamp);
// Returns the curve's current distance at |current_time|.
double GetCurrentCurveDistance(base::TimeDelta current_time);
// The initial scroll offset of the scroller.
const gfx::Vector2dF start_offset_;
......
......@@ -40,15 +40,12 @@ TEST(SnapFlingCurveTest, AdvanceHalfwayThrough) {
EXPECT_FALSE(curve.IsFinished());
}
TEST(SnapFlingCurveTest, AdvanceFullyThroughOnlyFinishesAfterUpdate) {
TEST(SnapFlingCurveTest, AdvanceFullyThrough) {
SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500),
base::TimeTicks());
gfx::Vector2dF delta =
curve.GetScrollDelta(base::TimeTicks() + curve.duration());
EXPECT_EQ(gfx::Vector2dF(400, 400), delta);
EXPECT_FALSE(curve.IsFinished());
curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500));
EXPECT_TRUE(curve.IsFinished());
}
......@@ -56,8 +53,6 @@ TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) {
SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500),
base::TimeTicks());
curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500));
EXPECT_TRUE(curve.IsFinished());
gfx::Vector2dF delta = curve.GetScrollDelta(base::TimeTicks());
EXPECT_EQ(gfx::Vector2dF(), delta);
EXPECT_TRUE(curve.IsFinished());
......@@ -67,5 +62,20 @@ TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) {
EXPECT_TRUE(curve.IsFinished());
}
TEST(SnapFlingCurveTest, FlingFinishesWithinOnePixel) {
SnapFlingCurve curve(gfx::Vector2dF(0, 0), gfx::Vector2dF(100.5, 99.5),
base::TimeTicks());
EXPECT_FALSE(curve.IsFinished());
curve.UpdateCurrentOffset(gfx::Vector2dF(99, 101));
// IsFinished() is updated in GetScrollDelta().
curve.GetScrollDelta(base::TimeTicks());
EXPECT_FALSE(curve.IsFinished());
curve.UpdateCurrentOffset(gfx::Vector2dF(100, 100));
curve.GetScrollDelta(base::TimeTicks());
EXPECT_TRUE(curve.IsFinished());
}
} // namespace test
} // namespace cc
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