mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1453425 - Add relative scroll offset updates using nsGkAtoms::relative. r=botond
This commit adds a scroll origin, nsGkAtoms::relative, which can be used to mark main thread scrolling that can be combined with a concurrent APZ scroll. The behavior of this is controlled by a pref, apz.relative-update. This pref is initially activated and is intended as an aid to narrowing down causes of regressions for users in bug reports. Relative scroll updates work by tracking the last sent or accepted APZ scroll offset. This is sent along with every FrameMetrics. Additionally, a flag is added to FrameMetrics, mIsRelative, indicating whether the scroll offset can be combined with a potential APZ scroll. When this flag is set, AsyncPanZoomController will apply the delta between the sent base scroll offset, and sent new scroll offset. This flag is controlled by the last scroll origin on nsGfxScrollFrame. The new origin, `relative`, is marked as being able to clobber APZ updates, but can only be set if all scrolls since the last repaint request or layers transaction have been relative. Differential Revision: https://phabricator.services.mozilla.com/D8234 --HG-- extra : rebase_source : 51351a84c9cda228a0975e22eda3fd3bd8d261c4 extra : histedit_source : 4b564c19b16fe2bd26adc671b62b7cb6106e8163
This commit is contained in:
parent
d4c042f28a
commit
1601a8bb80
@ -8,7 +8,6 @@
|
||||
#define __GFXMESSAGEUTILS_H__
|
||||
|
||||
#include "FilterSupport.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "RegionBuilder.h"
|
||||
#include "base/process_util.h"
|
||||
|
@ -38,6 +38,8 @@ namespace layers {
|
||||
struct ScrollUpdateInfo {
|
||||
uint32_t mScrollGeneration;
|
||||
CSSPoint mScrollOffset;
|
||||
CSSPoint mBaseScrollOffset;
|
||||
bool mIsRelative;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -78,6 +80,7 @@ public:
|
||||
, mCumulativeResolution()
|
||||
, mDevPixelsPerCSSPixel(1)
|
||||
, mScrollOffset(0, 0)
|
||||
, mBaseScrollOffset(0, 0)
|
||||
, mZoom()
|
||||
, mScrollGeneration(0)
|
||||
, mSmoothScrollOffset(0, 0)
|
||||
@ -89,6 +92,7 @@ public:
|
||||
, mPaintRequestTime()
|
||||
, mScrollUpdateType(eNone)
|
||||
, mIsRootContent(false)
|
||||
, mIsRelative(false)
|
||||
, mDoSmoothScroll(false)
|
||||
, mUseDisplayPortMargins(false)
|
||||
, mIsScrollInfoLayer(false)
|
||||
@ -109,6 +113,7 @@ public:
|
||||
mCumulativeResolution == aOther.mCumulativeResolution &&
|
||||
mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel &&
|
||||
mScrollOffset == aOther.mScrollOffset &&
|
||||
mBaseScrollOffset == aOther.mBaseScrollOffset &&
|
||||
// don't compare mZoom
|
||||
mScrollGeneration == aOther.mScrollGeneration &&
|
||||
mSmoothScrollOffset == aOther.mSmoothScrollOffset &&
|
||||
@ -120,6 +125,7 @@ public:
|
||||
mPaintRequestTime == aOther.mPaintRequestTime &&
|
||||
mScrollUpdateType == aOther.mScrollUpdateType &&
|
||||
mIsRootContent == aOther.mIsRootContent &&
|
||||
mIsRelative == aOther.mIsRelative &&
|
||||
mDoSmoothScroll == aOther.mDoSmoothScroll &&
|
||||
mUseDisplayPortMargins == aOther.mUseDisplayPortMargins &&
|
||||
mIsScrollInfoLayer == aOther.mIsScrollInfoLayer;
|
||||
@ -247,24 +253,53 @@ public:
|
||||
mZoom.yScale *= aScale.height;
|
||||
}
|
||||
|
||||
void CopyScrollInfoFrom(const FrameMetrics& aOther)
|
||||
/*
|
||||
* Compares an APZ frame metrics with an incoming content frame metrics
|
||||
* to see if APZ has a scroll offset that has not been incorporated into
|
||||
* the content frame metrics.
|
||||
*/
|
||||
bool HasPendingScroll(const FrameMetrics& aContentFrameMetrics) const
|
||||
{
|
||||
return mScrollOffset != aContentFrameMetrics.mBaseScrollOffset;
|
||||
}
|
||||
|
||||
void ApplyScrollUpdateFrom(const FrameMetrics& aOther)
|
||||
{
|
||||
mScrollOffset = aOther.mScrollOffset;
|
||||
mScrollGeneration = aOther.mScrollGeneration;
|
||||
}
|
||||
|
||||
void CopySmoothScrollInfoFrom(const FrameMetrics& aOther)
|
||||
void ApplySmoothScrollUpdateFrom(const FrameMetrics& aOther)
|
||||
{
|
||||
mSmoothScrollOffset = aOther.mSmoothScrollOffset;
|
||||
mScrollGeneration = aOther.mScrollGeneration;
|
||||
mDoSmoothScroll = aOther.mDoSmoothScroll;
|
||||
}
|
||||
|
||||
void ApplyRelativeScrollUpdateFrom(const FrameMetrics& aOther)
|
||||
{
|
||||
MOZ_ASSERT(aOther.IsRelative());
|
||||
CSSPoint delta = (aOther.mScrollOffset - aOther.mBaseScrollOffset);
|
||||
ClampAndSetScrollOffset(mScrollOffset + delta);
|
||||
mScrollGeneration = aOther.mScrollGeneration;
|
||||
}
|
||||
|
||||
void ApplyRelativeSmoothScrollUpdateFrom(const FrameMetrics& aOther)
|
||||
{
|
||||
MOZ_ASSERT(aOther.IsRelative());
|
||||
CSSPoint delta = (aOther.mSmoothScrollOffset - aOther.mBaseScrollOffset);
|
||||
ClampAndSetSmoothScrollOffset(mScrollOffset + delta);
|
||||
mScrollGeneration = aOther.mScrollGeneration;
|
||||
mDoSmoothScroll = aOther.mDoSmoothScroll;
|
||||
}
|
||||
|
||||
void UpdatePendingScrollInfo(const ScrollUpdateInfo& aInfo)
|
||||
{
|
||||
mScrollOffset = aInfo.mScrollOffset;
|
||||
mBaseScrollOffset = aInfo.mBaseScrollOffset;
|
||||
mScrollGeneration = aInfo.mScrollGeneration;
|
||||
mScrollUpdateType = ePending;
|
||||
mIsRelative = aInfo.mIsRelative;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -343,6 +378,11 @@ public:
|
||||
mScrollOffset = aScrollOffset;
|
||||
}
|
||||
|
||||
void SetBaseScrollOffset(const CSSPoint& aScrollOffset)
|
||||
{
|
||||
mBaseScrollOffset = aScrollOffset;
|
||||
}
|
||||
|
||||
// Set scroll offset, first clamping to the scroll range.
|
||||
void ClampAndSetScrollOffset(const CSSPoint& aScrollOffset)
|
||||
{
|
||||
@ -354,11 +394,21 @@ public:
|
||||
return mScrollOffset;
|
||||
}
|
||||
|
||||
const CSSPoint& GetBaseScrollOffset() const
|
||||
{
|
||||
return mBaseScrollOffset;
|
||||
}
|
||||
|
||||
void SetSmoothScrollOffset(const CSSPoint& aSmoothScrollDestination)
|
||||
{
|
||||
mSmoothScrollOffset = aSmoothScrollDestination;
|
||||
}
|
||||
|
||||
void ClampAndSetSmoothScrollOffset(const CSSPoint& aSmoothScrollOffset)
|
||||
{
|
||||
SetSmoothScrollOffset(CalculateScrollRange().ClampPoint(aSmoothScrollOffset));
|
||||
}
|
||||
|
||||
const CSSPoint& GetSmoothScrollOffset() const
|
||||
{
|
||||
return mSmoothScrollOffset;
|
||||
@ -374,16 +424,14 @@ public:
|
||||
return mZoom;
|
||||
}
|
||||
|
||||
void SetScrollOffsetUpdated(uint32_t aScrollGeneration)
|
||||
void SetScrollGeneration(uint32_t aScrollGeneration)
|
||||
{
|
||||
mScrollUpdateType = eMainThread;
|
||||
mScrollGeneration = aScrollGeneration;
|
||||
}
|
||||
|
||||
void SetScrollOffsetRestored(uint32_t aScrollGeneration)
|
||||
void SetScrollOffsetUpdateType(ScrollOffsetUpdateType aScrollUpdateType)
|
||||
{
|
||||
mScrollUpdateType = eRestore;
|
||||
mScrollGeneration = aScrollGeneration;
|
||||
mScrollUpdateType = aScrollUpdateType;
|
||||
}
|
||||
|
||||
void SetSmoothScrollOffsetUpdated(int32_t aScrollGeneration)
|
||||
@ -402,6 +450,16 @@ public:
|
||||
return mScrollUpdateType != eNone;
|
||||
}
|
||||
|
||||
void SetIsRelative(bool aIsRelative)
|
||||
{
|
||||
mIsRelative = aIsRelative;
|
||||
}
|
||||
|
||||
bool IsRelative() const
|
||||
{
|
||||
return mIsRelative;
|
||||
}
|
||||
|
||||
bool GetDoSmoothScroll() const
|
||||
{
|
||||
return mDoSmoothScroll;
|
||||
@ -642,6 +700,10 @@ private:
|
||||
// not any parents, regardless of parent transforms.
|
||||
CSSPoint mScrollOffset;
|
||||
|
||||
// The base scroll offset to use for calculating a relative update to a
|
||||
// scroll offset.
|
||||
CSSPoint mBaseScrollOffset;
|
||||
|
||||
// The "user zoom". Content is painted by gecko at mResolution * mDevPixelsPerCSSPixel,
|
||||
// but will be drawn to the screen at mZoom. In the steady state, the
|
||||
// two will be the same, but during an async zoom action the two may
|
||||
@ -689,6 +751,10 @@ private:
|
||||
// Whether or not this is the root scroll frame for the root content document.
|
||||
bool mIsRootContent:1;
|
||||
|
||||
// When mIsRelative, the scroll offset was updated using a relative API,
|
||||
// such as `ScrollBy`, and can combined with an async scroll.
|
||||
bool mIsRelative:1;
|
||||
|
||||
// When mDoSmoothScroll, the scroll offset should be animated to
|
||||
// smoothly transition to mScrollOffset rather than be updated instantly.
|
||||
bool mDoSmoothScroll:1;
|
||||
|
@ -491,6 +491,11 @@ typedef PlatformSpecificStateBase PlatformSpecificState; // no extra state, jus
|
||||
* A negative number prevents repaint requests during a scale.\n
|
||||
* Units: ms
|
||||
*
|
||||
* \li\b apz.relative-update.enabled
|
||||
* Whether to enable relative scroll offset updates or not. Relative scroll
|
||||
* offset updates allow APZ and the main thread to concurrently update
|
||||
* the scroll offset and merge the result.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -3378,11 +3383,6 @@ void AsyncPanZoomController::ScrollByAndClamp(const CSSPoint& aOffset) {
|
||||
ClampAndSetScrollOffset(Metrics().GetScrollOffset() + aOffset);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::CopyScrollInfoFrom(const FrameMetrics& aFrameMetrics) {
|
||||
Metrics().CopyScrollInfoFrom(aFrameMetrics);
|
||||
Metrics().RecalculateViewportOffset();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScaleWithFocus(float aScale,
|
||||
const CSSPoint& aFocus) {
|
||||
Metrics().ZoomBy(aScale);
|
||||
@ -4256,6 +4256,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||
// ignore it
|
||||
|
||||
bool needContentRepaint = false;
|
||||
bool userAction = false;
|
||||
bool viewportUpdated = false;
|
||||
|
||||
// We usually don't entertain viewport updates on the same transaction as
|
||||
@ -4372,10 +4373,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||
mScrollMetadata.SetOverscrollBehavior(aScrollMetadata.GetOverscrollBehavior());
|
||||
|
||||
if (scrollOffsetUpdated) {
|
||||
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
|
||||
ToString(Metrics().GetScrollOffset()).c_str(),
|
||||
ToString(aLayerMetrics.GetScrollOffset()).c_str());
|
||||
|
||||
// Send an acknowledgement with the new scroll generation so that any
|
||||
// repaint requests later in this function go through.
|
||||
// Because of the scroll generation update, any inflight paint requests are
|
||||
@ -4383,7 +4380,30 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||
// becomes incorrect for the purposes of calculating the LD transform. To
|
||||
// correct this we need to update mExpectedGeckoMetrics to be the
|
||||
// last thing we know was painted by Gecko.
|
||||
CopyScrollInfoFrom(aLayerMetrics);
|
||||
if (gfxPrefs::APZRelativeUpdate() && aLayerMetrics.IsRelative()) {
|
||||
APZC_LOG("%p relative updating scroll offset from %s by %s\n", this,
|
||||
ToString(Metrics().GetScrollOffset()).c_str(),
|
||||
ToString(aLayerMetrics.GetScrollOffset() - aLayerMetrics.GetBaseScrollOffset()).c_str());
|
||||
|
||||
// It's possible that the main thread has ignored an APZ scroll offset
|
||||
// update for the pending relative scroll that we have just received.
|
||||
// When this happens, we need to send a new scroll offset update with
|
||||
// the combined scroll offset or else the main thread may have an
|
||||
// incorrect scroll offset for a period of time.
|
||||
if (Metrics().HasPendingScroll(aLayerMetrics)) {
|
||||
needContentRepaint = true;
|
||||
userAction = true;
|
||||
}
|
||||
|
||||
Metrics().ApplyRelativeScrollUpdateFrom(aLayerMetrics);
|
||||
} else {
|
||||
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
|
||||
ToString(Metrics().GetScrollOffset()).c_str(),
|
||||
ToString(aLayerMetrics.GetScrollOffset()).c_str());
|
||||
Metrics().ApplyScrollUpdateFrom(aLayerMetrics);
|
||||
}
|
||||
Metrics().RecalculateViewportOffset();
|
||||
|
||||
mCompositedLayoutViewport = Metrics().GetViewport();
|
||||
mCompositedScrollOffset = Metrics().GetScrollOffset();
|
||||
mExpectedGeckoMetrics = aLayerMetrics;
|
||||
@ -4424,7 +4444,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||
|
||||
// See comment on the similar code in the |if (scrollOffsetUpdated)| block
|
||||
// above.
|
||||
Metrics().CopySmoothScrollInfoFrom(aLayerMetrics);
|
||||
if (gfxPrefs::APZRelativeUpdate() && aLayerMetrics.IsRelative()) {
|
||||
Metrics().ApplyRelativeSmoothScrollUpdateFrom(aLayerMetrics);
|
||||
} else {
|
||||
Metrics().ApplySmoothScrollUpdateFrom(aLayerMetrics);
|
||||
}
|
||||
needContentRepaint = true;
|
||||
mExpectedGeckoMetrics = aLayerMetrics;
|
||||
|
||||
@ -4443,7 +4467,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||
|
||||
if (needContentRepaint) {
|
||||
// This repaint request is not driven by a user action on the APZ side
|
||||
RequestContentRepaint(RepaintUpdateType::eNone);
|
||||
RepaintUpdateType updateType = RepaintUpdateType::eNone;
|
||||
if (userAction) {
|
||||
updateType = RepaintUpdateType::eUserAction;
|
||||
}
|
||||
RequestContentRepaint(updateType);
|
||||
}
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
|
@ -709,11 +709,6 @@ protected:
|
||||
*/
|
||||
void ScrollByAndClamp(const CSSPoint& aOffset);
|
||||
|
||||
/**
|
||||
* Copy the scroll offset and scroll generation from |aFrameMetrics|.
|
||||
*/
|
||||
void CopyScrollInfoFrom(const FrameMetrics& aFrameMetrics);
|
||||
|
||||
/**
|
||||
* Scales the viewport by an amount (note that it multiplies this scale in to
|
||||
* the current scale, it doesn't set it to |aScale|). Also considers a focus
|
||||
|
@ -174,6 +174,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
WriteParam(aMsg, aParam.mCumulativeResolution);
|
||||
WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel);
|
||||
WriteParam(aMsg, aParam.mScrollOffset);
|
||||
WriteParam(aMsg, aParam.mBaseScrollOffset);
|
||||
WriteParam(aMsg, aParam.mZoom);
|
||||
WriteParam(aMsg, aParam.mScrollGeneration);
|
||||
WriteParam(aMsg, aParam.mSmoothScrollOffset);
|
||||
@ -185,6 +186,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
WriteParam(aMsg, aParam.mPaintRequestTime);
|
||||
WriteParam(aMsg, aParam.mScrollUpdateType);
|
||||
WriteParam(aMsg, aParam.mIsRootContent);
|
||||
WriteParam(aMsg, aParam.mIsRelative);
|
||||
WriteParam(aMsg, aParam.mDoSmoothScroll);
|
||||
WriteParam(aMsg, aParam.mUseDisplayPortMargins);
|
||||
WriteParam(aMsg, aParam.mIsScrollInfoLayer);
|
||||
@ -201,6 +203,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
ReadParam(aMsg, aIter, &aResult->mCumulativeResolution) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mBaseScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mZoom) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollGeneration) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) &&
|
||||
@ -212,6 +215,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
ReadParam(aMsg, aIter, &aResult->mPaintRequestTime) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollUpdateType) &&
|
||||
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetIsRootContent) &&
|
||||
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetIsRelative) &&
|
||||
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetDoSmoothScroll) &&
|
||||
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetUseDisplayPortMargins) &&
|
||||
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetIsScrollInfoLayer));
|
||||
|
@ -68,6 +68,7 @@ WebRenderLayerScrollData::Initialize(WebRenderScrollData& aOwner,
|
||||
Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
|
||||
aOwner.GetManager(), aItem->ReferenceFrame(),
|
||||
Nothing(), nullptr);
|
||||
asr->mScrollableFrame->NotifyApzTransaction();
|
||||
MOZ_ASSERT(metadata);
|
||||
MOZ_ASSERT(metadata->GetMetrics().GetScrollId() == scrollId);
|
||||
mScrollIds.AppendElement(aOwner.AddMetadata(metadata.ref()));
|
||||
|
@ -365,6 +365,7 @@ private:
|
||||
DECL_GFX_PREF(Live, "apz.y_stationary_size_multiplier", APZYStationarySizeMultiplier, float, 3.5f);
|
||||
DECL_GFX_PREF(Live, "apz.zoom_animation_duration_ms", APZZoomAnimationDuration, int32_t, 250);
|
||||
DECL_GFX_PREF(Live, "apz.scale_repaint_delay_ms", APZScaleRepaintDelay, int32_t, 500);
|
||||
DECL_GFX_PREF(Live, "apz.relative-update.enabled", APZRelativeUpdate, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "browser.ui.scroll-toolbar-threshold", ToolbarScrollThreshold, int32_t, 10);
|
||||
DECL_GFX_PREF(Live, "browser.ui.zoom.force-user-scalable", ForceUserScalable, bool, false);
|
||||
|
@ -9229,7 +9229,9 @@ nsLayoutUtils::ComputeScrollMetadata(nsIFrame* aForFrame,
|
||||
|
||||
if (scrollableFrame) {
|
||||
CSSPoint scrollPosition = CSSPoint::FromAppUnits(scrollableFrame->GetScrollPosition());
|
||||
CSSPoint apzScrollPosition = CSSPoint::FromAppUnits(scrollableFrame->GetApzScrollPosition());
|
||||
metrics.SetScrollOffset(scrollPosition);
|
||||
metrics.SetBaseScrollOffset(apzScrollPosition);
|
||||
|
||||
CSSRect viewport = metrics.GetViewport();
|
||||
viewport.MoveTo(scrollPosition);
|
||||
@ -9243,12 +9245,17 @@ nsLayoutUtils::ComputeScrollMetadata(nsIFrame* aForFrame,
|
||||
// its scroll offset. We want to distinguish the case where the scroll offset
|
||||
// was "restored" because in that case the restored scroll position should
|
||||
// not overwrite a user-driven scroll.
|
||||
if (scrollableFrame->LastScrollOrigin() == nsGkAtoms::restore) {
|
||||
metrics.SetScrollOffsetRestored(scrollableFrame->CurrentScrollGeneration());
|
||||
} else if (CanScrollOriginClobberApz(scrollableFrame->LastScrollOrigin())) {
|
||||
metrics.SetScrollOffsetUpdated(scrollableFrame->CurrentScrollGeneration());
|
||||
nsAtom* lastOrigin = scrollableFrame->LastScrollOrigin();
|
||||
if (lastOrigin == nsGkAtoms::restore) {
|
||||
metrics.SetScrollGeneration(scrollableFrame->CurrentScrollGeneration());
|
||||
metrics.SetScrollOffsetUpdateType(FrameMetrics::eRestore);
|
||||
} else if (CanScrollOriginClobberApz(lastOrigin)) {
|
||||
if (lastOrigin == nsGkAtoms::relative) {
|
||||
metrics.SetIsRelative(true);
|
||||
}
|
||||
metrics.SetScrollGeneration(scrollableFrame->CurrentScrollGeneration());
|
||||
metrics.SetScrollOffsetUpdateType(FrameMetrics::eMainThread);
|
||||
}
|
||||
scrollableFrame->AllowScrollOriginDowngrade();
|
||||
|
||||
nsAtom* lastSmoothScrollOrigin = scrollableFrame->LastSmoothScrollOrigin();
|
||||
if (lastSmoothScrollOrigin) {
|
||||
|
@ -2040,7 +2040,7 @@ ScrollFrameHelper::AsyncScroll::InitSmoothScroll(TimeStamp aTime,
|
||||
const nsRect& aRange,
|
||||
const nsSize& aCurrentVelocity)
|
||||
{
|
||||
if (!aOrigin || aOrigin == nsGkAtoms::restore) {
|
||||
if (!aOrigin || aOrigin == nsGkAtoms::restore || aOrigin == nsGkAtoms::relative) {
|
||||
// We don't have special prefs for "restore", just treat it as "other".
|
||||
// "restore" scrolls are (for now) always instant anyway so unless something
|
||||
// changes we should never have aOrigin == nsGkAtoms::restore here.
|
||||
@ -2122,6 +2122,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
|
||||
, mDestination(0, 0)
|
||||
, mRestorePos(-1, -1)
|
||||
, mLastPos(-1, -1)
|
||||
, mApzScrollPos(0, 0)
|
||||
, mScrollPosForLayerPixelAlignment(-1, -1)
|
||||
, mLastUpdateFramesPos(-1, -1)
|
||||
, mHadDisplayPortAtLastFrameUpdate(false)
|
||||
@ -2923,6 +2924,17 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsAtom* aOrig
|
||||
// Update frame position for scrolling
|
||||
mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt);
|
||||
|
||||
// If this scroll is |relative|, but we've already had a user scroll that
|
||||
// was not relative, promote this origin to |other|. This ensures that we
|
||||
// may only transmit a relative update to APZ if all scrolls since the last
|
||||
// transaction or repaint request have been relative.
|
||||
if (aOrigin == nsGkAtoms::relative &&
|
||||
(mLastScrollOrigin &&
|
||||
mLastScrollOrigin != nsGkAtoms::relative &&
|
||||
mLastScrollOrigin != nsGkAtoms::apz)) {
|
||||
aOrigin = nsGkAtoms::other;
|
||||
}
|
||||
|
||||
// If |mLastScrollOrigin| is already set to something that can clobber APZ's
|
||||
// scroll offset, then we don't want to change it to something that can't.
|
||||
// If we allowed this, then we could end up in a state where APZ ignores
|
||||
@ -2933,12 +2945,16 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsAtom* aOrig
|
||||
!nsLayoutUtils::CanScrollOriginClobberApz(aOrigin);
|
||||
bool allowScrollOriginChange = mAllowScrollOriginDowngrade ||
|
||||
!isScrollOriginDowngrade;
|
||||
|
||||
if (allowScrollOriginChange) {
|
||||
mLastScrollOrigin = aOrigin;
|
||||
mAllowScrollOriginDowngrade = false;
|
||||
}
|
||||
mLastSmoothScrollOrigin = nullptr;
|
||||
mScrollGeneration = ++sScrollGenerationCounter;
|
||||
if (mLastScrollOrigin == nsGkAtoms::apz) {
|
||||
mApzScrollPos = GetScrollPosition();
|
||||
}
|
||||
|
||||
// If the new scroll offset is going to clobber APZ's scroll offset, for
|
||||
// the RCD-RSF this will have the effect of resetting the visual viewport
|
||||
@ -3006,7 +3022,12 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsAtom* aOrig
|
||||
// instead of a full transaction. This empty transaction might still get
|
||||
// squashed into a full transaction if something happens to trigger one.
|
||||
success = manager->SetPendingScrollUpdateForNextTransaction(id,
|
||||
{ mScrollGeneration, CSSPoint::FromAppUnits(GetScrollPosition()) });
|
||||
{
|
||||
mScrollGeneration,
|
||||
CSSPoint::FromAppUnits(GetScrollPosition()),
|
||||
CSSPoint::FromAppUnits(GetApzScrollPosition()),
|
||||
mLastScrollOrigin == nsGkAtoms::relative
|
||||
});
|
||||
if (success) {
|
||||
schedulePaint = false;
|
||||
mOuter->SchedulePaint(nsIFrame::PAINT_COMPOSITE_ONLY);
|
||||
|
@ -213,6 +213,9 @@ public:
|
||||
pt.y = mScrollPort.y - mScrolledFrame->GetPosition().y;
|
||||
return pt;
|
||||
}
|
||||
nsPoint GetApzScrollPosition() const {
|
||||
return mApzScrollPos;
|
||||
}
|
||||
nsRect GetScrollRange() const;
|
||||
// Get the scroll range assuming the viewport has size (aWidth, aHeight).
|
||||
nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
|
||||
@ -443,6 +446,10 @@ public:
|
||||
nsRect* aDirtyRect,
|
||||
bool aSetBase,
|
||||
bool* aDirtyRectHasBeenOverriden = nullptr);
|
||||
void NotifyApzTransaction() {
|
||||
mAllowScrollOriginDowngrade = true;
|
||||
mApzScrollPos = GetScrollPosition();
|
||||
}
|
||||
void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort);
|
||||
bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(nsRect* aDisplayPort);
|
||||
|
||||
@ -456,7 +463,6 @@ public:
|
||||
void HandleScrollbarStyleSwitching();
|
||||
|
||||
nsAtom* LastScrollOrigin() const { return mLastScrollOrigin; }
|
||||
void AllowScrollOriginDowngrade() { mAllowScrollOriginDowngrade = true; }
|
||||
nsAtom* LastSmoothScrollOrigin() const { return mLastSmoothScrollOrigin; }
|
||||
uint32_t CurrentScrollGeneration() const { return mScrollGeneration; }
|
||||
nsPoint LastScrollDestination() const { return mDestination; }
|
||||
@ -550,6 +556,11 @@ public:
|
||||
// other than trying to restore mRestorePos.
|
||||
nsPoint mLastPos;
|
||||
|
||||
// The latest scroll position we've sent or received from APZ. This
|
||||
// represents the main thread's best knowledge of the APZ scroll position,
|
||||
// and is used to calculate relative scroll offset updates.
|
||||
nsPoint mApzScrollPos;
|
||||
|
||||
nsExpirationState mActivityExpirationState;
|
||||
|
||||
nsCOMPtr<nsITimer> mScrollActivityTimer;
|
||||
@ -857,6 +868,9 @@ public:
|
||||
virtual nsPoint GetLogicalScrollPosition() const override {
|
||||
return mHelper.GetLogicalScrollPosition();
|
||||
}
|
||||
virtual nsPoint GetApzScrollPosition() const override {
|
||||
return mHelper.GetApzScrollPosition();
|
||||
}
|
||||
virtual nsRect GetScrollRange() const override {
|
||||
return mHelper.GetScrollRange();
|
||||
}
|
||||
@ -973,9 +987,6 @@ public:
|
||||
virtual nsAtom* LastScrollOrigin() override {
|
||||
return mHelper.LastScrollOrigin();
|
||||
}
|
||||
virtual void AllowScrollOriginDowngrade() override {
|
||||
mHelper.AllowScrollOriginDowngrade();
|
||||
}
|
||||
virtual nsAtom* LastSmoothScrollOrigin() override {
|
||||
return mHelper.LastSmoothScrollOrigin();
|
||||
}
|
||||
@ -1020,6 +1031,9 @@ public:
|
||||
bool aSetBase) override {
|
||||
return mHelper.DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect, aSetBase);
|
||||
}
|
||||
virtual void NotifyApzTransaction() override {
|
||||
mHelper.NotifyApzTransaction();
|
||||
}
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) override {
|
||||
mHelper.NotifyApproximateFrameVisibilityUpdate(aIgnoreDisplayPort);
|
||||
}
|
||||
@ -1319,6 +1333,9 @@ public:
|
||||
virtual nsPoint GetLogicalScrollPosition() const override {
|
||||
return mHelper.GetLogicalScrollPosition();
|
||||
}
|
||||
virtual nsPoint GetApzScrollPosition() const override {
|
||||
return mHelper.GetApzScrollPosition();
|
||||
}
|
||||
virtual nsRect GetScrollRange() const override {
|
||||
return mHelper.GetScrollRange();
|
||||
}
|
||||
@ -1431,9 +1448,6 @@ public:
|
||||
virtual nsAtom* LastScrollOrigin() override {
|
||||
return mHelper.LastScrollOrigin();
|
||||
}
|
||||
virtual void AllowScrollOriginDowngrade() override {
|
||||
mHelper.AllowScrollOriginDowngrade();
|
||||
}
|
||||
virtual nsAtom* LastSmoothScrollOrigin() override {
|
||||
return mHelper.LastSmoothScrollOrigin();
|
||||
}
|
||||
@ -1553,6 +1567,9 @@ public:
|
||||
bool aSetBase) override {
|
||||
return mHelper.DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect, aSetBase);
|
||||
}
|
||||
virtual void NotifyApzTransaction() override {
|
||||
mHelper.NotifyApzTransaction();
|
||||
}
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) override {
|
||||
mHelper.NotifyApproximateFrameVisibilityUpdate(aIgnoreDisplayPort);
|
||||
}
|
||||
|
@ -138,6 +138,12 @@ public:
|
||||
* As GetScrollPosition(), but uses the top-right as origin for RTL frames.
|
||||
*/
|
||||
virtual nsPoint GetLogicalScrollPosition() const = 0;
|
||||
/**
|
||||
* Get the latest scroll position that the main thread has sent or received
|
||||
* from APZ.
|
||||
*/
|
||||
virtual nsPoint GetApzScrollPosition() const = 0;
|
||||
|
||||
/**
|
||||
* Get the area that must contain the scroll position. Typically
|
||||
* (but not always, e.g. for RTL content) x and y will be 0, and
|
||||
@ -380,15 +386,6 @@ public:
|
||||
* latest instant scroll.
|
||||
*/
|
||||
virtual nsAtom* LastScrollOrigin() = 0;
|
||||
/**
|
||||
* Sets a flag on the scrollframe that indicates the current scroll origin
|
||||
* has been sent over in a layers transaction, and subsequent changes to
|
||||
* the scroll position by "weaker" origins are permitted to overwrite the
|
||||
* the scroll origin. Scroll origins that nsLayoutUtils::CanScrollOriginClobberApz
|
||||
* returns false for are considered "weaker" than scroll origins for which
|
||||
* that function returns true.
|
||||
*/
|
||||
virtual void AllowScrollOriginDowngrade() = 0;
|
||||
/**
|
||||
* Returns the origin that triggered the last smooth scroll.
|
||||
* Will equal nsGkAtoms::apz when the compositor's replica frame
|
||||
@ -494,6 +491,22 @@ public:
|
||||
nsRect* aDirtyRect,
|
||||
bool aSetBase) = 0;
|
||||
|
||||
/**
|
||||
* Notify the scrollframe that the current scroll offset and origin have been
|
||||
* sent over in a layers transaction.
|
||||
*
|
||||
* This sets a flag on the scrollframe that indicates subsequent changes
|
||||
* to the scroll position by "weaker" origins are permitted to overwrite the
|
||||
* the scroll origin. Scroll origins that nsLayoutUtils::CanScrollOriginClobberApz
|
||||
* returns false for are considered "weaker" than scroll origins for which
|
||||
* that function returns true.
|
||||
*
|
||||
* This function must be called for a scrollframe after all calls to
|
||||
* ComputeScrollMetadata in a layers transaction have been completed.
|
||||
*
|
||||
*/
|
||||
virtual void NotifyApzTransaction() = 0;
|
||||
|
||||
/**
|
||||
* Notification that this scroll frame is getting its frame visibility updated.
|
||||
* aIgnoreDisplayPort indicates that the display port was ignored (because
|
||||
|
@ -6161,6 +6161,7 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry)
|
||||
} else {
|
||||
metadata = scrollFrame->ComputeScrollMetadata(
|
||||
aEntry->mLayer->Manager(), mContainerReferenceFrame, Some(mParameters), clip);
|
||||
scrollFrame->NotifyApzTransaction();
|
||||
mCachedScrollMetadata.mASR = asr;
|
||||
mCachedScrollMetadata.mClip = clip;
|
||||
mCachedScrollMetadata.mMetadata = metadata;
|
||||
|
@ -7229,7 +7229,7 @@ nsDisplaySubDocument::ComputeScrollMetadata(
|
||||
nsRect viewport = mFrame->GetRect() - mFrame->GetPosition() +
|
||||
mFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
||||
|
||||
return MakeUnique<ScrollMetadata>(
|
||||
UniquePtr<ScrollMetadata> metadata = MakeUnique<ScrollMetadata>(
|
||||
nsLayoutUtils::ComputeScrollMetadata(mFrame,
|
||||
rootScrollFrame,
|
||||
rootScrollFrame->GetContent(),
|
||||
@ -7240,6 +7240,12 @@ nsDisplaySubDocument::ComputeScrollMetadata(
|
||||
Nothing(),
|
||||
isRootContentDocument,
|
||||
Some(params)));
|
||||
nsIScrollableFrame* scrollableFrame = rootScrollFrame->GetScrollTargetFrame();
|
||||
if (scrollableFrame) {
|
||||
scrollableFrame->NotifyApzTransaction();
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -7932,6 +7938,10 @@ nsDisplayScrollInfoLayer::ComputeScrollMetadata(
|
||||
false,
|
||||
Some(aContainerParameters));
|
||||
metadata.GetMetrics().SetIsScrollInfoLayer(true);
|
||||
nsIScrollableFrame* scrollableFrame = mScrollFrame->GetScrollTargetFrame();
|
||||
if (scrollableFrame) {
|
||||
scrollableFrame->NotifyApzTransaction();
|
||||
}
|
||||
|
||||
return UniquePtr<ScrollMetadata>(new ScrollMetadata(metadata));
|
||||
}
|
||||
|
@ -737,6 +737,9 @@ pref("apz.pinch_lock.scoll_lock_threshold", "0.03125"); // 1/32 inches
|
||||
pref("apz.pinch_lock.span_breakout_threshold", "0.03125"); // 1/32 inches
|
||||
pref("apz.pinch_lock.span_lock_threshold", "0.03125"); // 1/32 inches
|
||||
pref("apz.popups.enabled", false);
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("apz.relative-update.enabled", true);
|
||||
#endif
|
||||
|
||||
// Whether to print the APZC tree for debugging
|
||||
pref("apz.printtree", false);
|
||||
|
@ -2070,6 +2070,7 @@ STATIC_ATOMS = [
|
||||
# Scroll origins without smooth-scrolling prefs
|
||||
Atom("apz", "apz"),
|
||||
Atom("restore", "restore"),
|
||||
Atom("relative", "relative"),
|
||||
|
||||
Atom("alert", "alert"),
|
||||
Atom("alertdialog", "alertdialog"),
|
||||
|
Loading…
Reference in New Issue
Block a user