Bug 1874199 - Animate sticky elements by using an animation property on the StickyFrame rather than creating a ReferenceFrame. r=gw,dlrobertson

This uses the support added in the previous patch to set an animation property
on a StickyFrame spatial node directly.

Depends on D208237

Differential Revision: https://phabricator.services.mozilla.com/D208238
This commit is contained in:
Dan Robertson 2024-05-02 02:49:21 +00:00
parent b7116da08f
commit 4486d95678
2 changed files with 56 additions and 23 deletions

View File

@ -5207,7 +5207,7 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands(
Maybe<wr::WrAnimationProperty> prop;
bool needsProp = aManager->LayerManager()->AsyncPanZoomEnabled() &&
(IsScrollThumbLayer() || IsZoomingLayer() ||
ShouldGetFixedOrStickyAnimationId() ||
ShouldGetFixedAnimationId() ||
(IsRootScrollbarContainer() && HasDynamicToolbar()));
if (needsProp) {
@ -5234,7 +5234,7 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands(
params.prim_flags |= wr::PrimitiveFlags::IS_SCROLLBAR_CONTAINER;
}
if (IsZoomingLayer() ||
(ShouldGetFixedOrStickyAnimationId() ||
(ShouldGetFixedAnimationId() ||
(IsRootScrollbarContainer() && HasDynamicToolbar()))) {
params.is_2d_scale_translation = true;
params.should_snap = true;
@ -5250,9 +5250,8 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands(
bool nsDisplayOwnLayer::UpdateScrollData(WebRenderScrollData* aData,
WebRenderLayerScrollData* aLayerData) {
bool isRelevantToApz =
(IsScrollThumbLayer() || IsScrollbarContainer() || IsZoomingLayer() ||
ShouldGetFixedOrStickyAnimationId());
bool isRelevantToApz = (IsScrollThumbLayer() || IsScrollbarContainer() ||
IsZoomingLayer() || ShouldGetFixedAnimationId());
if (!isRelevantToApz) {
return false;
@ -5267,16 +5266,11 @@ bool nsDisplayOwnLayer::UpdateScrollData(WebRenderScrollData* aData,
return true;
}
if (IsFixedPositionLayer() && ShouldGetFixedOrStickyAnimationId()) {
if (IsFixedPositionLayer() && ShouldGetFixedAnimationId()) {
aLayerData->SetFixedPositionAnimationId(mWrAnimationId);
return true;
}
if (IsStickyPositionLayer() && ShouldGetFixedOrStickyAnimationId()) {
aLayerData->SetStickyPositionAnimationId(mWrAnimationId);
return true;
}
MOZ_ASSERT(IsScrollbarContainer() || IsScrollThumbLayer());
aLayerData->SetScrollbarData(mScrollbarData);
@ -5458,7 +5452,7 @@ bool nsDisplayFixedPosition::UpdateScrollData(
return true;
}
bool nsDisplayFixedPosition::ShouldGetFixedOrStickyAnimationId() {
bool nsDisplayFixedPosition::ShouldGetFixedAnimationId() {
#if defined(MOZ_WIDGET_ANDROID)
return mFrame->PresContext()->IsRootContentDocumentCrossProcess() &&
nsLayoutUtils::ScrollIdForRootScrollFrame(mFrame->PresContext()) ==
@ -5522,7 +5516,8 @@ nsDisplayStickyPosition::nsDisplayStickyPosition(
: nsDisplayOwnLayer(aBuilder, aFrame, aList, aActiveScrolledRoot),
mContainerASR(aContainerASR),
mClippedToDisplayPort(aClippedToDisplayPort),
mShouldFlatten(false) {
mShouldFlatten(false),
mWrStickyAnimationId(0) {
MOZ_COUNT_CTOR(nsDisplayStickyPosition);
}
@ -5738,13 +5733,27 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands(
wr::LayoutVector2D applied = {
NSAppUnitsToFloatPixels(appliedOffset.x, auPerDevPixel),
NSAppUnitsToFloatPixels(appliedOffset.y, auPerDevPixel)};
bool needsProp = ShouldGetStickyAnimationId();
Maybe<wr::WrAnimationProperty> prop;
auto spatialKey = wr::SpatialKey(uint64_t(mFrame), GetPerFrameKey(),
wr::SpatialKeyKind::Sticky);
if (needsProp) {
RefPtr<WebRenderAPZAnimationData> animationData =
aManager->CommandBuilder()
.CreateOrRecycleWebRenderUserData<WebRenderAPZAnimationData>(
this);
mWrStickyAnimationId = animationData->GetAnimationId();
prop.emplace();
prop->id = mWrStickyAnimationId;
prop->key = spatialKey;
prop->effect_type = wr::WrAnimationType::Transform;
}
wr::WrSpatialId spatialId = aBuilder.DefineStickyFrame(
wr::ToLayoutRect(bounds), topMargin.ptrOr(nullptr),
rightMargin.ptrOr(nullptr), bottomMargin.ptrOr(nullptr),
leftMargin.ptrOr(nullptr), vBounds, hBounds, applied,
wr::SpatialKey(uint64_t(mFrame), GetPerFrameKey(),
wr::SpatialKeyKind::Sticky),
nullptr);
leftMargin.ptrOr(nullptr), vBounds, hBounds, applied, spatialKey,
prop.ptrOr(nullptr));
saccHelper.emplace(aBuilder, spatialId);
aManager->CommandBuilder().PushOverrideForASR(mContainerASR, spatialId);
@ -5813,6 +5822,10 @@ bool nsDisplayStickyPosition::UpdateScrollData(
->GetContent());
aLayerData->SetStickyPositionScrollContainerId(scrollId);
}
if (ShouldGetStickyAnimationId()) {
aLayerData->SetStickyPositionAnimationId(mWrStickyAnimationId);
}
}
// Return true if either there is a dynamic toolbar affecting this sticky
// item or the OwnLayer base implementation returns true for some other
@ -5822,10 +5835,11 @@ bool nsDisplayStickyPosition::UpdateScrollData(
return ret;
}
bool nsDisplayStickyPosition::ShouldGetFixedOrStickyAnimationId() {
bool nsDisplayStickyPosition::ShouldGetStickyAnimationId() const {
#if defined(MOZ_WIDGET_ANDROID)
if (HasDynamicToolbar()) { // also implies being in the cross-process RCD
StickyScrollContainer* stickyScrollContainer = GetStickyScrollContainer();
StickyScrollContainer* stickyScrollContainer =
const_cast<nsDisplayStickyPosition*>(this)->GetStickyScrollContainer();
if (stickyScrollContainer) {
ScrollableLayerGuid::ViewID scrollId =
nsLayoutUtils::FindOrCreateIDFor(stickyScrollContainer->ScrollFrame()

View File

@ -5475,7 +5475,7 @@ class nsDisplayOwnLayer : public nsDisplayWrapList {
bool IsFixedPositionLayer() const;
bool IsStickyPositionLayer() const;
bool HasDynamicToolbar() const;
virtual bool ShouldGetFixedOrStickyAnimationId() { return false; }
virtual bool ShouldGetFixedAnimationId() { return false; }
bool CreatesStackingContextHelper() override { return true; }
@ -5491,6 +5491,16 @@ class nsDisplayOwnLayer : public nsDisplayWrapList {
*/
layers::ScrollbarData mScrollbarData;
bool mForceActive;
// Used for APZ to animate this layer for purposes such as
// pinch-zooming or scrollbar thumb movement. Note that setting this
// creates a WebRender ReferenceFrame spatial node, and should only
// be used for display items that establish a Gecko reference frame
// as well (or leaf items like scrollbar thumb nodes where it does not
// matter).
// FIXME: This is currently also used for adjusting position:fixed items
// for dynamic toolbar movement. This may be a problem as position:fixed
// items do not establish Gecko reference frames.
uint64_t mWrAnimationId;
};
@ -5550,7 +5560,8 @@ class nsDisplayStickyPosition : public nsDisplayOwnLayer {
: nsDisplayOwnLayer(aBuilder, aOther),
mContainerASR(aOther.mContainerASR),
mClippedToDisplayPort(aOther.mClippedToDisplayPort),
mShouldFlatten(false) {
mShouldFlatten(false),
mWrStickyAnimationId(0) {
MOZ_COUNT_CTOR(nsDisplayStickyPosition);
}
@ -5575,7 +5586,6 @@ class nsDisplayStickyPosition : public nsDisplayOwnLayer {
bool UpdateScrollData(layers::WebRenderScrollData* aData,
layers::WebRenderLayerScrollData* aLayerData) override;
bool ShouldGetFixedOrStickyAnimationId() override;
const ActiveScrolledRoot* GetContainerASR() const { return mContainerASR; }
@ -5591,6 +5601,8 @@ class nsDisplayStickyPosition : public nsDisplayOwnLayer {
return mShouldFlatten;
}
bool ShouldGetStickyAnimationId() const;
private:
NS_DISPLAY_ALLOW_CLONING()
@ -5620,6 +5632,13 @@ class nsDisplayStickyPosition : public nsDisplayOwnLayer {
// True if this item should be flattened away.
bool mShouldFlatten;
// Used for APZ to animate the sticky element in the compositor
// for purposes such as dynamic toolbar movement and (in the future)
// overscroll-related adjustment. Unlike nsDisplayOwnLayer::mWrAnimationId,
// this does not create a WebRender ReferenceFrame, which is important
// because sticky elements do not establish Gecko reference frames either.
uint64_t mWrStickyAnimationId;
};
class nsDisplayFixedPosition : public nsDisplayOwnLayer {
@ -5661,7 +5680,7 @@ class nsDisplayFixedPosition : public nsDisplayOwnLayer {
nsDisplayListBuilder* aDisplayListBuilder) override;
bool UpdateScrollData(layers::WebRenderScrollData* aData,
layers::WebRenderLayerScrollData* aLayerData) override;
bool ShouldGetFixedOrStickyAnimationId() override;
bool ShouldGetFixedAnimationId() override;
void WriteDebugInfo(std::stringstream& aStream) override;
protected: