mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1774537 - Propagate last snap target id(s) from APZ to the content. r=botond
Depends on D149495 Differential Revision: https://phabricator.services.mozilla.com/D149496
This commit is contained in:
parent
52a1e4ddb2
commit
802ddc1ef6
@ -10,14 +10,15 @@
|
||||
#include <iosfwd>
|
||||
#include <stdint.h> // for uint8_t, uint32_t, uint64_t
|
||||
|
||||
#include "FrameMetrics.h" // for FrameMetrics
|
||||
#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
|
||||
#include "mozilla/gfx/BasePoint.h" // for BasePoint
|
||||
#include "mozilla/gfx/Rect.h" // for RoundedIn
|
||||
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp
|
||||
#include "Units.h" // for CSSRect, CSSPixel, etc
|
||||
#include "UnitTransforms.h" // for ViewAs
|
||||
#include "FrameMetrics.h" // for FrameMetrics
|
||||
#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
|
||||
#include "mozilla/gfx/BasePoint.h" // for BasePoint
|
||||
#include "mozilla/gfx/Rect.h" // for RoundedIn
|
||||
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
|
||||
#include "mozilla/ScrollSnapTargetId.h" // for ScrollSnapTargetIds
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp
|
||||
#include "Units.h" // for CSSRect, CSSPixel, etc
|
||||
#include "UnitTransforms.h" // for ViewAs
|
||||
|
||||
namespace IPC {
|
||||
template <typename T>
|
||||
@ -65,7 +66,8 @@ struct RepaintRequest {
|
||||
const ScreenMargin& aDisplayportMargins,
|
||||
const ScrollOffsetUpdateType aScrollUpdateType,
|
||||
APZScrollAnimationType aScrollAnimationType,
|
||||
const APZScrollGeneration& aScrollGenerationOnApz)
|
||||
const APZScrollGeneration& aScrollGenerationOnApz,
|
||||
const ScrollSnapTargetIds& aLastSnapTargetIds)
|
||||
: mScrollId(aOther.GetScrollId()),
|
||||
mPresShellResolution(aOther.GetPresShellResolution()),
|
||||
mCompositionBounds(aOther.GetCompositionBounds()),
|
||||
@ -82,6 +84,7 @@ struct RepaintRequest {
|
||||
mPaintRequestTime(aOther.GetPaintRequestTime()),
|
||||
mScrollUpdateType(aScrollUpdateType),
|
||||
mScrollAnimationType(aScrollAnimationType),
|
||||
mLastSnapTargetIds(aLastSnapTargetIds),
|
||||
mIsRootContent(aOther.IsRootContent()),
|
||||
mIsScrollInfoLayer(aOther.IsScrollInfoLayer()) {}
|
||||
|
||||
@ -104,6 +107,7 @@ struct RepaintRequest {
|
||||
mPaintRequestTime == aOther.mPaintRequestTime &&
|
||||
mScrollUpdateType == aOther.mScrollUpdateType &&
|
||||
mScrollAnimationType == aOther.mScrollAnimationType &&
|
||||
mLastSnapTargetIds == aOther.mLastSnapTargetIds &&
|
||||
mIsRootContent == aOther.mIsRootContent &&
|
||||
mIsScrollInfoLayer == aOther.mIsScrollInfoLayer;
|
||||
}
|
||||
@ -198,6 +202,10 @@ struct RepaintRequest {
|
||||
return mScrollAnimationType;
|
||||
}
|
||||
|
||||
const ScrollSnapTargetIds& GetLastSnapTargetIds() const {
|
||||
return mLastSnapTargetIds;
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetIsRootContent(bool aIsRootContent) {
|
||||
mIsRootContent = aIsRootContent;
|
||||
@ -298,6 +306,8 @@ struct RepaintRequest {
|
||||
|
||||
APZScrollAnimationType mScrollAnimationType;
|
||||
|
||||
ScrollSnapTargetIds mLastSnapTargetIds;
|
||||
|
||||
// Whether or not this is the root scroll frame for the root content document.
|
||||
bool mIsRootContent : 1;
|
||||
|
||||
|
@ -1976,7 +1976,7 @@ nsEventStatus AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent) {
|
||||
CSSPoint destination = GetKeyboardDestination(aEvent.mAction);
|
||||
ScrollOrigin scrollOrigin =
|
||||
SmoothScrollAnimation::GetScrollOriginForAction(aEvent.mAction.mType);
|
||||
bool scrollSnapped = MaybeAdjustDestinationForScrollSnapping(
|
||||
Maybe<CSSSnapTarget> snapTarget = MaybeAdjustDestinationForScrollSnapping(
|
||||
aEvent, destination, GetScrollSnapFlagsForKeyboardAction(aEvent.mAction));
|
||||
ScrollMode scrollMode = apz::GetScrollModeForOrigin(scrollOrigin);
|
||||
|
||||
@ -2013,6 +2013,9 @@ nsEventStatus AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent) {
|
||||
SetState(KEYBOARD_SCROLL);
|
||||
}
|
||||
|
||||
if (snapTarget) {
|
||||
mLastSnapTargetIds = std::move(snapTarget->mTargetIds);
|
||||
}
|
||||
SetState(NOTHING);
|
||||
|
||||
return nsEventStatus_eConsumeDoDefault;
|
||||
@ -2023,13 +2026,13 @@ nsEventStatus AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent) {
|
||||
// update it.
|
||||
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||
|
||||
if (scrollSnapped) {
|
||||
if (snapTarget) {
|
||||
// If we're scroll snapping, use a smooth scroll animation to get
|
||||
// the desired physics. Note that SmoothMsdScrollTo() will re-use an
|
||||
// existing smooth scroll animation if there is one.
|
||||
APZC_LOG("%p keyboard scrolling to snap point %s\n", this,
|
||||
ToString(destination).c_str());
|
||||
SmoothMsdScrollTo(destination, ScrollTriggeredByScript::No);
|
||||
SmoothMsdScrollTo(std::move(*snapTarget), ScrollTriggeredByScript::No);
|
||||
return nsEventStatus_eConsumeDoDefault;
|
||||
}
|
||||
|
||||
@ -2418,8 +2421,9 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(
|
||||
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||
startPosition = Metrics().GetVisualScrollOffset();
|
||||
}
|
||||
MaybeAdjustDeltaForScrollSnappingOnWheelInput(aEvent, delta,
|
||||
startPosition);
|
||||
Maybe<CSSSnapTarget> snapTarget =
|
||||
MaybeAdjustDeltaForScrollSnappingOnWheelInput(aEvent, delta,
|
||||
startPosition);
|
||||
|
||||
ScreenPoint distance = ToScreenCoordinates(
|
||||
ParentLayerPoint(fabs(delta.x), fabs(delta.y)), aEvent.mLocalOrigin);
|
||||
@ -2436,11 +2440,14 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(
|
||||
CallDispatchScroll(startPoint, endPoint, handoffState);
|
||||
ParentLayerPoint remainingDelta = endPoint - startPoint;
|
||||
if (remainingDelta != delta) {
|
||||
// If any scrolling happened, set KEYBOARD_SCROLL explicitly so that it
|
||||
// If any scrolling happened, set WHEEL_SCROLL explicitly so that it
|
||||
// will trigger a TransformEnd notification.
|
||||
SetState(WHEEL_SCROLL);
|
||||
}
|
||||
|
||||
if (snapTarget) {
|
||||
mLastSnapTargetIds = std::move(snapTarget->mTargetIds);
|
||||
}
|
||||
SetState(NOTHING);
|
||||
|
||||
// The calls above handle their own locking; moreover,
|
||||
@ -2465,14 +2472,15 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(
|
||||
CSSPoint startPosition = GetCurrentAnimationDestination(lock).valueOr(
|
||||
Metrics().GetVisualScrollOffset());
|
||||
|
||||
if (MaybeAdjustDeltaForScrollSnappingOnWheelInput(aEvent, delta,
|
||||
startPosition)) {
|
||||
if (Maybe<CSSSnapTarget> snapTarget =
|
||||
MaybeAdjustDeltaForScrollSnappingOnWheelInput(aEvent, delta,
|
||||
startPosition)) {
|
||||
// If we're scroll snapping, use a smooth scroll animation to get
|
||||
// the desired physics. Note that SmoothMsdScrollTo() will re-use an
|
||||
// existing smooth scroll animation if there is one.
|
||||
APZC_LOG("%p wheel scrolling to snap point %s\n", this,
|
||||
ToString(startPosition).c_str());
|
||||
SmoothMsdScrollTo(startPosition, ScrollTriggeredByScript::No);
|
||||
SmoothMsdScrollTo(std::move(*snapTarget), ScrollTriggeredByScript::No);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3811,12 +3819,14 @@ void AsyncPanZoomController::SmoothScrollTo(const CSSPoint& aDestination,
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SmoothMsdScrollTo(
|
||||
const CSSPoint& aDestination, ScrollTriggeredByScript aTriggeredByScript) {
|
||||
CSSSnapTarget&& aDestination, ScrollTriggeredByScript aTriggeredByScript) {
|
||||
if (mState == SMOOTHMSD_SCROLL && mAnimation) {
|
||||
APZC_LOG("%p updating destination on existing animation\n", this);
|
||||
RefPtr<SmoothMsdScrollAnimation> animation(
|
||||
static_cast<SmoothMsdScrollAnimation*>(mAnimation.get()));
|
||||
animation->SetDestination(aDestination, aTriggeredByScript);
|
||||
animation->SetDestination(aDestination.mPosition,
|
||||
std::move(aDestination.mTargetIds),
|
||||
aTriggeredByScript);
|
||||
} else {
|
||||
CancelAnimation();
|
||||
SetState(SMOOTHMSD_SCROLL);
|
||||
@ -3829,10 +3839,11 @@ void AsyncPanZoomController::SmoothMsdScrollTo(
|
||||
}
|
||||
|
||||
StartAnimation(new SmoothMsdScrollAnimation(
|
||||
*this, Metrics().GetVisualScrollOffset(), initialVelocity, aDestination,
|
||||
*this, Metrics().GetVisualScrollOffset(), initialVelocity,
|
||||
aDestination.mPosition,
|
||||
StaticPrefs::layout_css_scroll_behavior_spring_constant(),
|
||||
StaticPrefs::layout_css_scroll_behavior_damping_ratio(),
|
||||
aTriggeredByScript));
|
||||
std::move(aDestination.mTargetIds), aTriggeredByScript));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3983,6 +3994,7 @@ void AsyncPanZoomController::CancelAnimation(CancelAnimationFlags aFlags) {
|
||||
}
|
||||
|
||||
SetState(NOTHING);
|
||||
mLastSnapTargetIds = ScrollSnapTargetIds{};
|
||||
mAnimation = nullptr;
|
||||
// Since there is no animation in progress now the axes should
|
||||
// have no velocity either. If we are dropping the velocity from a non-zero
|
||||
@ -4409,7 +4421,7 @@ void AsyncPanZoomController::RequestContentRepaint(
|
||||
: APZScrollAnimationType::TriggeredByUserInput;
|
||||
}
|
||||
RepaintRequest request(aFrameMetrics, aDisplayportMargins, aUpdateType,
|
||||
animationType, mScrollGeneration);
|
||||
animationType, mScrollGeneration, mLastSnapTargetIds);
|
||||
|
||||
if (request.IsRootContent() && request.GetZoom() != mLastNotifiedZoom &&
|
||||
mState != PINCHING && mState != ANIMATING_ZOOM) {
|
||||
@ -4435,7 +4447,9 @@ void AsyncPanZoomController::RequestContentRepaint(
|
||||
request.GetScrollUpdateType() ==
|
||||
mLastPaintRequestMetrics.GetScrollUpdateType() &&
|
||||
request.GetScrollAnimationType() ==
|
||||
mLastPaintRequestMetrics.GetScrollAnimationType()) {
|
||||
mLastPaintRequestMetrics.GetScrollAnimationType() &&
|
||||
request.GetLastSnapTargetIds() ==
|
||||
mLastPaintRequestMetrics.GetLastSnapTargetIds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4511,6 +4525,10 @@ bool AsyncPanZoomController::UpdateAnimation(
|
||||
*aOutDeferredTasks = mAnimation->TakeDeferredTasks();
|
||||
if (!continueAnimation) {
|
||||
SetState(NOTHING);
|
||||
if (mAnimation->AsSmoothMsdScrollAnimation()) {
|
||||
mLastSnapTargetIds =
|
||||
mAnimation->AsSmoothMsdScrollAnimation()->TakeSnapTargetIds();
|
||||
}
|
||||
mAnimation = nullptr;
|
||||
}
|
||||
// Request a repaint at the end of the animation in case something such as a
|
||||
@ -5318,7 +5336,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(
|
||||
}
|
||||
|
||||
if (scrollUpdate.GetMode() == ScrollMode::SmoothMsd) {
|
||||
SmoothMsdScrollTo(destination,
|
||||
// FIXME: Need to use ScrollSnapTargetIds coming from the main-thread.
|
||||
SmoothMsdScrollTo(CSSSnapTarget{destination},
|
||||
scrollUpdate.GetScrollTriggeredByScript());
|
||||
} else {
|
||||
MOZ_ASSERT(scrollUpdate.GetMode() == ScrollMode::Smooth);
|
||||
@ -6087,7 +6106,7 @@ void AsyncPanZoomController::SetTestAsyncZoom(
|
||||
ScheduleComposite();
|
||||
}
|
||||
|
||||
Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
|
||||
Maybe<CSSSnapTarget> AsyncPanZoomController::FindSnapPointNear(
|
||||
const CSSPoint& aDestination, ScrollUnit aUnit,
|
||||
ScrollSnapFlags aSnapFlags) {
|
||||
mRecursiveMutex.AssertCurrentThreadIn();
|
||||
@ -6104,19 +6123,20 @@ Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
|
||||
// of the scroll frame's scroll range. Clamp it here (this matches the
|
||||
// behaviour of the main-thread code path, which clamps it in
|
||||
// nsGfxScrollFrame::ScrollTo()).
|
||||
return Some(scrollRange.ClampPoint(cssSnapPoint));
|
||||
return Some(CSSSnapTarget{scrollRange.ClampPoint(cssSnapPoint),
|
||||
snapTarget->mTargetIds});
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination,
|
||||
ScrollSnapFlags aSnapFlags) {
|
||||
if (Maybe<CSSPoint> snapPoint = FindSnapPointNear(
|
||||
if (Maybe<CSSSnapTarget> snapTarget = FindSnapPointNear(
|
||||
aDestination, ScrollUnit::DEVICE_PIXELS, aSnapFlags)) {
|
||||
if (*snapPoint != Metrics().GetVisualScrollOffset()) {
|
||||
if (snapTarget->mPosition != Metrics().GetVisualScrollOffset()) {
|
||||
APZC_LOG("%p smooth scrolling to snap point %s\n", this,
|
||||
ToString(*snapPoint).c_str());
|
||||
SmoothMsdScrollTo(*snapPoint, ScrollTriggeredByScript::No);
|
||||
ToString(snapTarget->mPosition).c_str());
|
||||
SmoothMsdScrollTo(std::move(*snapTarget), ScrollTriggeredByScript::No);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6155,8 +6175,9 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
|
||||
if (predictedDelta != ParentLayerPoint()) {
|
||||
snapFlags |= ScrollSnapFlags::IntendedDirection;
|
||||
}
|
||||
if (MaybeAdjustDeltaForScrollSnapping(ScrollUnit::DEVICE_PIXELS, snapFlags,
|
||||
predictedDelta, startPosition)) {
|
||||
if (Maybe<CSSSnapTarget> snapTarget = MaybeAdjustDeltaForScrollSnapping(
|
||||
ScrollUnit::DEVICE_PIXELS, snapFlags, predictedDelta,
|
||||
startPosition)) {
|
||||
APZC_LOG(
|
||||
"%p fling snapping. friction: %f velocity: %f, %f "
|
||||
"predictedDelta: %f, %f position: %f, %f "
|
||||
@ -6166,37 +6187,38 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
|
||||
(float)Metrics().GetVisualScrollOffset().y, (float)startPosition.x,
|
||||
(float)startPosition.y);
|
||||
|
||||
SmoothMsdScrollTo(startPosition, ScrollTriggeredByScript::No);
|
||||
SmoothMsdScrollTo(std::move(*snapTarget), ScrollTriggeredByScript::No);
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
|
||||
Maybe<CSSSnapTarget> AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
|
||||
ScrollUnit aUnit, ScrollSnapFlags aSnapFlags, ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition) {
|
||||
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||
CSSToParentLayerScale zoom = Metrics().GetZoom();
|
||||
if (zoom == CSSToParentLayerScale(0)) {
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
CSSPoint destination = Metrics().CalculateScrollRange().ClampPoint(
|
||||
aStartPosition + (aDelta / zoom));
|
||||
|
||||
if (Maybe<CSSPoint> snapPoint =
|
||||
if (Maybe<CSSSnapTarget> snapTarget =
|
||||
FindSnapPointNear(destination, aUnit, aSnapFlags)) {
|
||||
aDelta = (*snapPoint - aStartPosition) * zoom;
|
||||
aStartPosition = *snapPoint;
|
||||
return true;
|
||||
aDelta = (snapTarget->mPosition - aStartPosition) * zoom;
|
||||
aStartPosition = snapTarget->mPosition;
|
||||
return snapTarget;
|
||||
}
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnappingOnWheelInput(
|
||||
Maybe<CSSSnapTarget>
|
||||
AsyncPanZoomController::MaybeAdjustDeltaForScrollSnappingOnWheelInput(
|
||||
const ScrollWheelInput& aEvent, ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition) {
|
||||
// Don't scroll snap for pixel scrolls. This matches the main thread
|
||||
// behaviour in EventStateManager::DoScrollText().
|
||||
if (aEvent.mDeltaType == ScrollWheelInput::SCROLLDELTA_PIXEL) {
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// Note that this MaybeAdjustDeltaForScrollSnappingOnWheelInput also gets
|
||||
@ -6217,18 +6239,19 @@ bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnappingOnWheelInput(
|
||||
ScrollSnapFlags::IntendedDirection, aDelta, aStartPosition);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::MaybeAdjustDestinationForScrollSnapping(
|
||||
Maybe<CSSSnapTarget>
|
||||
AsyncPanZoomController::MaybeAdjustDestinationForScrollSnapping(
|
||||
const KeyboardInput& aEvent, CSSPoint& aDestination,
|
||||
ScrollSnapFlags aSnapFlags) {
|
||||
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||
ScrollUnit unit = KeyboardScrollAction::GetScrollUnit(aEvent.mAction.mType);
|
||||
|
||||
if (Maybe<CSSPoint> snapPoint =
|
||||
if (Maybe<CSSSnapTarget> snapPoint =
|
||||
FindSnapPointNear(aDestination, unit, aSnapFlags)) {
|
||||
aDestination = *snapPoint;
|
||||
return true;
|
||||
aDestination = snapPoint->mPosition;
|
||||
return snapPoint;
|
||||
}
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SetZoomAnimationId(
|
||||
|
@ -1521,7 +1521,7 @@ class AsyncPanZoomController {
|
||||
|
||||
// Start a smooth-scrolling animation to the given destination, with MSD
|
||||
// physics that is suited for scroll-snapping.
|
||||
void SmoothMsdScrollTo(const CSSPoint& aDestination,
|
||||
void SmoothMsdScrollTo(CSSSnapTarget&& aDestination,
|
||||
ScrollTriggeredByScript aTriggeredByScript);
|
||||
|
||||
// Returns whether overscroll is allowed during an event.
|
||||
@ -1754,6 +1754,7 @@ class AsyncPanZoomController {
|
||||
// is in a panning state.
|
||||
TimeDuration mTouchStartRestingTimeBeforePan;
|
||||
Maybe<ParentLayerCoord> mMinimumVelocityDuringPan;
|
||||
ScrollSnapTargetIds mLastSnapTargetIds;
|
||||
// Extra offset to add to the async scroll position for testing
|
||||
CSSPoint mTestAsyncScrollOffset;
|
||||
// Extra zoom to include in the aync zoom for testing
|
||||
@ -1794,20 +1795,19 @@ class AsyncPanZoomController {
|
||||
// |aUnit| affects the snapping behaviour (see ScrollSnapUtils::
|
||||
// GetSnapPointForDestination).
|
||||
// Returns true iff. a target snap point was found.
|
||||
bool MaybeAdjustDeltaForScrollSnapping(ScrollUnit aUnit,
|
||||
ScrollSnapFlags aFlags,
|
||||
ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition);
|
||||
Maybe<CSSSnapTarget> MaybeAdjustDeltaForScrollSnapping(
|
||||
ScrollUnit aUnit, ScrollSnapFlags aSnapFlags, ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition);
|
||||
|
||||
// A wrapper function of MaybeAdjustDeltaForScrollSnapping for
|
||||
// ScrollWheelInput.
|
||||
bool MaybeAdjustDeltaForScrollSnappingOnWheelInput(
|
||||
Maybe<CSSSnapTarget> MaybeAdjustDeltaForScrollSnappingOnWheelInput(
|
||||
const ScrollWheelInput& aEvent, ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition);
|
||||
|
||||
bool MaybeAdjustDestinationForScrollSnapping(const KeyboardInput& aEvent,
|
||||
CSSPoint& aDestination,
|
||||
ScrollSnapFlags aSnapFlags);
|
||||
Maybe<CSSSnapTarget> MaybeAdjustDestinationForScrollSnapping(
|
||||
const KeyboardInput& aEvent, CSSPoint& aDestination,
|
||||
ScrollSnapFlags aSnapFlags);
|
||||
|
||||
// Snap to a snap position nearby the current scroll position, if appropriate.
|
||||
void ScrollSnap(ScrollSnapFlags aSnapFlags);
|
||||
@ -1824,9 +1824,9 @@ class AsyncPanZoomController {
|
||||
// |aUnit| affects the snapping behaviour (see ScrollSnapUtils::
|
||||
// GetSnapPointForDestination). It should generally be determined by the
|
||||
// type of event that's triggering the scroll.
|
||||
Maybe<CSSPoint> FindSnapPointNear(const CSSPoint& aDestination,
|
||||
ScrollUnit aUnit,
|
||||
ScrollSnapFlags aSnapFlags);
|
||||
Maybe<CSSSnapTarget> FindSnapPointNear(const CSSPoint& aDestination,
|
||||
ScrollUnit aUnit,
|
||||
ScrollSnapFlags aSnapFlags);
|
||||
|
||||
friend std::ostream& operator<<(
|
||||
std::ostream& aOut, const AsyncPanZoomController::PanZoomState& aState);
|
||||
|
@ -13,12 +13,14 @@ SmoothMsdScrollAnimation::SmoothMsdScrollAnimation(
|
||||
AsyncPanZoomController& aApzc, const CSSPoint& aInitialPosition,
|
||||
const CSSPoint& aInitialVelocity, const CSSPoint& aDestination,
|
||||
double aSpringConstant, double aDampingRatio,
|
||||
ScrollSnapTargetIds&& aSnapTargetIds,
|
||||
ScrollTriggeredByScript aTriggeredByScript)
|
||||
: mApzc(aApzc),
|
||||
mXAxisModel(aInitialPosition.x, aDestination.x, aInitialVelocity.x,
|
||||
aSpringConstant, aDampingRatio),
|
||||
mYAxisModel(aInitialPosition.y, aDestination.y, aInitialVelocity.y,
|
||||
aSpringConstant, aDampingRatio),
|
||||
mSnapTargetIds(std::move(aSnapTargetIds)),
|
||||
mTriggeredByScript(aTriggeredByScript) {}
|
||||
|
||||
bool SmoothMsdScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
|
||||
@ -116,10 +118,11 @@ bool SmoothMsdScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
|
||||
}
|
||||
|
||||
void SmoothMsdScrollAnimation::SetDestination(
|
||||
const CSSPoint& aNewDestination,
|
||||
const CSSPoint& aNewDestination, ScrollSnapTargetIds&& aSnapTargetIds,
|
||||
ScrollTriggeredByScript aTriggeredByScript) {
|
||||
mXAxisModel.SetDestination(aNewDestination.x);
|
||||
mYAxisModel.SetDestination(aNewDestination.y);
|
||||
mSnapTargetIds = std::move(aSnapTargetIds);
|
||||
mTriggeredByScript = aTriggeredByScript;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ class SmoothMsdScrollAnimation final : public AsyncPanZoomAnimation {
|
||||
const CSSPoint& aInitialVelocity,
|
||||
const CSSPoint& aDestination, double aSpringConstant,
|
||||
double aDampingRatio,
|
||||
ScrollSnapTargetIds&& aSnapTargetIds,
|
||||
ScrollTriggeredByScript aTriggeredByScript);
|
||||
|
||||
/**
|
||||
@ -35,6 +36,7 @@ class SmoothMsdScrollAnimation final : public AsyncPanZoomAnimation {
|
||||
const TimeDuration& aDelta) override;
|
||||
|
||||
void SetDestination(const CSSPoint& aNewDestination,
|
||||
ScrollSnapTargetIds&& aSnapTargetIds,
|
||||
ScrollTriggeredByScript aTriggeredByScript);
|
||||
CSSPoint GetDestination() const;
|
||||
SmoothMsdScrollAnimation* AsSmoothMsdScrollAnimation() override;
|
||||
@ -43,10 +45,13 @@ class SmoothMsdScrollAnimation final : public AsyncPanZoomAnimation {
|
||||
return mTriggeredByScript == ScrollTriggeredByScript::Yes;
|
||||
}
|
||||
|
||||
ScrollSnapTargetIds TakeSnapTargetIds() { return std::move(mSnapTargetIds); }
|
||||
|
||||
private:
|
||||
AsyncPanZoomController& mApzc;
|
||||
AxisPhysicsMSDModel mXAxisModel;
|
||||
AxisPhysicsMSDModel mYAxisModel;
|
||||
ScrollSnapTargetIds mSnapTargetIds;
|
||||
ScrollTriggeredByScript mTriggeredByScript;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Re-snapping to the last snapped element on APZ</title>
|
||||
<script src="apz_test_utils.js"></script>
|
||||
<script src="apz_test_native_event_utils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<style>
|
||||
div {
|
||||
position: absolute;
|
||||
}
|
||||
#scroller {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
overflow-y: scroll;
|
||||
scroll-snap-type: y mandatory;
|
||||
}
|
||||
.child {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
background-color: blue;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="scroller">
|
||||
<div class="child" style="top: 0px;"></div>
|
||||
<div class="child" style="top: 200px;"></div>
|
||||
<div style="width: 100%; height: 2000px;"></div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
async function test() {
|
||||
let transformEndPromise = promiseTransformEnd();
|
||||
await promiseMoveMouseAndScrollWheelOver(scroller, 100, 100);
|
||||
|
||||
await transformEndPromise;
|
||||
await promiseApzFlushedRepaints();
|
||||
|
||||
is(scroller.scrollTop, 200, "snap to 200px");
|
||||
|
||||
document.querySelectorAll(".child")[1].style.top = "400px";
|
||||
is(scroller.scrollTop, 400, "re-snap to 400px");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(test)
|
||||
.then(subtestDone, subtestFailed);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -19,6 +19,9 @@ const prefs = [
|
||||
|
||||
const subtests = [
|
||||
{"file": "helper_scroll_snap_no_valid_snap_position.html", "prefs": prefs},
|
||||
{"file": "helper_scroll_snap_resnap_after_async_scroll.html"},
|
||||
{"file": "helper_scroll_snap_resnap_after_async_scroll.html",
|
||||
"prefs": [["general.smoothScroll", false]]},
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
|
@ -129,7 +129,9 @@ static CSSPoint ScrollFrameTo(nsIScrollableFrame* aFrame,
|
||||
// request because we'll clobber that one, which is bad.
|
||||
bool scrollInProgress = APZCCallbackHelper::IsScrollInProgress(aFrame);
|
||||
if (!scrollInProgress) {
|
||||
aFrame->ScrollToCSSPixelsForApz(targetScrollPosition);
|
||||
ScrollSnapTargetIds snapTargetIds = aRequest.GetLastSnapTargetIds();
|
||||
aFrame->ScrollToCSSPixelsForApz(targetScrollPosition,
|
||||
std::move(snapTargetIds));
|
||||
geckoScrollPosition = CSSPoint::FromAppUnits(aFrame->GetScrollPosition());
|
||||
aSuccessOut = true;
|
||||
}
|
||||
@ -387,7 +389,9 @@ void APZCCallbackHelper::UpdateRootFrame(const RepaintRequest& aRequest) {
|
||||
nsLayoutUtils::FindScrollableFrameFor(aRequest.GetScrollId());
|
||||
CSSPoint currentScrollPosition =
|
||||
CSSPoint::FromAppUnits(sf->GetScrollPosition());
|
||||
sf->ScrollToCSSPixelsForApz(currentScrollPosition);
|
||||
ScrollSnapTargetIds snapTargetIds = aRequest.GetLastSnapTargetIds();
|
||||
sf->ScrollToCSSPixelsForApz(currentScrollPosition,
|
||||
std::move(snapTargetIds));
|
||||
}
|
||||
|
||||
// Do this as late as possible since scrolling can flush layout. It also
|
||||
|
@ -305,6 +305,21 @@ struct ParamTraits<mozilla::APZScrollAnimationType>
|
||||
mozilla::APZScrollAnimationType, mozilla::APZScrollAnimationType::No,
|
||||
mozilla::APZScrollAnimationType::TriggeredByUserInput> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ScrollSnapTargetIds> {
|
||||
typedef mozilla::ScrollSnapTargetIds paramType;
|
||||
|
||||
static void Write(MessageWriter* aWriter, const paramType& aParam) {
|
||||
WriteParam(aWriter, aParam.mIdsOnX);
|
||||
WriteParam(aWriter, aParam.mIdsOnY);
|
||||
}
|
||||
|
||||
static bool Read(MessageReader* aReader, paramType* aResult) {
|
||||
return ReadParam(aReader, &aResult->mIdsOnX) &&
|
||||
ReadParam(aReader, &aResult->mIdsOnY);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::RepaintRequest>
|
||||
: BitfieldHelper<mozilla::layers::RepaintRequest> {
|
||||
@ -327,6 +342,7 @@ struct ParamTraits<mozilla::layers::RepaintRequest>
|
||||
WriteParam(aWriter, aParam.mPaintRequestTime);
|
||||
WriteParam(aWriter, aParam.mScrollUpdateType);
|
||||
WriteParam(aWriter, aParam.mScrollAnimationType);
|
||||
WriteParam(aWriter, aParam.mLastSnapTargetIds);
|
||||
WriteParam(aWriter, aParam.mIsRootContent);
|
||||
WriteParam(aWriter, aParam.mIsScrollInfoLayer);
|
||||
}
|
||||
@ -349,6 +365,7 @@ struct ParamTraits<mozilla::layers::RepaintRequest>
|
||||
ReadParam(aReader, &aResult->mPaintRequestTime) &&
|
||||
ReadParam(aReader, &aResult->mScrollUpdateType) &&
|
||||
ReadParam(aReader, &aResult->mScrollAnimationType) &&
|
||||
ReadParam(aReader, &aResult->mLastSnapTargetIds) &&
|
||||
ReadBoolForBitfield(aReader, aResult, ¶mType::SetIsRootContent) &&
|
||||
ReadBoolForBitfield(aReader, aResult,
|
||||
¶mType::SetIsScrollInfoLayer));
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include "nsPoint.h"
|
||||
#include "nsTArray.h"
|
||||
#include "Units.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -20,6 +21,9 @@ enum class ScrollSnapTargetId : uintptr_t {
|
||||
struct ScrollSnapTargetIds {
|
||||
CopyableTArray<ScrollSnapTargetId> mIdsOnX;
|
||||
CopyableTArray<ScrollSnapTargetId> mIdsOnY;
|
||||
bool operator==(const ScrollSnapTargetIds& aOther) const {
|
||||
return mIdsOnX == aOther.mIdsOnX && mIdsOnY == aOther.mIdsOnY;
|
||||
}
|
||||
};
|
||||
|
||||
struct SnapTarget {
|
||||
@ -27,6 +31,11 @@ struct SnapTarget {
|
||||
ScrollSnapTargetIds mTargetIds;
|
||||
};
|
||||
|
||||
struct CSSSnapTarget {
|
||||
CSSPoint mPosition;
|
||||
ScrollSnapTargetIds mTargetIds;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ScrollSnapTargetId_h_
|
||||
|
@ -2530,14 +2530,15 @@ void ScrollFrameHelper::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition,
|
||||
}
|
||||
|
||||
void ScrollFrameHelper::ScrollToCSSPixelsForApz(
|
||||
const CSSPoint& aScrollPosition) {
|
||||
const CSSPoint& aScrollPosition, ScrollSnapTargetIds&& aLastSnapTargetIds) {
|
||||
nsPoint pt = CSSPoint::ToAppUnits(aScrollPosition);
|
||||
nscoord halfRange = nsPresContext::CSSPixelsToAppUnits(1000);
|
||||
nsRect range(pt.x - halfRange, pt.y - halfRange, 2 * halfRange - 1,
|
||||
2 * halfRange - 1);
|
||||
ScrollToWithOrigin(
|
||||
pt, &range,
|
||||
ScrollOperationParams{ScrollMode::Instant, ScrollOrigin::Apz});
|
||||
ScrollOperationParams{ScrollMode::Instant, ScrollOrigin::Apz,
|
||||
std::move(aLastSnapTargetIds)});
|
||||
// 'this' might be destroyed here
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,9 @@ class ScrollFrameHelper : public nsIReflowCallback {
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToCSSPixelsForApz(const mozilla::CSSPoint& aScrollPosition);
|
||||
void ScrollToCSSPixelsForApz(
|
||||
const mozilla::CSSPoint& aScrollPosition,
|
||||
mozilla::ScrollSnapTargetIds&& aLastSnapTargetIds);
|
||||
|
||||
CSSIntPoint GetScrollPositionCSSPixels();
|
||||
/**
|
||||
@ -1102,8 +1104,11 @@ class nsHTMLScrollFrame : public nsContainerFrame,
|
||||
ScrollMode aMode = ScrollMode::Instant) final {
|
||||
mHelper.ScrollToCSSPixels(aScrollPosition, aMode);
|
||||
}
|
||||
void ScrollToCSSPixelsForApz(const mozilla::CSSPoint& aScrollPosition) final {
|
||||
mHelper.ScrollToCSSPixelsForApz(aScrollPosition);
|
||||
void ScrollToCSSPixelsForApz(
|
||||
const mozilla::CSSPoint& aScrollPosition,
|
||||
mozilla::ScrollSnapTargetIds&& aLastSnapTargetIds) final {
|
||||
mHelper.ScrollToCSSPixelsForApz(aScrollPosition,
|
||||
std::move(aLastSnapTargetIds));
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
@ -1581,8 +1586,11 @@ class nsXULScrollFrame final : public nsBoxFrame,
|
||||
ScrollMode aMode = ScrollMode::Instant) final {
|
||||
mHelper.ScrollToCSSPixels(aScrollPosition, aMode);
|
||||
}
|
||||
void ScrollToCSSPixelsForApz(const mozilla::CSSPoint& aScrollPosition) final {
|
||||
mHelper.ScrollToCSSPixelsForApz(aScrollPosition);
|
||||
void ScrollToCSSPixelsForApz(
|
||||
const mozilla::CSSPoint& aScrollPosition,
|
||||
mozilla::ScrollSnapTargetIds&& aLastSnapTargetIds) final {
|
||||
mHelper.ScrollToCSSPixelsForApz(aScrollPosition,
|
||||
std::move(aLastSnapTargetIds));
|
||||
}
|
||||
CSSIntPoint GetScrollPositionCSSPixels() final {
|
||||
return mHelper.GetScrollPositionCSSPixels();
|
||||
|
@ -294,7 +294,8 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
|
||||
* number of layer pixels (so the operation is fast and looks clean).
|
||||
*/
|
||||
virtual void ScrollToCSSPixelsForApz(
|
||||
const mozilla::CSSPoint& aScrollPosition) = 0;
|
||||
const mozilla::CSSPoint& aScrollPosition,
|
||||
mozilla::ScrollSnapTargetIds&& aLastSnapTargetIds) = 0;
|
||||
|
||||
/**
|
||||
* Returns the scroll position in integer CSS pixels, rounded to the nearest
|
||||
|
Loading…
Reference in New Issue
Block a user