diff --git a/layout/base/DisplayPortUtils.cpp b/layout/base/DisplayPortUtils.cpp index 58855026d8b0..45b11cb9ec6d 100644 --- a/layout/base/DisplayPortUtils.cpp +++ b/layout/base/DisplayPortUtils.cpp @@ -1289,6 +1289,40 @@ const ActiveScrolledRoot* DisplayPortUtils::ActivateDisplayportOnASRAncestors( return asr; } +const ActiveScrolledRoot* DisplayPortUtils::GetASRForAbsPosFrame( + nsIFrame* aFrame, const ActiveScrolledRoot* aContainingBlockASR, + nsDisplayListBuilder* aBuilder) { + MOZ_ASSERT(aFrame->IsAbsolutelyPositioned()); + if (!aBuilder->IsPaintingToWindow() || + // If we are in view transition capture we get a null asr no matter + // what, so don't bother checking for async scrolling with a CSS anchor + // pos anchor. + aBuilder->IsInViewTransitionCapture() || + // If there is an active view transition in this document it is tricky + // to determine what will be an active scroll frame outside of that + // frame's BuildDisplayList, so don't bother to async scroll with an + // anchor in that case. Bug 2001861 tracks removing this check. + aFrame->PresContext()->Document()->GetActiveViewTransition()) { + return aContainingBlockASR; + } + nsIFrame* scrollsWithAnchor = + AnchorPositioningUtils::GetAnchorThatFrameScrollsWith(aFrame, aBuilder); + if (!scrollsWithAnchor) { + return aContainingBlockASR; + } + if (aBuilder->IsRetainingDisplayList()) { + if (aBuilder->IsPartialUpdate()) { + aBuilder->SetPartialBuildFailed(true); + } else { + aBuilder->SetDisablePartialUpdates(true); + } + } + // TODO should we set the scroll parent id too? + // https://github.com/w3c/csswg-drafts/issues/12042 + return ActivateDisplayportOnASRAncestors( + scrollsWithAnchor, aFrame->GetParent(), aContainingBlockASR, aBuilder); +} + static bool CheckAxes(ScrollContainerFrame* aScrollFrame, PhysicalAxes aAxes) { if (aAxes == kPhysicalAxesBoth) { return true; diff --git a/layout/base/DisplayPortUtils.h b/layout/base/DisplayPortUtils.h index fe65ae6b2610..7733f0521a0a 100644 --- a/layout/base/DisplayPortUtils.h +++ b/layout/base/DisplayPortUtils.h @@ -406,6 +406,13 @@ class DisplayPortUtils { const ActiveScrolledRoot* aASRofLimitAncestor, nsDisplayListBuilder* aBuilder); + /** + * Returns the ASR that an abspos frame `aFrame` should scroll with. + */ + static const ActiveScrolledRoot* GetASRForAbsPosFrame( + nsIFrame* aFrame, const ActiveScrolledRoot* aContainingBlockASR, + nsDisplayListBuilder* aBuilder); + /** * aFrame is an absolutely positioned frame that is anchor positioned and * compensates for scroll in at least one axis. diff --git a/layout/generic/ViewportFrame.cpp b/layout/generic/ViewportFrame.cpp index 7a0314aeb513..b5c7237cf90c 100644 --- a/layout/generic/ViewportFrame.cpp +++ b/layout/generic/ViewportFrame.cpp @@ -12,6 +12,7 @@ #include "MobileViewportManager.h" #include "mozilla/AbsoluteContainingBlock.h" #include "mozilla/ComputedStyleInlines.h" +#include "mozilla/DisplayPortUtils.h" #include "mozilla/PresShell.h" #include "mozilla/ProfilerLabels.h" #include "mozilla/ReflowInput.h" @@ -133,8 +134,11 @@ static void BuildDisplayListForTopLayerFrame(nsDisplayListBuilder* aBuilder, // root scroll frame. clipState.SetClipChainForContainingBlockDescendants( savedOutOfFlowData->mCombinedClipChain); + asrSetter.SetCurrentActiveScrolledRoot( - savedOutOfFlowData->mContainingBlockActiveScrolledRoot); + DisplayPortUtils::GetASRForAbsPosFrame( + aFrame, savedOutOfFlowData->mContainingBlockActiveScrolledRoot, + aBuilder)); asrSetter.SetCurrentScrollParentId(savedOutOfFlowData->mScrollParentId); } } diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index e57e6711343e..08daead4ec52 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -4607,30 +4607,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, if (savedOutOfFlowData) { aBuilder->SetBuildingInvisibleItems(false); - nsIFrame* scrollsWithAnchor = nullptr; - if (aBuilder->IsPaintingToWindow() && - // If we are in view transition capture we get a null asr no matter - // what, so don't bother checking for async scrolling with a CSS anchor - // pos anchor. - !aBuilder->IsInViewTransitionCapture() && - child->IsAbsolutelyPositioned(disp) && - // If there is an active view transition in this document it is tricky - // to determine what will be an active scroll frame outside of that - // frame's BuildDisplayList, so don't bother to async scroll with an - // anchor in that case. Bug 2001861 tracks removing this check. - !PresContext()->Document()->GetActiveViewTransition()) { - scrollsWithAnchor = AnchorPositioningUtils::GetAnchorThatFrameScrollsWith( - child, aBuilder); - - if (scrollsWithAnchor && aBuilder->IsRetainingDisplayList()) { - if (aBuilder->IsPartialUpdate()) { - aBuilder->SetPartialBuildFailed(true); - } else { - aBuilder->SetDisablePartialUpdates(true); - } - } - } - const ActiveScrolledRoot* asr = savedOutOfFlowData->mContainingBlockActiveScrolledRoot; @@ -4669,12 +4645,8 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } #endif - if (scrollsWithAnchor) { - asr = DisplayPortUtils::ActivateDisplayportOnASRAncestors( - scrollsWithAnchor, child->GetParent(), asr, aBuilder); - - // TODO should we set the scroll parent id too? - // https://github.com/w3c/csswg-drafts/issues/12042 + if (child->IsAbsolutelyPositioned(disp)) { + asr = DisplayPortUtils::GetASRForAbsPosFrame(child, asr, aBuilder); } if (aBuilder->IsInViewTransitionCapture()) { diff --git a/layout/reftests/async-scrolling/anchor-pos-top-layer-1-ref.html b/layout/reftests/async-scrolling/anchor-pos-top-layer-1-ref.html new file mode 100644 index 000000000000..ad91bb7b5ea3 --- /dev/null +++ b/layout/reftests/async-scrolling/anchor-pos-top-layer-1-ref.html @@ -0,0 +1,32 @@ + + + +
+
+
+ diff --git a/layout/reftests/async-scrolling/anchor-pos-top-layer-1.html b/layout/reftests/async-scrolling/anchor-pos-top-layer-1.html new file mode 100644 index 000000000000..33c7e87cd93e --- /dev/null +++ b/layout/reftests/async-scrolling/anchor-pos-top-layer-1.html @@ -0,0 +1,62 @@ + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/async-scrolling/reftest.list b/layout/reftests/async-scrolling/reftest.list index baebd5c3296b..235db7c343b1 100644 --- a/layout/reftests/async-scrolling/reftest.list +++ b/layout/reftests/async-scrolling/reftest.list @@ -202,3 +202,4 @@ defaults == anchor-pos-sticky-3.html anchor-pos-sticky-3-ref.html == anchor-pos-sticky-4.html anchor-pos-sticky-4-ref.html == anchor-pos-one-axis-1.html anchor-pos-one-axis-1-ref.html +== anchor-pos-top-layer-1.html anchor-pos-top-layer-1-ref.html