diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 3861e08b3c6f..43a9c20d1666 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -6891,6 +6891,10 @@ bool nsDisplayOwnLayer::IsFixedPositionLayer() const { return GetType() == DisplayItemType::TYPE_FIXED_POSITION; } +bool nsDisplayOwnLayer::IsStickyPositionLayer() const { + return GetType() == DisplayItemType::TYPE_STICKY_POSITION; +} + bool nsDisplayOwnLayer::HasDynamicToolbar() const { if (!mFrame->PresContext()->IsRootContentDocumentCrossProcess()) { return false; @@ -6929,6 +6933,7 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands( bool needsProp = aManager->LayerManager()->AsyncPanZoomEnabled() && (IsScrollThumbLayer() || IsZoomingLayer() || (IsFixedPositionLayer() && HasDynamicToolbar()) || + (IsStickyPositionLayer() && HasDynamicToolbar()) || (IsRootScrollbarContainer() && HasDynamicToolbar())); if (needsProp) { @@ -6969,7 +6974,9 @@ bool nsDisplayOwnLayer::UpdateScrollData( mozilla::layers::WebRenderLayerScrollData* aLayerData) { bool isRelevantToApz = (IsScrollThumbLayer() || IsScrollbarContainer() || IsZoomingLayer() || - (IsFixedPositionLayer() && HasDynamicToolbar())); + (IsFixedPositionLayer() && HasDynamicToolbar()) || + (IsStickyPositionLayer() && HasDynamicToolbar())); + if (!isRelevantToApz) { return false; } @@ -6988,6 +6995,11 @@ bool nsDisplayOwnLayer::UpdateScrollData( return true; } + if (IsStickyPositionLayer() && HasDynamicToolbar()) { + aLayerData->SetStickyPositionAnimationId(mWrAnimationId); + return true; + } + MOZ_ASSERT(IsScrollbarContainer() || IsScrollThumbLayer()); aLayerData->SetScrollbarData(mScrollbarData); @@ -7334,7 +7346,8 @@ bool nsDisplayFixedPosition::UpdateScrollData( } aLayerData->SetFixedPositionScrollContainerId(GetScrollTargetId()); } - return nsDisplayOwnLayer::UpdateScrollData(aData, aLayerData) | true; + nsDisplayOwnLayer::UpdateScrollData(aData, aLayerData); + return true; } void nsDisplayFixedPosition::WriteDebugInfo(std::stringstream& aStream) { @@ -7454,23 +7467,11 @@ already_AddRefed nsDisplayStickyPosition::BuildLayer( stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent()); float factor = presContext->AppUnitsPerDevPixel(); - nsRectAbsolute outer; - nsRectAbsolute inner; - stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner); - LayerRectAbsolute stickyOuter( - NSAppUnitsToFloatPixels(outer.X(), factor) * aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(outer.Y(), factor) * aContainerParameters.mYScale, - NSAppUnitsToFloatPixels(outer.XMost(), factor) * - aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(outer.YMost(), factor) * - aContainerParameters.mYScale); - LayerRectAbsolute stickyInner( - NSAppUnitsToFloatPixels(inner.X(), factor) * aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(inner.Y(), factor) * aContainerParameters.mYScale, - NSAppUnitsToFloatPixels(inner.XMost(), factor) * - aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(inner.YMost(), factor) * - aContainerParameters.mYScale); + LayerRectAbsolute stickyOuter; + LayerRectAbsolute stickyInner; + CalculateLayerScrollRanges( + stickyScrollContainer, factor, aContainerParameters.mXScale, + aContainerParameters.mYScale, stickyOuter, stickyInner); layer->SetStickyPositionData(scrollId, stickyOuter, stickyInner); return layer.forget(); @@ -7490,11 +7491,7 @@ static nscoord DistanceToRange(nscoord min, nscoord max) { return 0; } -bool nsDisplayStickyPosition::CreateWebRenderCommands( - mozilla::wr::DisplayListBuilder& aBuilder, - mozilla::wr::IpcResourceUpdateQueue& aResources, - const StackingContextHelper& aSc, RenderRootStateManager* aManager, - nsDisplayListBuilder* aDisplayListBuilder) { +StickyScrollContainer* nsDisplayStickyPosition::GetStickyScrollContainer() { StickyScrollContainer* stickyScrollContainer = StickyScrollContainer::GetStickyScrollContainerForFrame(mFrame); if (stickyScrollContainer) { @@ -7514,6 +7511,15 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands( stickyScrollContainer = nullptr; } } + return stickyScrollContainer; +} + +bool nsDisplayStickyPosition::CreateWebRenderCommands( + mozilla::wr::DisplayListBuilder& aBuilder, + mozilla::wr::IpcResourceUpdateQueue& aResources, + const StackingContextHelper& aSc, RenderRootStateManager* aManager, + nsDisplayListBuilder* aDisplayListBuilder) { + StickyScrollContainer* stickyScrollContainer = GetStickyScrollContainer(); Maybe saccHelper; @@ -7649,7 +7655,7 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands( wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId()); StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, params); - nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, + nsDisplayOwnLayer::CreateWebRenderCommands(aBuilder, aResources, sc, aManager, aDisplayListBuilder); } @@ -7660,6 +7666,62 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands( return true; } +void nsDisplayStickyPosition::CalculateLayerScrollRanges( + StickyScrollContainer* aStickyScrollContainer, float aAppUnitsPerDevPixel, + float aScaleX, float aScaleY, LayerRectAbsolute& aStickyOuter, + LayerRectAbsolute& aStickyInner) { + nsRectAbsolute outer; + nsRectAbsolute inner; + aStickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner); + aStickyOuter.SetBox( + NSAppUnitsToFloatPixels(outer.X(), aAppUnitsPerDevPixel) * aScaleX, + NSAppUnitsToFloatPixels(outer.Y(), aAppUnitsPerDevPixel) * aScaleY, + NSAppUnitsToFloatPixels(outer.XMost(), aAppUnitsPerDevPixel) * aScaleX, + NSAppUnitsToFloatPixels(outer.YMost(), aAppUnitsPerDevPixel) * aScaleY); + aStickyInner.SetBox( + NSAppUnitsToFloatPixels(inner.X(), aAppUnitsPerDevPixel) * aScaleX, + NSAppUnitsToFloatPixels(inner.Y(), aAppUnitsPerDevPixel) * aScaleY, + NSAppUnitsToFloatPixels(inner.XMost(), aAppUnitsPerDevPixel) * aScaleX, + NSAppUnitsToFloatPixels(inner.YMost(), aAppUnitsPerDevPixel) * aScaleY); +} + +bool nsDisplayStickyPosition::UpdateScrollData( + mozilla::layers::WebRenderScrollData* aData, + mozilla::layers::WebRenderLayerScrollData* aLayerData) { + bool hasDynamicToolbar = HasDynamicToolbar(); + if (aLayerData && hasDynamicToolbar) { + StickyScrollContainer* stickyScrollContainer = GetStickyScrollContainer(); + if (stickyScrollContainer) { + float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); + float cumulativeResolution = + mFrame->PresShell()->GetCumulativeResolution(); + LayerRectAbsolute stickyOuter; + LayerRectAbsolute stickyInner; + CalculateLayerScrollRanges(stickyScrollContainer, auPerDevPixel, + cumulativeResolution, cumulativeResolution, + stickyOuter, stickyInner); + aLayerData->SetStickyScrollRangeOuter(stickyOuter); + aLayerData->SetStickyScrollRangeInner(stickyInner); + + SideBits sides = + nsLayoutUtils::GetSideBitsForFixedPositionContent(mFrame); + aLayerData->SetFixedPositionSides(sides); + + ViewID scrollId = + nsLayoutUtils::FindOrCreateIDFor(stickyScrollContainer->ScrollFrame() + ->GetScrolledFrame() + ->GetContent()); + aLayerData->SetStickyPositionScrollContainerId(scrollId); + } + } + // Return true if either there is a dynamic toolbar affecting this sticky + // item or the OwnLayer base implementation returns true for some other + // reason. + bool ret = hasDynamicToolbar; + ret |= nsDisplayOwnLayer::UpdateScrollData(aData, aLayerData); + return ret; +} + nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer( nsDisplayListBuilder* aBuilder, nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame, const CompositorHitTestInfo& aHitInfo, diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h index fa3bfd055e60..e2a070e024de 100644 --- a/layout/painting/nsDisplayList.h +++ b/layout/painting/nsDisplayList.h @@ -49,6 +49,7 @@ #include "nsAutoLayoutPhase.h" #include "nsDisplayItemTypes.h" #include "RetainedDisplayListHelpers.h" +#include "Units.h" #include #include "nsTHashtable.h" @@ -77,6 +78,7 @@ class TransformReferenceBox; namespace mozilla { class FrameLayerBuilder; class PresShell; +class StickyScrollContainer; namespace layers { struct FrameMetrics; class RenderRootStateManager; @@ -6101,6 +6103,7 @@ class nsDisplayOwnLayer : public nsDisplayWrapList { bool IsRootScrollbarContainer() const; bool IsZoomingLayer() const; bool IsFixedPositionLayer() const; + bool IsStickyPositionLayer() const; bool HasDynamicToolbar() const; protected: @@ -6236,11 +6239,23 @@ class nsDisplayStickyPosition : public nsDisplayOwnLayer { mozilla::layers::RenderRootStateManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) override; + bool UpdateScrollData( + mozilla::layers::WebRenderScrollData* aData, + mozilla::layers::WebRenderLayerScrollData* aLayerData) override; + const ActiveScrolledRoot* GetContainerASR() const { return mContainerASR; } private: NS_DISPLAY_ALLOW_CLONING() + void CalculateLayerScrollRanges( + mozilla::StickyScrollContainer* aStickyScrollContainer, + float aAppUnitsPerDevPixel, float aScaleX, float aScaleY, + mozilla::LayerRectAbsolute& aStickyOuter, + mozilla::LayerRectAbsolute& aStickyInner); + + mozilla::StickyScrollContainer* GetStickyScrollContainer(); + // This stores the ASR that this sticky container item would have assuming it // has no fixed descendants. This may be the same as the ASR returned by // GetActiveScrolledRoot(), or it may be a descendant of that.