Bug 1458653 - Don't accelerate a fling if the previous fling animation has slowed down below a velocity threshold. r=botond

This should prevent most cases of unintended fling acceleration. For example,
when scrolling paragraph-by-paragraph via a series of short flings, we would
often accelerate the next fling even if the previous fling had already slowed
down almost to a stop. With this change, we will no longer trigger acceleration
in that scenario.

This also matches Chrome's behavior.

This patch does not add a new pref for the new velocity threshold.
Chrome also shares the same velocity threshold for both velocities.

Differential Revision: https://phabricator.services.mozilla.com/D95469
This commit is contained in:
Markus Stange 2020-11-04 22:59:22 +00:00
Родитель 621c2b0fb7
Коммит cfbcc7d97b
6 изменённых файлов: 46 добавлений и 2 удалений

Просмотреть файл

@ -259,8 +259,9 @@ typedef PlatformSpecificStateBase
* Units: milliseconds
*
* \li\b apz.fling_accel_min_velocity
* The minimum velocity of the second fling for it to be considered for fling
* acceleration.
* The minimum velocity of the second fling, and the minimum velocity of the
* previous fling animation at the point of interruption, for the new fling to
* be considered for fling acceleration.
* Units: screen pixels per milliseconds
*
* \li\b apz.fling_accel_base_mult

Просмотреть файл

@ -16,6 +16,7 @@ namespace layers {
void FlingAccelerator::Reset() {
mPreviousFlingStartTime = SampleTime{};
mPreviousFlingStartingVelocity = ParentLayerPoint{};
mPreviousFlingCancelVelocity = ParentLayerPoint{};
}
static bool SameDirection(float aVelocity1, float aVelocity2) {
@ -53,6 +54,8 @@ ParentLayerPoint FlingAccelerator::GetFlingStartingVelocity(
}
}
Reset();
mPreviousFlingStartTime = aNow;
mPreviousFlingStartingVelocity = velocity;
@ -81,6 +84,15 @@ bool FlingAccelerator::ShouldAccelerate(
return false;
}
if (mPreviousFlingCancelVelocity.Length() <
StaticPrefs::apz_fling_accel_min_velocity()) {
FLING_LOG(
"%p The previous fling animation had slowed down too much when it was "
"interrupted (%f), not accelerating.\n",
this, float(mPreviousFlingCancelVelocity.Length()));
return false;
}
return true;
}

Просмотреть файл

@ -32,6 +32,10 @@ class FlingAccelerator final {
ParentLayerPoint GetFlingStartingVelocity(const SampleTime& aNow,
const ParentLayerPoint& aVelocity);
void ObserveFlingCanceled(const ParentLayerPoint& aVelocity) {
mPreviousFlingCancelVelocity = aVelocity;
}
protected:
bool ShouldAccelerate(const SampleTime& aNow,
const ParentLayerPoint& aVelocity) const;
@ -41,6 +45,9 @@ class FlingAccelerator final {
// The time at which the most recent fling started. This is the time when the
// finger is lifted at the end of the gesture, as the fling animation starts.
SampleTime mPreviousFlingStartTime;
// The velocity that the previous fling animation had at the point it was
// interrupted.
ParentLayerPoint mPreviousFlingCancelVelocity;
};
} // namespace layers

Просмотреть файл

@ -183,6 +183,10 @@ class GenericFlingAnimation : public AsyncPanZoomAnimation,
return true;
}
void Cancel(CancelAnimationFlags aFlags) override {
mApzc.mFlingAccelerator.ObserveFlingCanceled(mApzc.GetVelocityVector());
}
virtual bool HandleScrollOffsetUpdate(
const Maybe<CSSPoint>& aRelativeDelta) override {
return true;

Просмотреть файл

@ -146,3 +146,17 @@ TEST_F(APZCFlingAccelerationTester,
{0, 0, 14, 61, 41, 0, 45, 35});
CHECK_VELOCITY(Up, 3.2, 4.2);
}
TEST_F(APZCFlingAccelerationTester,
ShouldNotAccelerateWhenPreviousFlingHasSlowedDown) {
SCOPED_GFX_PREF_INT("apz.fling_accel_interval_ms", 750);
ExecutePanGesture100Hz(ScreenIntPoint{748, 1046},
{0, 9, 15, 23, 31, 30, 0, 34, 31, 29, 28, 24, 24, 11});
CHECK_VELOCITY(Up, 2.2, 3.0);
ExecuteWait(TimeDuration::FromMilliseconds(498));
CHECK_VELOCITY(Up, 0.8, 1.0);
ExecutePanGesture100Hz(ScreenIntPoint{745, 1056},
{0, 10, 17, 29, 29, 33, 33, 0, 31, 27, 13});
CHECK_VELOCITY(Up, 2.3, 2.7);
}

Просмотреть файл

@ -567,6 +567,12 @@ TEST_F(APZScrollHandoffTester, ScrollgrabFlingAcceleration1) {
SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
SCOPED_GFX_VAR(UseWebRender, bool, false);
CreateScrollgrabLayerTree(true /* make parent scrollable */);
// Note: Usually, fling acceleration does not work across handoff, because our
// fling acceleration code does not propagate the "fling cancel velocity"
// across handoff. However, this test sets apz.fling_min_velocity_threshold to
// zero, so the "fling cancel velocity" is allowed to be zero, and fling
// acceleration succeeds, almost by accident.
TestFlingAcceleration();
}