Bug 1709334 - Ensure calling SampleOverscrollAnimation for overscroll animations which are about to finish. r=botond

In cases where the overscroll amount is pretty small, the animation's
physics model considers it's finished, which exacly means it's about
to finish, so if we don't call SampleOverscrollAnimation in such cases,
the small amount of overscrolling value remains there, then we try to
create overscroll animations repeatedly even if the overscroll amount
is visually noticeablt.

Differential Revision: https://phabricator.services.mozilla.com/D114445
This commit is contained in:
Hiroyuki Ikezoe 2021-05-07 05:24:10 +00:00
Родитель 442aa07485
Коммит c99a053acb
4 изменённых файлов: 75 добавлений и 2 удалений

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

@ -235,6 +235,12 @@ bool Axis::IsOverscrollAnimationRunning() const {
return !mMSDModel.IsFinished(1.0);
}
bool Axis::IsOverscrollAnimationAlive() const {
// Unlike IsOverscrollAnimationRunning, check the position and the velocity to
// be sure that the animation has started but hasn't yet finished.
return mMSDModel.GetPosition() != 0.0 || mMSDModel.GetVelocity() != 0.0;
}
bool Axis::IsOverscrolled() const { return mOverscroll != 0.f; }
void Axis::ClearOverscroll() {

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

@ -174,8 +174,17 @@ class Axis {
*/
void ClearOverscroll();
/**
* Returns whether the overscroll animation is alive.
*/
bool IsOverscrollAnimationAlive() const;
/**
* Returns whether the overscroll animation is running.
* Note that unlike the above IsOverscrollAnimationAlive, this function
* returns false even if the animation is still there but is very close to
* the destination position and its velocity is quite low, i.e. it's time to
* finish.
*/
bool IsOverscrollAnimationRunning() const;

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

@ -37,9 +37,9 @@ class OverscrollAnimation : public AsyncPanZoomAnimation {
virtual bool DoSample(FrameMetrics& aFrameMetrics,
const TimeDuration& aDelta) override {
// Can't inline these variables due to short-circuit evaluation.
bool continueX = mApzc.mX.IsOverscrollAnimationRunning() &&
bool continueX = mApzc.mX.IsOverscrollAnimationAlive() &&
mApzc.mX.SampleOverscrollAnimation(aDelta);
bool continueY = mApzc.mY.IsOverscrollAnimationRunning() &&
bool continueY = mApzc.mY.IsOverscrollAnimationAlive() &&
mApzc.mY.SampleOverscrollAnimation(aDelta);
if (!continueX && !continueY) {
// If we got into overscroll from a fling, that fling did not request a

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

@ -1437,6 +1437,64 @@ TEST_F(APZCOverscrollTester, DynamicallyLoadingContent) {
}
#endif
#ifndef MOZ_WIDGET_ANDROID // Only applies to GenericOverscrollEffect
TEST_F(APZCOverscrollTester, SmallAmountOfOverscroll) {
SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
ScrollMetadata metadata;
FrameMetrics& metrics = metadata.GetMetrics();
metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
// Do vertical overscroll first.
ScreenIntPoint panPoint(50, 50);
PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
ScreenPoint(0, -10), mcc->Time());
mcc->AdvanceByMillis(10);
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
ScreenPoint(0, -10), mcc->Time());
mcc->AdvanceByMillis(10);
PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
mcc->Time());
mcc->AdvanceByMillis(10);
// Then do small horizontal overscroll which will be considered as "finished"
// by our overscroll animation physics model.
PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
ScreenPoint(-0.1, 0), mcc->Time());
mcc->AdvanceByMillis(10);
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
ScreenPoint(-0.2, 0), mcc->Time());
mcc->AdvanceByMillis(10);
PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
mcc->Time());
mcc->AdvanceByMillis(10);
EXPECT_TRUE(apzc->IsOverscrolled());
EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0); // overscrolled at top
EXPECT_TRUE(apzc->GetOverscrollAmount().x < 0); // and overscrolled at left
// Then do vertical scroll.
PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
ScreenPoint(0, 10), mcc->Time());
mcc->AdvanceByMillis(10);
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
ScreenPoint(0, 100), mcc->Time());
mcc->AdvanceByMillis(10);
PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
mcc->Time());
ParentLayerPoint scrollOffset =
apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting);
EXPECT_GT(scrollOffset.y, 0); // Make sure the vertical scroll offset is
// greater than zero.
// The small horizontal overscroll amount should be restored to zero.
ParentLayerPoint expectedScrollOffset(0, scrollOffset.y);
SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif
class APZCOverscrollTesterForLayersOnly : public APZCTreeManagerTester {
public:
APZCOverscrollTesterForLayersOnly() { mLayersOnly = true; }