Bug 1835600 - Add scroll snap support to SmoothScrollAnimation. r=hiro

And also propagate the ScrollTriggeredByScript flag through it.

Differential Revision: https://phabricator.services.mozilla.com/D181421
This commit is contained in:
Botond Ballo 2023-06-23 07:30:24 +00:00
parent bf6116ce93
commit a716f5be1d
5 changed files with 47 additions and 22 deletions

View File

@ -3936,11 +3936,12 @@ void AsyncPanZoomController::HandleSmoothScrollOverscroll(
BuildOverscrollHandoffChain(), nullptr);
}
void AsyncPanZoomController::SmoothScrollTo(const CSSPoint& aDestination,
const ScrollOrigin& aOrigin) {
void AsyncPanZoomController::SmoothScrollTo(
CSSSnapTarget&& aDestination, ScrollTriggeredByScript aTriggeredByScript,
const ScrollOrigin& aOrigin) {
// Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s and then
// to appunits/second.
nsPoint destination = CSSPoint::ToAppUnits(aDestination);
nsPoint destination = CSSPoint::ToAppUnits(aDestination.mPosition);
nsSize velocity;
if (Metrics().GetZoom() != CSSToParentLayerScale(0)) {
velocity = CSSSize::ToAppUnits(ParentLayerSize(mX.GetVelocity() * 1000.0f,
@ -3953,8 +3954,9 @@ void AsyncPanZoomController::SmoothScrollTo(const CSSPoint& aDestination,
mAnimation->AsSmoothScrollAnimation());
if (animation->GetScrollOrigin() == aOrigin) {
APZC_LOG("%p updating destination on existing animation\n", this);
animation->UpdateDestination(GetFrameTime().Time(), destination,
velocity);
animation->UpdateDestinationAndSnapTargets(
GetFrameTime().Time(), destination, velocity,
std::move(aDestination.mTargetIds), aTriggeredByScript);
return;
}
}
@ -3965,7 +3967,9 @@ void AsyncPanZoomController::SmoothScrollTo(const CSSPoint& aDestination,
CSSPoint::ToAppUnits(Metrics().GetVisualScrollOffset());
RefPtr<SmoothScrollAnimation> animation =
new SmoothScrollAnimation(*this, initialPosition, aOrigin);
animation->UpdateDestination(GetFrameTime().Time(), destination, velocity);
animation->UpdateDestinationAndSnapTargets(
GetFrameTime().Time(), destination, velocity,
std::move(aDestination.mTargetIds), aTriggeredByScript);
StartAnimation(animation.get());
}
@ -4690,6 +4694,10 @@ bool AsyncPanZoomController::UpdateAnimation(
mLastSnapTargetIds =
mAnimation->AsSmoothMsdScrollAnimation()->TakeSnapTargetIds();
}
} else if (mAnimation->AsSmoothScrollAnimation()) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
mLastSnapTargetIds =
mAnimation->AsSmoothScrollAnimation()->TakeSnapTargetIds();
}
mAnimation = nullptr;
}
@ -5518,10 +5526,10 @@ void AsyncPanZoomController::NotifyLayersUpdated(
scrollUpdate.GetScrollTriggeredByScript());
} else {
MOZ_ASSERT(scrollUpdate.GetMode() == ScrollMode::Smooth);
MOZ_ASSERT(!scrollUpdate.WasTriggeredByScript());
MOZ_ASSERT(scrollUpdate.GetSnapTargetIds().mIdsOnX.IsEmpty());
MOZ_ASSERT(scrollUpdate.GetSnapTargetIds().mIdsOnY.IsEmpty());
SmoothScrollTo(destination, scrollUpdate.GetOrigin());
SmoothScrollTo(
CSSSnapTarget{destination, scrollUpdate.GetSnapTargetIds()},
scrollUpdate.GetScrollTriggeredByScript(),
scrollUpdate.GetOrigin());
}
continue;
}

View File

