diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 6cd4494ce8d2..f3400ffdeb91 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -670,72 +670,6 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer, aLayer, data, pending); } -nsDisplayListBuilder::AutoCurrentScrollParentIdSetter:: - AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, - nsIFrame* aScrollParent) - : mBuilder(aBuilder) - , mOldScrollParent(aBuilder->mCurrentScrollParent) - , mOldDisplayPortConsideringAncestors(aBuilder->mDisplayPortConsideringAncestors) - , mOldScrollPortConsideringAncestors(aBuilder->mScrollPortConsideringAncestors) - , mOldScrollParentId(aBuilder->mCurrentScrollParentId) - , mOldForceLayer(aBuilder->mForceLayerForScrollParent) - , mChangedSubtrees(false) -{ - aBuilder->UpdateCurrentScrollParent(aScrollParent); - Init(); -} - -nsDisplayListBuilder::AutoCurrentScrollParentIdSetter:: - AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, - const OutOfFlowDisplayData* aOutOfFlowData) - : mBuilder(aBuilder) - , mOldScrollParent(aBuilder->mCurrentScrollParent) - , mOldDisplayPortConsideringAncestors(aBuilder->mDisplayPortConsideringAncestors) - , mOldScrollPortConsideringAncestors(aBuilder->mScrollPortConsideringAncestors) - , mOldScrollParentId(aBuilder->mCurrentScrollParentId) - , mOldForceLayer(aBuilder->mForceLayerForScrollParent) - , mChangedSubtrees(true) -{ - aBuilder->UpdateCurrentScrollParentForOutOfFlow(aOutOfFlowData); - Init(); -} - -void -nsDisplayListBuilder::AutoCurrentScrollParentIdSetter::Init() -{ - // If this AutoCurrentScrollParentIdSetter has the same scrollId as the - // previous one on the stack, then that means the scrollframe that - // created this isn't actually scrollable and cannot participate in - // scroll handoff. We set mCanBeScrollParent to false to indicate this. - mCanBeScrollParent = mOldScrollParentId != mBuilder->mCurrentScrollParentId; - - mBuilder->mForceLayerForScrollParent = false; -} - -nsDisplayListBuilder::AutoCurrentScrollParentIdSetter:: - ~AutoCurrentScrollParentIdSetter() -{ - mBuilder->mCurrentScrollParent = mOldScrollParent; - mBuilder->mDisplayPortConsideringAncestors = mOldDisplayPortConsideringAncestors; - mBuilder->mScrollPortConsideringAncestors = mOldScrollPortConsideringAncestors; - mBuilder->mCurrentScrollParentId = mOldScrollParentId; - - if (mCanBeScrollParent || mChangedSubtrees) { - // If |mCanBeScrollParent| is set, caller code is responsible for - // having dealt with the current value of - // mBuilder->mForceLayerForScrollParent, so we can just restore the - // old value. If |mChangedSubtrees| is set, we don't propagate the - // flag because it doesn't make sense to propagate it through - // unrelated subtrees. - mBuilder->mForceLayerForScrollParent = mOldForceLayer; - } else { - // Otherwise we need to keep propagating the force-layerization flag - // upwards to the next ancestor scrollframe that does participate in - // scroll handoff. - mBuilder->mForceLayerForScrollParent |= mOldForceLayer; - } -} - nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, nsDisplayListBuilderMode aMode, bool aBuildCaret) : mReferenceFrame(aReferenceFrame), @@ -751,7 +685,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mGlassDisplayItem(nullptr), mScrollInfoItemsForHoisting(nullptr), mMode(aMode), - mCurrentScrollParent(nullptr), mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarFlags(0), @@ -799,9 +732,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mFrameToAnimatedGeometryRootMap.Put(aReferenceFrame, &mRootAGR); - UpdateCurrentScrollParent( - nsLayoutUtils::GetAsyncScrollableProperAncestorFrameOrFallback(aReferenceFrame)); - nsCSSRendering::BeginFrameTreesLocked(); PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS)); } @@ -924,12 +854,7 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants(); const DisplayItemScrollClip* sc = mClipState.GetCurrentInnermostScrollClip(); - OutOfFlowDisplayData* data = - new OutOfFlowDisplayData(oldClip, sc, dirty, - mCurrentScrollParent, mCurrentScrollParentId, - mDisplayPortConsideringAncestors, - mScrollPortConsideringAncestors); - + OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, dirty); aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data); MarkFrameForDisplay(aFrame, aDirtyFrame); @@ -1296,132 +1221,6 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame) return cursor; } -void -nsDisplayListBuilder::UpdateCurrentScrollParent(nsIFrame* aScrollParent) -{ - // If the new scroll parent is the same as the old scroll parent, we don't - // have to do anything. This can happen because we sometimes instantiate an - // AutoCurrentScrollParentIdSetter unconditionally but only pass it a new - // scroll parent if certain conditions are true. - if (aScrollParent == mCurrentScrollParent) { - return; - } - - // Update the current scroll parent. - nsIFrame* oldScrollParent = mCurrentScrollParent; - mCurrentScrollParent = aScrollParent; - - // If there's no scroll parent now (which may be true because we're - // initializing this nsDisplayListBuilder for the first time, or because - // we're in a strange state where there's no pres shell or no root frame) - // then we just reset everything to its initial values. - if (!aScrollParent) { - mDisplayPortConsideringAncestors = nsRect(); - mScrollPortConsideringAncestors = nsRect(); - mCurrentScrollParentId = FrameMetrics::NULL_SCROLL_ID; - return; - } - - // Compute the new scroll parent ID. - nsIContent* content = aScrollParent->GetContent(); - mCurrentScrollParentId = content ? nsLayoutUtils::FindOrCreateIDFor(content) - : FrameMetrics::NULL_SCROLL_ID; - - nsIScrollableFrame* newScrollParent = do_QueryFrame(aScrollParent); - if (!newScrollParent) { - // There's no scrollable parent frame, so we've been forced to fall back - // to the root frame. (Most likely this is a XUL document.) Just use its - // size for both the displayport and the scrollport. - MOZ_ASSERT(!oldScrollParent, "Falling back to the root frame when an ancestor " - "scrollable frame existed?"); - nsRect frameRect(nsPoint(0, 0), aScrollParent->GetSize()); - mDisplayPortConsideringAncestors = frameRect; - mScrollPortConsideringAncestors = frameRect; - return; - } - - MOZ_ASSERT(mCurrentScrollParentId != FrameMetrics::NULL_SCROLL_ID, - "Couldn't get a scroll ID for a scrollable frame?"); - - // If we didn't have a scroll parent before, but we do now, the displayport - // and scrollport we're tracking are just those of the new scroll parent. - if (!oldScrollParent) { - mDisplayPortConsideringAncestors = - nsLayoutUtils::GetDisplayPortOrFallbackToScrollPort(newScrollParent); - mScrollPortConsideringAncestors = newScrollParent->GetScrollPortRect(); - return; - } - -#ifdef DEBUG - { - nsIScrollableFrame* oldScrollableParent = do_QueryFrame(oldScrollParent); - if (oldScrollableParent && oldScrollableParent->WantAsyncScroll()) { - // Normally, the old scroll parent should be the nearest async - // scrollable ancestor of the new scroll parent. - MOZ_ASSERT(nsLayoutUtils::GetAsyncScrollableProperAncestorFrame(aScrollParent) == - oldScrollableParent); - } else { - // If the old scroll parent isn't async scrollable or isn't scrollable - // at all, (e.g., because we had to fall back to the root frame in a XUL - // document) then at least assert it's an ancestor of the new scroll parent. - MOZ_ASSERT(nsLayoutUtils::IsProperAncestorFrameCrossDoc(oldScrollParent, - aScrollParent)); - } - } -#endif - - // If the effective displayport, considering ancestors, is already empty, we - // can bail early as we know the intersection checks below will fail. - if (mDisplayPortConsideringAncestors.IsEmpty()) { - mDisplayPortConsideringAncestors = nsRect(); - mScrollPortConsideringAncestors = nsRect(); - return; - } - - // The entire displayport for this subtree is the critical displayport of - // this scroll parent if any part of it is visible within the previous scroll - // parent's critical displayport. (What we're trying to do is capture - // everything that APZ could asynchronously scroll into view.) If it isn't - // visible, then the displayport for this subtree is empty and the - // scrollport, trivially, is too. - nsRect displayPort = - nsLayoutUtils::GetDisplayPortOrFallbackToScrollPort(newScrollParent); - nsRect displayPortIntersection = - nsLayoutUtils::TransformAndIntersectRect(oldScrollParent, - mDisplayPortConsideringAncestors, - aScrollParent, - displayPort); - if (displayPortIntersection.IsEmpty()) { - mDisplayPortConsideringAncestors = nsRect(); - mScrollPortConsideringAncestors = nsRect(); - return; - } - - // See above: we take the whole thing, not the intersection with the - // previous scroll parent's critical displayport. - mDisplayPortConsideringAncestors = displayPort; - - // The scrollport for this subtree is the intersection of aScrollParent's - // scrollport with all ancestor scrollports. - mScrollPortConsideringAncestors = - nsLayoutUtils::TransformAndIntersectRect(oldScrollParent, - mScrollPortConsideringAncestors, - aScrollParent, - newScrollParent->GetScrollPortRect()); -} - -void -nsDisplayListBuilder::UpdateCurrentScrollParentForOutOfFlow(const OutOfFlowDisplayData* aOutOfFlowData) -{ - MOZ_ASSERT(aOutOfFlowData); - - // Just set the information from |aOutOfFlowData| unconditionally. - mCurrentScrollParent = aOutOfFlowData->mCurrentScrollParent; - mCurrentScrollParentId = aOutOfFlowData->mCurrentScrollParentId; - mDisplayPortConsideringAncestors = aOutOfFlowData->mDisplayPortConsideringAncestors; - mScrollPortConsideringAncestors = aOutOfFlowData->mScrollPortConsideringAncestors; -} - void nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot() { diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 218803d6f1fa..97d98107822b 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -368,30 +368,6 @@ public: * Get the scrollframe to ignore, if any. */ nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; } - /** - * Get the nearest ancestor scrollframe, or the root frame if there is no - * ancestor scrollframe, or null if neither exists. - */ - nsIFrame* GetCurrentScrollParent() { return mCurrentScrollParent; } - /** - * Get the critical displayport of the nearest ancestor scrollframe, in the - * coordinate system of the frame returned by GetCurrentScrollParent(). If - * the ancestor scrollframe's critical displayport does not intersect the - * critical displayport of the scrollframe that encloses it, and so on - * transitively up the frame tree, returns the empty rect. The idea is that - * this method considers a displayport visible if its nearest ancestor is - * visible and some part of it intersects its nearest ancestor, which means - * that we capture everything that APZ could asynchronously scroll into - * view. Used for visibility tracking during painting. - */ - nsRect GetDisplayPortConsideringAncestors() { return mDisplayPortConsideringAncestors; } - /** - * Get the intersection of all ancestor scrollframes' scrollports. Used for - * visibility tracking during painting. Unlike the displayport case, for - * scrollports we use strict intersection, because we only want to detect - * frames that are actually visible in the viewport. - */ - nsRect GetScrollPortConsideringAncestors() { return mScrollPortConsideringAncestors; } /** * Get the ViewID of the nearest scrolling ancestor frame. */ @@ -850,64 +826,49 @@ public: uint32_t mCachedItemIndex; }; - struct OutOfFlowDisplayData; - /** - * A helper class to temporarily set the value of mCurrentScrollParentId and - * cache information about the effective displayport and scrollport, - * considering all ancestor scrollframes. See - * GetDisplayPortConsideringAncestors() and - * GetScrollPortConsideringAncestors() for the details. + * A helper class to temporarily set the value of mCurrentScrollParentId. */ class AutoCurrentScrollParentIdSetter; friend class AutoCurrentScrollParentIdSetter; class AutoCurrentScrollParentIdSetter { public: - /** - * Temporarily update the cached scroll parent information on @aBuilder - * from frame @aFrame. @aFrame should be a a scrollframe that is a - * descendant of @aBuilder's current scroll parent. (The exception is if - * there's no current scroll parent, in which case @aFrame does not have to - * be a scrollframe; this is fallback behavior for XUL documents, which - * may not have a root scrollframe.) - * - * If @aNewScrollParentFrom is SCROLLFRAMES_ON_PATH_TO_ROOT, @aFrame is - * interpreted as a scrollframe in a different subtree. In this case we - * have to walk up the frame tree all the way to the root to gather - * information about the effective displayport and scrollport. - */ - AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, - nsIFrame* aScrollParent); - - /** - * Temporarily updated the cached scroll parent information on @aBuilder - * from saved information on @aOutOfFlowData. This is necessary when - * traversing out-of-flow frames via their placeholder frames, since their - * scroll parent may not be the same as the scroll parent of the - * placeholder frame. - */ - AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, - const OutOfFlowDisplayData* aOutOfFlowData); - - ~AutoCurrentScrollParentIdSetter(); - + AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId) + : mBuilder(aBuilder) + , mOldValue(aBuilder->mCurrentScrollParentId) + , mOldForceLayer(aBuilder->mForceLayerForScrollParent) { + // If this AutoCurrentScrollParentIdSetter has the same scrollId as the + // previous one on the stack, then that means the scrollframe that + // created this isn't actually scrollable and cannot participate in + // scroll handoff. We set mCanBeScrollParent to false to indicate this. + mCanBeScrollParent = (mOldValue != aScrollId); + aBuilder->mCurrentScrollParentId = aScrollId; + aBuilder->mForceLayerForScrollParent = false; + } bool ShouldForceLayerForScrollParent() const { // Only scrollframes participating in scroll handoff can be forced to // layerize return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent; + }; + ~AutoCurrentScrollParentIdSetter() { + mBuilder->mCurrentScrollParentId = mOldValue; + if (mCanBeScrollParent) { + // If this flag is set, caller code is responsible for having dealt + // with the current value of mBuilder->mForceLayerForScrollParent, so + // we can just restore the old value. + mBuilder->mForceLayerForScrollParent = mOldForceLayer; + } else { + // Otherwise we need to keep propagating the force-layerization flag + // upwards to the next ancestor scrollframe that does participate in + // scroll handoff. + mBuilder->mForceLayerForScrollParent |= mOldForceLayer; + } } - private: - void Init(); - nsDisplayListBuilder* mBuilder; - nsIFrame* mOldScrollParent; - nsRect mOldDisplayPortConsideringAncestors; - nsRect mOldScrollPortConsideringAncestors; - ViewID mOldScrollParentId; - bool mOldForceLayer : 1; - bool mCanBeScrollParent : 1; - bool mChangedSubtrees : 1; + ViewID mOldValue; + bool mOldForceLayer; + bool mCanBeScrollParent; }; /** @@ -1028,26 +989,14 @@ public: struct OutOfFlowDisplayData { OutOfFlowDisplayData(const DisplayItemClip* aContainingBlockClip, const DisplayItemScrollClip* aContainingBlockScrollClip, - const nsRect& aDirtyRect, - nsIFrame* aCurrentScrollParent, - ViewID aCurrentScrollParentId, - const nsRect& aDisplayPortConsideringAncestors, - const nsRect& aScrollPortConsideringAncestors) + const nsRect &aDirtyRect) : mContainingBlockClip(aContainingBlockClip ? *aContainingBlockClip : DisplayItemClip()) , mContainingBlockScrollClip(aContainingBlockScrollClip) , mDirtyRect(aDirtyRect) - , mCurrentScrollParent(aCurrentScrollParent) - , mCurrentScrollParentId(aCurrentScrollParentId) - , mDisplayPortConsideringAncestors(aDisplayPortConsideringAncestors) - , mScrollPortConsideringAncestors(aScrollPortConsideringAncestors) {} DisplayItemClip mContainingBlockClip; const DisplayItemScrollClip* mContainingBlockScrollClip; nsRect mDirtyRect; - nsIFrame* mCurrentScrollParent; - ViewID mCurrentScrollParentId; - nsRect mDisplayPortConsideringAncestors; - nsRect mScrollPortConsideringAncestors; }; NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty, @@ -1204,23 +1153,6 @@ private: */ nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame); - /** - * Updates cached information about the nearest ancestor scrollable frame. - * @aScrollParent should be a descendant of the previous nearest ancestor - * scrollable frame. @aScrollParent may be null, indicating that there is - * no ancestor scrollable frame. - */ - void UpdateCurrentScrollParent(nsIFrame* aScrollParent); - - /** - * Updates cached information about the nearest ancestor scrollable frame. - * The new information is read from @aOutOfFlowData, and unconditionally - * replaces the cached information without reference to the current scroll - * parent, since we're descending into an out-of-flow frame that does not - * necessarily have the same scroll parent chain. - */ - void UpdateCurrentScrollParentForOutOfFlow(const OutOfFlowDisplayData* aOutOfFlowData); - friend class nsDisplayCanvasBackgroundImage; friend class nsDisplayBackgroundImage; friend class nsDisplayFixedPosition; @@ -1318,10 +1250,7 @@ private: nsTArray mScrollClipsToDestroy; nsTArray mDisplayItemClipsToDestroy; nsDisplayListBuilderMode mMode; - nsIFrame* mCurrentScrollParent; ViewID mCurrentScrollParentId; - nsRect mDisplayPortConsideringAncestors; - nsRect mScrollPortConsideringAncestors; ViewID mCurrentScrollbarTarget; uint32_t mCurrentScrollbarFlags; Preserves3DContext mPreserves3DCtx; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index afb4bf39d17a..c1f34d4aa4ed 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3534,6 +3534,34 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram builder.EnterPresShell(aFrame); nsRect dirtyRect = visibleRegion.GetBounds(); { + // If a scrollable container layer is created in nsDisplayList::PaintForFrame, + // it will be the scroll parent for display items that are built in the + // BuildDisplayListForStackingContext call below. We need to set the scroll + // parent on the display list builder while we build those items, so that they + // can pick up their scroll parent's id. + ViewID id = FrameMetrics::NULL_SCROLL_ID; + if (ignoreViewportScrolling && presContext->IsRootContentDocument()) { + if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) { + if (nsIContent* content = rootScrollFrame->GetContent()) { + id = nsLayoutUtils::FindOrCreateIDFor(content); + } + } + } +#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ) + else if (presShell->GetDocument() && presShell->GetDocument()->IsRootDisplayDocument() + && !presShell->GetRootScrollFrame()) { + // In cases where the root document is a XUL document, we want to take + // the ViewID from the root element, as that will be the ViewID of the + // root APZC in the tree. Skip doing this in cases where we know + // nsGfxScrollFrame::BuilDisplayList will do it instead. + if (dom::Element* element = presShell->GetDocument()->GetDocumentElement()) { + id = nsLayoutUtils::FindOrCreateIDFor(element); + } + } +#endif + + nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(&builder, id); + PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList", js::ProfileEntry::Category::GRAPHICS); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 0ca3228cac85..de44d92fe4a0 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -2782,17 +2782,11 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, DisplayListClipState::AutoClipMultiple clipState(aBuilder); CheckForApzAwareEventHandlers(aBuilder, child); - Maybe idSetter; if (savedOutOfFlowData) { clipState.SetClipForContainingBlockDescendants( &savedOutOfFlowData->mContainingBlockClip); clipState.SetScrollClipForContainingBlockDescendants( savedOutOfFlowData->mContainingBlockScrollClip); - - // For out-of-flow frames, the current scroll parent is wrong, because it's - // the scroll parent for the placeholder frame rather than the actual - // out-of-flow frame, so we need to update the current scroll parent. - idSetter.emplace(aBuilder, savedOutOfFlowData); } else if (GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO && isPlaceholder) { // If we have nested out-of-flow frames and the outer one isn't visible diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 8e5194a3c412..a17349ca5e36 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3299,11 +3299,11 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, // parent. This is intentional because that is what happens for positioned children // of scroll layers, and we want to maintain consistent behaviour between scroll layers // and scroll info layers. - nsIContent* content = couldBuildLayer ? mScrolledFrame->GetContent() - : nullptr; - nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter( - aBuilder, content ? mOuter : aBuilder->GetCurrentScrollParent()); + aBuilder, + couldBuildLayer && mScrolledFrame->GetContent() + ? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent()) + : aBuilder->GetCurrentScrollParentId()); nsRect clipRect = mScrollPort + aBuilder->ToReferenceFrame(mOuter); // Our override of GetBorderRadii ensures we never have a radius at diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 49d739ee308f..8344a7dfd0c4 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -483,12 +483,11 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (subdocRootFrame) { nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame(); - nsIContent* content = ignoreViewportScrolling && rootScrollFrame - ? rootScrollFrame->GetContent() - : nullptr; - nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter( - aBuilder, content ? rootScrollFrame : aBuilder->GetCurrentScrollParent()); + aBuilder, + ignoreViewportScrolling && rootScrollFrame && rootScrollFrame->GetContent() + ? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent()) + : aBuilder->GetCurrentScrollParentId()); aBuilder->SetAncestorHasApzAwareEventHandler(false); subdocRootFrame->