tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a22fae43e3022fe93b695b8931343cfb8139262c
parent 6c08e3a2d61f5667e682ea7359cb6eb70233a94e
Author: Botond Ballo <botond@mozilla.com>
Date:   Tue, 25 Nov 2025 03:52:41 +0000

Bug 2001866 - Stop using the sticky display item in ClipManager::DefineStickyNode r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D273733

Diffstat:
Mgfx/layers/wr/ClipManager.cpp | 103+++++++++++++------------------------------------------------------------------
Mgfx/layers/wr/ClipManager.h | 10----------
Mgfx/layers/wr/WebRenderCommandBuilder.cpp | 16----------------
Mlayout/reftests/position-sticky/reftest.list | 1+
Alayout/reftests/position-sticky/transformed-4-ref.html | 19+++++++++++++++++++
Alayout/reftests/position-sticky/transformed-4.html | 19+++++++++++++++++++
6 files changed, 55 insertions(+), 113 deletions(-)

diff --git a/gfx/layers/wr/ClipManager.cpp b/gfx/layers/wr/ClipManager.cpp @@ -8,7 +8,6 @@ #include "DisplayItemClipChain.h" #include "FrameMetrics.h" -#include "mozilla/ReverseIterator.h" #include "mozilla/ScrollContainerFrame.h" #include "mozilla/dom/Document.h" #include "mozilla/layers/StackingContextHelper.h" @@ -16,6 +15,7 @@ #include "mozilla/StaticPrefs_apz.h" #include "mozilla/webrender/WebRenderAPI.h" #include "nsDisplayList.h" +#include "nsLayoutUtils.h" #include "nsRefreshDriver.h" #include "nsStyleStructInlines.h" #include "UnitTransforms.h" @@ -156,15 +156,6 @@ void ClipManager::PopOverrideForASR(const ActiveScrolledRoot* aASR) { } } -void ClipManager::PushStickyItem(const nsDisplayStickyPosition* aItem) { - mStickyItemStack.push_back(aItem); -} - -void ClipManager::PopStickyItem() { - MOZ_ASSERT(!mStickyItemStack.empty()); - mStickyItemStack.pop_back(); -} - wr::WrSpatialId ClipManager::SpatialIdAfterOverride( const wr::WrSpatialId& aSpatialId) { auto it = mASROverride.find(aSpatialId); @@ -386,56 +377,6 @@ static nscoord NegativePart(nscoord min, nscoord max) { return 0; } -const nsDisplayStickyPosition* ClipManager::FindStickyItem( - nsDisplayItem* aItemWithStickyASR, const nsIFrame* aStickyFrame) const { - // Most common case: the sticky item is the item with the sticky ASR. - if (aItemWithStickyASR->GetType() == DisplayItemType::TYPE_STICKY_POSITION && - aItemWithStickyASR->Frame() == aStickyFrame) { - return static_cast<nsDisplayStickyPosition*>(aItemWithStickyASR); - } - - // Next most common case: the item with the sticky ASR is a descendant of the - // sticky item. We've pushed sticky items we've entered onto a stack, - // so iterate it backwards to find our sticky item. - for (const nsDisplayStickyPosition* item : - mozilla::Reversed(mStickyItemStack)) { - if (item->Frame() == aStickyFrame) { - return item; - } - } - - // Edge case: the item with the sticky ASR is a wrapper display item wrapping - // the sticky item (e.g. an nsDisplayBlendMode). Fish out the sticky item. - if (aItemWithStickyASR->Frame() == aStickyFrame) { - nsDisplayItem* item = aItemWithStickyASR; - while (item) { - nsDisplayList* children = item->GetChildren(); - if (!children) { - return nullptr; - } - nsDisplayItem* onlyChild = nullptr; - for (nsDisplayItem* child : *children) { - if (!onlyChild) { - onlyChild = child; - } else { - // More than one child - return nullptr; - } - } - if (!onlyChild || onlyChild->Frame() != aStickyFrame) { - // Not a wrapping display item for the same frame. - return nullptr; - } - if (onlyChild->GetType() == DisplayItemType::TYPE_STICKY_POSITION) { - return static_cast<nsDisplayStickyPosition*>(onlyChild); - } - // Unwrap and keep looking. - item = onlyChild; - } - } - return nullptr; -} - Maybe<wr::WrSpatialId> ClipManager::DefineStickyNode( nsDisplayListBuilder* aBuilder, Maybe<wr::WrSpatialId> aParentSpatialId, const ActiveScrolledRoot* aASR, nsDisplayItem* aItem) { @@ -462,22 +403,21 @@ Maybe<wr::WrSpatialId> ClipManager::DefineStickyNode( float auPerDevPixel = stickyFrame->PresContext()->AppUnitsPerDevPixel(); nsRect itemBounds; - nsPoint toReferenceFrame; - - const nsDisplayStickyPosition* stickyItem = - FindStickyItem(aItem, stickyFrame); - if (stickyItem) { - bool snap; - itemBounds = stickyItem->GetBounds(aBuilder, &snap); - toReferenceFrame = stickyItem->ToReferenceFrame(); - } else { - MOZ_ASSERT(false, - "Cannot find sticky item in ClipManager::DefineStickyNode, " - "using fallback bounds which may be inaccurate"); - itemBounds = stickyFrame->GetRect() + - aBuilder->ToReferenceFrame(stickyFrame->GetParent()); - toReferenceFrame = aBuilder->ToReferenceFrame(stickyFrame); - } + + // Make both itemBounds and scrollPort be relative to the reference frame + // of the sticky frame's parent. + nsRect scrollPort = + stickyScrollContainer->ScrollContainer()->GetScrollPortRect(); + const nsIFrame* referenceFrame = + aBuilder->FindReferenceFrameFor(stickyFrame->GetParent()); + nsRect transformedBounds = stickyFrame->GetRectRelativeToSelf(); + DebugOnly transformResult = nsLayoutUtils::TransformRect( + stickyFrame, referenceFrame, transformedBounds); + MOZ_ASSERT(transformResult == nsLayoutUtils::TRANSFORM_SUCCEEDED); + itemBounds = transformedBounds; + scrollPort = scrollPort + + stickyScrollContainer->ScrollContainer()->GetOffsetToCrossDoc( + referenceFrame); Maybe<float> topMargin; Maybe<float> rightMargin; @@ -491,17 +431,6 @@ Maybe<wr::WrSpatialId> ClipManager::DefineStickyNode( nsRectAbsolute inner; stickyScrollContainer->GetScrollRanges(stickyFrame, &outer, &inner); - nsPoint offset = - stickyScrollContainer->ScrollContainer()->GetOffsetToCrossDoc( - stickyFrame) + - toReferenceFrame; - - // Adjust the scrollPort coordinates to be relative to the reference frame, - // so that it is in the same space as everything else. - nsRect scrollPort = - stickyScrollContainer->ScrollContainer()->GetScrollPortRect(); - scrollPort += offset; - // The following computations make more sense upon understanding the // semantics of "inner" and "outer", which is explained in the comment on // SetStickyPositionData in Layers.h. diff --git a/gfx/layers/wr/ClipManager.h b/gfx/layers/wr/ClipManager.h @@ -69,9 +69,6 @@ class ClipManager { const wr::WrSpatialId& aSpatialId); void PopOverrideForASR(const ActiveScrolledRoot* aASR); - void PushStickyItem(const nsDisplayStickyPosition* aItem); - void PopStickyItem(); - private: wr::WrSpatialId SpatialIdAfterOverride(const wr::WrSpatialId& aSpatialId); wr::WrSpatialId GetSpatialId(const ActiveScrolledRoot* aASR); @@ -84,8 +81,6 @@ class ClipManager { Maybe<wr::WrSpatialId> DefineStickyNode( nsDisplayListBuilder* aBuilder, Maybe<wr::WrSpatialId> aParentSpatialId, const ActiveScrolledRoot* aASR, nsDisplayItem* aItem); - const nsDisplayStickyPosition* FindStickyItem( - nsDisplayItem* aItemWithStickyASR, const nsIFrame* aStickyFrame) const; Maybe<wr::WrClipChainId> DefineClipChain(const DisplayItemClipChain* aChain, int32_t aAppUnitsPerDevPixel); @@ -127,11 +122,6 @@ class ClipManager { // is why we need a stack. std::unordered_map<wr::WrSpatialId, std::stack<wr::WrSpatialId>> mASROverride; - // A stack of sticky display items that WebRender display list building has - // entered. This is used to find the sticky display item corresponding to - // a sticky frame when creating a sticky spatial node in DefineStickyNode. - std::vector<const nsDisplayStickyPosition*> mStickyItemStack; - // This holds some clip state for a single nsDisplayItem struct ItemClips { ItemClips(const ActiveScrolledRoot* aASR, diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -1992,16 +1992,6 @@ struct MOZ_STACK_CLASS WebRenderCommandBuilder::AutoOpaqueRegionStateTracker { } }; -struct MOZ_STACK_CLASS AutoEnterStickyItem { - ClipManager& mClipManager; - - AutoEnterStickyItem(ClipManager& aClipManager, nsDisplayStickyPosition* aItem) - : mClipManager(aClipManager) { - mClipManager.PushStickyItem(aItem); - } - ~AutoEnterStickyItem() { mClipManager.PopStickyItem(); } -}; - void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList( nsDisplayList* aDisplayList, nsDisplayItem* aWrappingItem, nsDisplayListBuilder* aDisplayListBuilder, const StackingContextHelper& aSc, @@ -2049,12 +2039,6 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList( // applied. Maybe<AutoDisplayItemCacheSuppressor> cacheSuppressor; - Maybe<AutoEnterStickyItem> autoStickyItem; - if (itemType == DisplayItemType::TYPE_STICKY_POSITION) { - autoStickyItem.emplace(mClipManager, - static_cast<nsDisplayStickyPosition*>(item)); - } - if (itemType == DisplayItemType::TYPE_OPACITY) { nsDisplayOpacity* opacity = static_cast<nsDisplayOpacity*>(item); diff --git a/layout/reftests/position-sticky/reftest.list b/layout/reftests/position-sticky/reftest.list @@ -52,6 +52,7 @@ fuzzy(0-1,0-220) == block-in-inline-3.html block-in-inline-3-ref.html == transformed-1.html transformed-1-ref.html skip-if(useDrawSnapshot) fails-if(useDrawSnapshot) fuzzy-if(Android,0-8,0-10) fuzzy-if(cocoaWidget,7-8,18-42) fuzzy-if(cocoaWidget&&isDebugBuild&&!swgl,0-14,0-31) fuzzy-if(gtkWidget,5-21,12-32) == transformed-2.html transformed-2-ref.html # Bug 1604644, Bug 1934906 == transformed-3.html transformed-3-ref.html +== transformed-4.html transformed-4-ref.html skip-if(useDrawSnapshot) fails-if(useDrawSnapshot) fuzzy-if(Android,0-14,0-17) fuzzy-if(cocoaWidget,13-16,20-44) fuzzy-if(cocoaWidget&&isDebugBuild&&!swgl,0-29,0-36) fuzzy-if(gtkWidget,8-37,12-32) == nested-sticky-1.html nested-sticky-1-ref.html # Bug 1604644, Bug 1934906 skip-if(useDrawSnapshot) fails-if(useDrawSnapshot) fuzzy-if(Android,0-14,0-96) fuzzy-if(cocoaWidget,13-16,20-44) fuzzy-if(cocoaWidget&&isDebugBuild&&!swgl,0-29,0-36) fuzzy-if(gtkWidget,8-37,12-32) == nested-sticky-2.html nested-sticky-2-ref.html # Bug 1604644, Bug 1934906 skip == fixed-inside-sticky-clip.html fixed-inside-sticky-clip-ref.html # should be fixed by bug 1730749 diff --git a/layout/reftests/position-sticky/transformed-4-ref.html b/layout/reftests/position-sticky/transformed-4-ref.html @@ -0,0 +1,19 @@ +<style> + html, body { + margin: 0; + padding: 0; + scrollbar-width: none; + } + body { + height: 200vh; + } + #sticky { + background: grey; + position: absolute; + width: 200px; + height: 200px; + left: -50px; + top: 50px; + } +</style> +<div id="sticky"></div> diff --git a/layout/reftests/position-sticky/transformed-4.html b/layout/reftests/position-sticky/transformed-4.html @@ -0,0 +1,19 @@ +<style> + html, body { + margin: 0; + padding: 0; + scrollbar-width: none; + } + body { + height: 200vh; + } + #sticky { + background: grey; + position: sticky; + width: 100px; + height: 100px; + top: 100px; + transform: scale(2); + } +</style> +<div id="sticky"></div>