mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1700215 - Generate OverscrollAnimation only if it's overscrolled on the axis. r=botond
This is a prerequisite change to keep momentum scrolls happening on the other axis where no overscroll animation is running. Differential Revision: https://phabricator.services.mozilla.com/D110793
This commit is contained in:
parent
a1a4fe1d55
commit
a41405e106
@ -56,7 +56,7 @@ void AxisPhysicsMSDModel::SetDestination(double aDestination) {
|
||||
mDestination = aDestination;
|
||||
}
|
||||
|
||||
bool AxisPhysicsMSDModel::IsFinished(double aSmallestVisibleIncrement) {
|
||||
bool AxisPhysicsMSDModel::IsFinished(double aSmallestVisibleIncrement) const {
|
||||
// In order to satisfy the condition of reaching the destination, the distance
|
||||
// between the simulation position and the destination must be less than
|
||||
// aSmallestVisibleIncrement while the speed is simultaneously less than
|
||||
|
@ -38,7 +38,7 @@ class AxisPhysicsMSDModel : public AxisPhysicsModel {
|
||||
* Returns true when the position is close to the destination and the
|
||||
* velocity is low.
|
||||
*/
|
||||
bool IsFinished(double aSmallestVisibleIncrement);
|
||||
bool IsFinished(double aSmallestVisibleIncrement) const;
|
||||
|
||||
protected:
|
||||
double Acceleration(const State& aState) override;
|
||||
|
@ -109,6 +109,24 @@ bool ShouldUseProgressivePaint() {
|
||||
#endif
|
||||
}
|
||||
|
||||
SideBits GetOverscrollSideBits(const ParentLayerPoint& aOverscrollAmount) {
|
||||
SideBits sides = SideBits::eNone;
|
||||
|
||||
if (aOverscrollAmount.x < 0) {
|
||||
sides |= SideBits::eLeft;
|
||||
} else if (aOverscrollAmount.x > 0) {
|
||||
sides |= SideBits::eRight;
|
||||
}
|
||||
|
||||
if (aOverscrollAmount.y < 0) {
|
||||
sides |= SideBits::eTop;
|
||||
} else if (aOverscrollAmount.y > 0) {
|
||||
sides |= SideBits::eBottom;
|
||||
}
|
||||
|
||||
return sides;
|
||||
}
|
||||
|
||||
} // namespace apz
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -205,6 +205,12 @@ bool AboutToCheckerboard(const FrameMetrics& aPaintedMetrics,
|
||||
* using the StaticPrefs getter directly.
|
||||
*/
|
||||
bool ShouldUseProgressivePaint();
|
||||
|
||||
/**
|
||||
* Returns SideBits where the given |aOverscrollAmount| overscrolls.
|
||||
*/
|
||||
SideBits GetOverscrollSideBits(const ParentLayerPoint& aOverscrollAmount);
|
||||
|
||||
} // namespace apz
|
||||
|
||||
} // namespace layers
|
||||
|
@ -2721,7 +2721,7 @@ nsEventStatus AsyncPanZoomController::OnPan(
|
||||
|
||||
if (aFingersOnTouchpad == FingersOnTouchpad::No) {
|
||||
if (IsOverscrolled() && mState != OVERSCROLL_ANIMATION) {
|
||||
StartOverscrollAnimation(velocity);
|
||||
StartOverscrollAnimation(velocity, GetOverscrollSideBits());
|
||||
} else if (!consumed) {
|
||||
// If there is unconsumed scroll and we're in the momentum part of the
|
||||
// pan gesture, terminate the momentum scroll. This prevents momentum
|
||||
@ -2754,7 +2754,7 @@ nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
|
||||
if (IsOverscrolled() && mState != OVERSCROLL_ANIMATION) {
|
||||
// If we are in overscrolled state, trigger OverscrollAnimation to
|
||||
// ensure we will snap back to the scroll edge.
|
||||
StartOverscrollAnimation(GetVelocityVector());
|
||||
StartOverscrollAnimation(GetVelocityVector(), GetOverscrollSideBits());
|
||||
} else {
|
||||
SetState(NOTHING);
|
||||
}
|
||||
@ -3635,7 +3635,7 @@ bool AsyncPanZoomController::OverscrollBehaviorAllowsSwipe() const {
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::HandleFlingOverscroll(
|
||||
const ParentLayerPoint& aVelocity,
|
||||
const ParentLayerPoint& aVelocity, SideBits aOverscrollSideBits,
|
||||
const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
|
||||
const RefPtr<const AsyncPanZoomController>& aScrolledApzc) {
|
||||
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
|
||||
@ -3659,17 +3659,19 @@ void AsyncPanZoomController::HandleFlingOverscroll(
|
||||
}
|
||||
|
||||
if (!IsZero(residualVelocity)) {
|
||||
mOverscrollEffect->HandleFlingOverscroll(residualVelocity);
|
||||
mOverscrollEffect->HandleFlingOverscroll(residualVelocity,
|
||||
aOverscrollSideBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::HandleSmoothScrollOverscroll(
|
||||
const ParentLayerPoint& aVelocity) {
|
||||
const ParentLayerPoint& aVelocity, SideBits aOverscrollSideBits) {
|
||||
// We must call BuildOverscrollHandoffChain from this deferred callback
|
||||
// function in order to avoid a deadlock when acquiring the tree lock.
|
||||
HandleFlingOverscroll(aVelocity, BuildOverscrollHandoffChain(), nullptr);
|
||||
HandleFlingOverscroll(aVelocity, aOverscrollSideBits,
|
||||
BuildOverscrollHandoffChain(), nullptr);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SmoothScrollTo(const CSSPoint& aDestination,
|
||||
@ -3730,13 +3732,13 @@ void AsyncPanZoomController::SmoothMsdScrollTo(const CSSPoint& aDestination) {
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::StartOverscrollAnimation(
|
||||
const ParentLayerPoint& aVelocity) {
|
||||
const ParentLayerPoint& aVelocity, SideBits aOverscrollSideBits) {
|
||||
SetState(OVERSCROLL_ANIMATION);
|
||||
|
||||
ParentLayerPoint velocity = aVelocity;
|
||||
AdjustDeltaForAllowedScrollDirections(velocity,
|
||||
GetOverscrollableDirections());
|
||||
StartAnimation(new OverscrollAnimation(*this, velocity));
|
||||
StartAnimation(new OverscrollAnimation(*this, velocity, aOverscrollSideBits));
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::CallDispatchScroll(
|
||||
@ -3834,6 +3836,10 @@ ParentLayerPoint AsyncPanZoomController::GetOverscrollAmount() const {
|
||||
return {mX.GetOverscroll(), mY.GetOverscroll()};
|
||||
}
|
||||
|
||||
SideBits AsyncPanZoomController::GetOverscrollSideBits() const {
|
||||
return apz::GetOverscrollSideBits({mX.GetOverscroll(), mY.GetOverscroll()});
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::RestoreOverscrollAmount(
|
||||
const ParentLayerPoint& aOverscroll) {
|
||||
mX.RestoreOverscroll(aOverscroll.x);
|
||||
@ -4175,7 +4181,7 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() {
|
||||
// animation - if so, don't start a new one.
|
||||
if (IsOverscrolled() && mState != OVERSCROLL_ANIMATION) {
|
||||
APZC_LOG("%p is overscrolled, starting snap-back\n", this);
|
||||
StartOverscrollAnimation(ParentLayerPoint(0, 0));
|
||||
StartOverscrollAnimation(ParentLayerPoint(0, 0), GetOverscrollSideBits());
|
||||
return true;
|
||||
}
|
||||
// If we don't kick off an overscroll animation, we still need to ask the
|
||||
|
@ -809,6 +809,12 @@ class AsyncPanZoomController {
|
||||
* Gets the amount by which this APZC is overscrolled along both axes.
|
||||
*/
|
||||
ParentLayerPoint GetOverscrollAmount() const;
|
||||
|
||||
/**
|
||||
* Returns SideBits where this APZC is overscrolled.
|
||||
*/
|
||||
SideBits GetOverscrollSideBits() const;
|
||||
|
||||
/**
|
||||
* Restore the amount by which this APZC is overscrolled along both axes
|
||||
* to the specified amount. This is for test-related use; overscrolling
|
||||
@ -1452,14 +1458,16 @@ class AsyncPanZoomController {
|
||||
// later in the handoff chain, or if there are no takers, continuing the
|
||||
// fling and entering an overscrolled state.
|
||||
void HandleFlingOverscroll(
|
||||
const ParentLayerPoint& aVelocity,
|
||||
const ParentLayerPoint& aVelocity, SideBits aOverscrollSideBits,
|
||||
const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
|
||||
const RefPtr<const AsyncPanZoomController>& aScrolledApzc);
|
||||
|
||||
void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity);
|
||||
void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity,
|
||||
SideBits aOverscrollSideBits);
|
||||
|
||||
// Start an overscroll animation with the given initial velocity.
|
||||
void StartOverscrollAnimation(const ParentLayerPoint& aVelocity);
|
||||
void StartOverscrollAnimation(const ParentLayerPoint& aVelocity,
|
||||
SideBits aOverscrollSideBits);
|
||||
|
||||
// Return the directions in which this APZC allows overscrolling.
|
||||
ScrollDirections GetOverscrollableDirections() const;
|
||||
|
@ -233,6 +233,10 @@ bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Axis::IsOverscrollAnimationRunning() const {
|
||||
return !mMSDModel.IsFinished(1.0);
|
||||
}
|
||||
|
||||
bool Axis::IsOverscrolled() const { return mOverscroll != 0.f; }
|
||||
|
||||
void Axis::ClearOverscroll() {
|
||||
|
@ -174,6 +174,11 @@ class Axis {
|
||||
*/
|
||||
void ClearOverscroll();
|
||||
|
||||
/**
|
||||
* Returns whether the overscroll animation is running.
|
||||
*/
|
||||
bool IsOverscrollAnimationRunning() const;
|
||||
|
||||
/**
|
||||
* Gets the starting position of the touch supplied in StartTouch().
|
||||
*/
|
||||
|
@ -164,12 +164,13 @@ class GenericFlingAnimation : public AsyncPanZoomAnimation,
|
||||
FLING_LOG("%p fling went into overscroll, handing off with velocity %s\n",
|
||||
&mApzc, ToString(velocity).c_str());
|
||||
mDeferredTasks.AppendElement(
|
||||
NewRunnableMethod<ParentLayerPoint,
|
||||
NewRunnableMethod<ParentLayerPoint, SideBits,
|
||||
RefPtr<const OverscrollHandoffChain>,
|
||||
RefPtr<const AsyncPanZoomController>>(
|
||||
"layers::AsyncPanZoomController::HandleFlingOverscroll", &mApzc,
|
||||
&AsyncPanZoomController::HandleFlingOverscroll, velocity,
|
||||
mOverscrollHandoffChain, mScrolledApzc));
|
||||
apz::GetOverscrollSideBits(overscroll), mOverscrollHandoffChain,
|
||||
mScrolledApzc));
|
||||
|
||||
// If there is a remaining velocity on this APZC, continue this fling
|
||||
// as well. (This fling and the handed-off fling will run concurrently.)
|
||||
|
@ -19,10 +19,15 @@ namespace layers {
|
||||
class OverscrollAnimation : public AsyncPanZoomAnimation {
|
||||
public:
|
||||
OverscrollAnimation(AsyncPanZoomController& aApzc,
|
||||
const ParentLayerPoint& aVelocity)
|
||||
const ParentLayerPoint& aVelocity,
|
||||
SideBits aOverscrollSideBits)
|
||||
: mApzc(aApzc) {
|
||||
mApzc.mX.StartOverscrollAnimation(aVelocity.x);
|
||||
mApzc.mY.StartOverscrollAnimation(aVelocity.y);
|
||||
if ((aOverscrollSideBits & SideBits::eLeftRight) != SideBits::eNone) {
|
||||
mApzc.mX.StartOverscrollAnimation(aVelocity.x);
|
||||
}
|
||||
if ((aOverscrollSideBits & SideBits::eTopBottom) != SideBits::eNone) {
|
||||
mApzc.mY.StartOverscrollAnimation(aVelocity.y);
|
||||
}
|
||||
}
|
||||
virtual ~OverscrollAnimation() {
|
||||
mApzc.mX.EndOverscrollAnimation();
|
||||
@ -32,8 +37,10 @@ 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.SampleOverscrollAnimation(aDelta);
|
||||
bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta);
|
||||
bool continueX = mApzc.mX.IsOverscrollAnimationRunning() &&
|
||||
mApzc.mX.SampleOverscrollAnimation(aDelta);
|
||||
bool continueY = mApzc.mY.IsOverscrollAnimationRunning() &&
|
||||
mApzc.mY.SampleOverscrollAnimation(aDelta);
|
||||
if (!continueX && !continueY) {
|
||||
// If we got into overscroll from a fling, that fling did not request a
|
||||
// fling snap to avoid a resulting scrollTo from cancelling the overscroll
|
||||
@ -65,7 +72,8 @@ class OverscrollEffectBase {
|
||||
virtual ~OverscrollEffectBase() = default;
|
||||
virtual void ConsumeOverscroll(ParentLayerPoint& aOverscroll,
|
||||
ScrollDirections aOverscrolableDirections) = 0;
|
||||
virtual void HandleFlingOverscroll(const ParentLayerPoint& aVelocity) = 0;
|
||||
virtual void HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
|
||||
SideBits aOverscrollSideBits) = 0;
|
||||
};
|
||||
|
||||
// A generic overscroll effect, implemented by AsyncPanZoomController itself.
|
||||
@ -91,8 +99,9 @@ class GenericOverscrollEffect : public OverscrollEffectBase {
|
||||
}
|
||||
}
|
||||
|
||||
void HandleFlingOverscroll(const ParentLayerPoint& aVelocity) override {
|
||||
mApzc.StartOverscrollAnimation(aVelocity);
|
||||
void HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
|
||||
SideBits aOverscrollSideBits) override {
|
||||
mApzc.StartOverscrollAnimation(aVelocity, aOverscrollSideBits);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -117,7 +126,8 @@ class WidgetOverscrollEffect : public OverscrollEffectBase {
|
||||
}
|
||||
}
|
||||
|
||||
void HandleFlingOverscroll(const ParentLayerPoint& aVelocity) override {
|
||||
void HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
|
||||
SideBits aOverscrollSideBits) override {
|
||||
RefPtr<GeckoContentController> controller =
|
||||
mApzc.GetGeckoContentController();
|
||||
if (controller) {
|
||||
|
@ -103,9 +103,10 @@ bool SmoothMsdScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
|
||||
// violate the lock ordering. Instead we schedule
|
||||
// HandleSmoothScrollOverscroll() to be called after mRecursiveMutex is
|
||||
// released.
|
||||
mDeferredTasks.AppendElement(NewRunnableMethod<ParentLayerPoint>(
|
||||
mDeferredTasks.AppendElement(NewRunnableMethod<ParentLayerPoint, SideBits>(
|
||||
"layers::AsyncPanZoomController::HandleSmoothScrollOverscroll", &mApzc,
|
||||
&AsyncPanZoomController::HandleSmoothScrollOverscroll, velocity));
|
||||
&AsyncPanZoomController::HandleSmoothScrollOverscroll, velocity,
|
||||
apz::GetOverscrollSideBits(overscroll)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user