tor-browser

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

commit 194e8b90fc7fcb23fa515c70f76c72c432097203
parent 0005d5ba37d31857fd4a193ff70e560791ca0cb6
Author: Botond Ballo <botond@mozilla.com>
Date:   Tue, 25 Nov 2025 01:50:34 +0000

Bug 2000991 - Generalize ClipManager::FindStickyItem() to handle other items for the sticky frame (e.g. blend mode) wrapping the sticky item. r=mstange

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

Diffstat:
Mgfx/layers/wr/ClipManager.cpp | 47++++++++++++++++++++++++++++++++++++++++++-----
Mgfx/layers/wr/ClipManager.h | 4++--
Alayout/base/crashtests/2000991.html | 7+++++++
Mlayout/base/crashtests/crashtests.list | 1+
4 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/gfx/layers/wr/ClipManager.cpp b/gfx/layers/wr/ClipManager.cpp @@ -378,16 +378,53 @@ static nscoord NegativePart(nscoord min, nscoord max) { return 0; } -const nsDisplayStickyPosition* ClipManager::FindStickyItemFromFrame( - const nsIFrame* aStickyFrame) const { - // Iterate in reverse order as the sticky item is more likely to be at - // the top of the stack. +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; } @@ -420,7 +457,7 @@ Maybe<wr::WrSpatialId> ClipManager::DefineStickyNode( nsPoint toReferenceFrame; const nsDisplayStickyPosition* stickyItem = - FindStickyItemFromFrame(stickyFrame); + FindStickyItem(aItem, stickyFrame); if (stickyItem) { bool snap; itemBounds = stickyItem->GetBounds(aBuilder, &snap); diff --git a/gfx/layers/wr/ClipManager.h b/gfx/layers/wr/ClipManager.h @@ -84,8 +84,8 @@ class ClipManager { Maybe<wr::WrSpatialId> DefineStickyNode( nsDisplayListBuilder* aBuilder, Maybe<wr::WrSpatialId> aParentSpatialId, const ActiveScrolledRoot* aASR, nsDisplayItem* aItem); - const nsDisplayStickyPosition* FindStickyItemFromFrame( - const nsIFrame* aStickyFrame) const; + const nsDisplayStickyPosition* FindStickyItem( + nsDisplayItem* aItemWithStickyASR, const nsIFrame* aStickyFrame) const; Maybe<wr::WrClipChainId> DefineClipChain(const DisplayItemClipChain* aChain, int32_t aAppUnitsPerDevPixel); diff --git a/layout/base/crashtests/2000991.html b/layout/base/crashtests/2000991.html @@ -0,0 +1,7 @@ +<style> +* { + position: sticky; + mix-blend-mode: screen; +} +</style> + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list @@ -568,3 +568,4 @@ load 1929445.html asserts(1-3) load 1931933.html load 1984507.html load 2000121.html +load 2000991.html