Skip to content

Commit

Permalink
End the snap fling within 1 pixel of destination.
Browse files Browse the repository at this point in the history
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/1159088
Reviewed-by: David Bokan <bokan@chromium.org>
Reviewed-by: Majid Valipour <majidvp@chromium.org>
Commit-Queue: Sandra Sun <sunyunjia@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584119}
  • Loading branch information
sunyunjia authored and Commit Bot committed Aug 17, 2018
1 parent 87a4d2b commit e86044f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 23 deletions.
27 changes: 12 additions & 15 deletions cc/input/snap_fling_curve.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "cc/input/snap_fling_curve.h"

#include <algorithm>
#include <cmath>
#include "build/build_config.h"

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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);
Expand All @@ -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_);

Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions cc/input/snap_fling_curve.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
22 changes: 16 additions & 6 deletions cc/input/snap_fling_curve_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,19 @@ 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());
}

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());
Expand All @@ -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

0 comments on commit e86044f

Please sign in to comment.