@ -1583,7 +1583,8 @@ class AsyncPanZoomController {
// Start a smooth-scrolling animation to the given destination, with physics
// based on the prefs for the indicated origin.
void SmoothScrollTo(const CSSPoint& aDestination,
void SmoothScrollTo(CSSSnapTarget&& aDestination,
ScrollTriggeredByScript aTriggeredByScript,
const ScrollOrigin& aOrigin);
// Start a smooth-scrolling animation to the given destination, with MSD

View File

@ -6,6 +6,8 @@
#include "SmoothScrollAnimation.h"
#include "ScrollAnimationBezierPhysics.h"
#include "ScrollPositionUpdate.h"
#include "apz/src/GenericScrollAnimation.h"
#include "mozilla/layers/APZPublicUtils.h"
namespace mozilla {
@ -17,12 +19,23 @@ SmoothScrollAnimation::SmoothScrollAnimation(AsyncPanZoomController& aApzc,
: GenericScrollAnimation(
aApzc, aInitialPosition,
apz::ComputeBezierAnimationSettingsForOrigin(aOrigin)),
mOrigin(aOrigin) {}
mOrigin(aOrigin),
mTriggeredByScript(ScrollTriggeredByScript::No) {}
SmoothScrollAnimation* SmoothScrollAnimation::AsSmoothScrollAnimation() {
return this;
}
void SmoothScrollAnimation::UpdateDestinationAndSnapTargets(
TimeStamp aTime, const nsPoint& aDestination,
const nsSize& aCurrentVelocity, ScrollSnapTargetIds&& aSnapTargetIds,
ScrollTriggeredByScript aTriggeredByScript) {
GenericScrollAnimation::UpdateDestination(aTime, aDestination,
aCurrentVelocity);
mSnapTargetIds = std::move(aSnapTargetIds);
mTriggeredByScript = aTriggeredByScript;
}
ScrollOrigin SmoothScrollAnimation::GetScrollOrigin() const { return mOrigin; }
ScrollOrigin SmoothScrollAnimation::GetScrollOriginForAction(

View File

@ -8,6 +8,7 @@
#define mozilla_layers_SmoothScrollAnimation_h_
#include "GenericScrollAnimation.h"
#include "ScrollPositionUpdate.h"
#include "mozilla/ScrollOrigin.h"
#include "mozilla/layers/KeyboardScrollAction.h"
@ -19,16 +20,26 @@ class AsyncPanZoomController;
class SmoothScrollAnimation : public GenericScrollAnimation {
public:
SmoothScrollAnimation(AsyncPanZoomController& aApzc,
const nsPoint& aInitialPosition,
ScrollOrigin aScrollOrigin);
const nsPoint& aInitialPosition, ScrollOrigin aOrigin);
void UpdateDestinationAndSnapTargets(
TimeStamp aTime, const nsPoint& aDestination,
const nsSize& aCurrentVelocity, ScrollSnapTargetIds&& aSnapTargetIds,
ScrollTriggeredByScript aTriggeredByScript);
SmoothScrollAnimation* AsSmoothScrollAnimation() override;
bool WasTriggeredByScript() const override {
return mTriggeredByScript == ScrollTriggeredByScript::Yes;
}
ScrollSnapTargetIds TakeSnapTargetIds() { return std::move(mSnapTargetIds); }
ScrollOrigin GetScrollOrigin() const;
static ScrollOrigin GetScrollOriginForAction(
KeyboardScrollAction::KeyboardScrollActionType aAction);
private:
ScrollOrigin mOrigin;
ScrollSnapTargetIds mSnapTargetIds;
ScrollTriggeredByScript mTriggeredByScript;
};
} // namespace layers

View File

@ -2560,14 +2560,6 @@ void nsHTMLScrollFrame::ScrollToWithOrigin(nsPoint aScrollPosition,
aParams.IsSmooth() && nsLayoutUtils::IsSmoothScrollingEnabled();
if (!mAsyncScroll) {
if (isSmoothScroll && canHandoffToApz) {
// APZ does not handle ScrollTriggeredByScript::Yes and snapTargetIds for
// ScrollMode::Smooth (but this can be added if the assertion firing
// indicates it's necessary).
MOZ_ASSERT(aParams.mTriggeredByScript == ScrollTriggeredByScript::No);
if (snapTargetIds) {
MOZ_ASSERT(snapTargetIds->mIdsOnX.IsEmpty());
MOZ_ASSERT(snapTargetIds->mIdsOnY.IsEmpty());
}
ApzSmoothScrollTo(mDestination, ScrollMode::Smooth, aParams.mOrigin,
aParams.mTriggeredByScript, std::move(snapTargetIds));
return;