Bug 1921553 - Use PseudoStyleRequest in AnimationCollection and TimelineCollection. r=view-transitions-reviewers,layout-reviewers,emilio

Just like what we do for EffectSet. Also, we will update
ElementAnimationData later, so for now only change the APIs of
AnimationCollection and TimelineCollection (and their callers).

Differential Revision: https://phabricator.services.mozilla.com/D228227
This commit is contained in:
Boris Chiou
2024-11-25 23:46:33 +00:00
parent dac5d98343
commit 2cacb75b9a
18 changed files with 125 additions and 115 deletions

View File

@@ -56,7 +56,8 @@ CSSTransitionCollection&
ElementAnimationData::PerElementOrPseudoData::DoEnsureTransitions( ElementAnimationData::PerElementOrPseudoData::DoEnsureTransitions(
dom::Element& aOwner, PseudoStyleType aType) { dom::Element& aOwner, PseudoStyleType aType) {
MOZ_ASSERT(!mTransitions); MOZ_ASSERT(!mTransitions);
mTransitions = MakeUnique<CSSTransitionCollection>(aOwner, aType); mTransitions =
MakeUnique<CSSTransitionCollection>(aOwner, PseudoStyleRequest(aType));
return *mTransitions; return *mTransitions;
} }
@@ -64,7 +65,8 @@ CSSAnimationCollection&
ElementAnimationData::PerElementOrPseudoData::DoEnsureAnimations( ElementAnimationData::PerElementOrPseudoData::DoEnsureAnimations(
dom::Element& aOwner, PseudoStyleType aType) { dom::Element& aOwner, PseudoStyleType aType) {
MOZ_ASSERT(!mAnimations); MOZ_ASSERT(!mAnimations);
mAnimations = MakeUnique<CSSAnimationCollection>(aOwner, aType); mAnimations =
MakeUnique<CSSAnimationCollection>(aOwner, PseudoStyleRequest(aType));
return *mAnimations; return *mAnimations;
} }
@@ -72,7 +74,8 @@ ScrollTimelineCollection&
ElementAnimationData::PerElementOrPseudoData::DoEnsureScrollTimelines( ElementAnimationData::PerElementOrPseudoData::DoEnsureScrollTimelines(
dom::Element& aOwner, PseudoStyleType aType) { dom::Element& aOwner, PseudoStyleType aType) {
MOZ_ASSERT(!mScrollTimelines); MOZ_ASSERT(!mScrollTimelines);
mScrollTimelines = MakeUnique<ScrollTimelineCollection>(aOwner, aType); mScrollTimelines =
MakeUnique<ScrollTimelineCollection>(aOwner, PseudoStyleRequest(aType));
return *mScrollTimelines; return *mScrollTimelines;
} }
@@ -80,7 +83,8 @@ ViewTimelineCollection&
ElementAnimationData::PerElementOrPseudoData::DoEnsureViewTimelines( ElementAnimationData::PerElementOrPseudoData::DoEnsureViewTimelines(
dom::Element& aOwner, PseudoStyleType aType) { dom::Element& aOwner, PseudoStyleType aType) {
MOZ_ASSERT(!mViewTimelines); MOZ_ASSERT(!mViewTimelines);
mViewTimelines = MakeUnique<ViewTimelineCollection>(aOwner, aType); mViewTimelines =
MakeUnique<ViewTimelineCollection>(aOwner, PseudoStyleRequest(aType));
return *mViewTimelines; return *mViewTimelines;
} }

View File

@@ -102,10 +102,11 @@ already_AddRefed<ScrollTimeline> ScrollTimeline::MakeAnonymous(
/* static*/ already_AddRefed<ScrollTimeline> ScrollTimeline::MakeNamed( /* static*/ already_AddRefed<ScrollTimeline> ScrollTimeline::MakeNamed(
Document* aDocument, Element* aReferenceElement, Document* aDocument, Element* aReferenceElement,
PseudoStyleType aPseudoType, const StyleScrollTimeline& aStyleTimeline) { const PseudoStyleRequest& aPseudoRequest,
const StyleScrollTimeline& aStyleTimeline) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
Scroller scroller = Scroller::Named(aReferenceElement, aPseudoType); Scroller scroller = Scroller::Named(aReferenceElement, aPseudoRequest.mType);
return MakeAndAddRef<ScrollTimeline>(aDocument, std::move(scroller), return MakeAndAddRef<ScrollTimeline>(aDocument, std::move(scroller),
aStyleTimeline.GetAxis()); aStyleTimeline.GetAxis());
} }
@@ -188,11 +189,11 @@ bool ScrollTimeline::ScrollingDirectionIsAvailable() const {
Axis()); Axis());
} }
void ScrollTimeline::ReplacePropertiesWith(const Element* aReferenceElement, void ScrollTimeline::ReplacePropertiesWith(
PseudoStyleType aPseudoType, const Element* aReferenceElement, const PseudoStyleRequest& aPseudoRequest,
const StyleScrollTimeline& aNew) { const StyleScrollTimeline& aNew) {
MOZ_ASSERT(aReferenceElement == mSource.mElement && MOZ_ASSERT(aReferenceElement == mSource.mElement &&
aPseudoType == mSource.mPseudoType); aPseudoRequest.mType == mSource.mPseudoType);
mAxis = aNew.GetAxis(); mAxis = aNew.GetAxis();
for (auto* anim = mAnimationOrder.getFirst(); anim; for (auto* anim = mAnimationOrder.getFirst(); anim;
@@ -219,8 +220,8 @@ void ScrollTimeline::RegisterWithScrollSource() {
return; return;
} }
auto& scheduler = auto& scheduler = ProgressTimelineScheduler::Ensure(
ProgressTimelineScheduler::Ensure(mSource.mElement, mSource.mPseudoType); mSource.mElement, PseudoStyleRequest(mSource.mPseudoType));
scheduler.AddTimeline(this); scheduler.AddTimeline(this);
} }
@@ -229,15 +230,16 @@ void ScrollTimeline::UnregisterFromScrollSource() {
return; return;
} }
auto* scheduler = auto* scheduler = ProgressTimelineScheduler::Get(
ProgressTimelineScheduler::Get(mSource.mElement, mSource.mPseudoType); mSource.mElement, PseudoStyleRequest(mSource.mPseudoType));
if (!scheduler) { if (!scheduler) {
return; return;
} }
scheduler->RemoveTimeline(this); scheduler->RemoveTimeline(this);
if (scheduler->IsEmpty()) { if (scheduler->IsEmpty()) {
ProgressTimelineScheduler::Destroy(mSource.mElement, mSource.mPseudoType); ProgressTimelineScheduler::Destroy(mSource.mElement,
PseudoStyleRequest(mSource.mPseudoType));
} }
} }
@@ -278,29 +280,29 @@ void ScrollTimeline::NotifyAnimationContentVisibilityChanged(
// Methods of ProgressTimelineScheduler // Methods of ProgressTimelineScheduler
// ------------------------------------ // ------------------------------------
/* static */ ProgressTimelineScheduler* ProgressTimelineScheduler::Get( /* static */ ProgressTimelineScheduler* ProgressTimelineScheduler::Get(
const Element* aElement, PseudoStyleType aPseudoType) { const Element* aElement, const PseudoStyleRequest& aPseudoRequest) {
MOZ_ASSERT(aElement); MOZ_ASSERT(aElement);
auto* data = aElement->GetAnimationData(); auto* data = aElement->GetAnimationData();
if (!data) { if (!data) {
return nullptr; return nullptr;
} }
return data->GetProgressTimelineScheduler(aPseudoType); return data->GetProgressTimelineScheduler(aPseudoRequest.mType);
} }
/* static */ ProgressTimelineScheduler& ProgressTimelineScheduler::Ensure( /* static */ ProgressTimelineScheduler& ProgressTimelineScheduler::Ensure(
Element* aElement, PseudoStyleType aPseudoType) { Element* aElement, const PseudoStyleRequest& aPseudoRequest) {
MOZ_ASSERT(aElement); MOZ_ASSERT(aElement);
return aElement->EnsureAnimationData().EnsureProgressTimelineScheduler( return aElement->EnsureAnimationData().EnsureProgressTimelineScheduler(
*aElement, aPseudoType); *aElement, aPseudoRequest.mType);
} }
/* static */ /* static */
void ProgressTimelineScheduler::Destroy(const Element* aElement, void ProgressTimelineScheduler::Destroy(
PseudoStyleType aPseudoType) { const Element* aElement, const PseudoStyleRequest& aPseudoRequest) {
auto* data = aElement->GetAnimationData(); auto* data = aElement->GetAnimationData();
MOZ_ASSERT(data); MOZ_ASSERT(data);
data->ClearProgressTimelineScheduler(aPseudoType); data->ClearProgressTimelineScheduler(aPseudoRequest.mType);
} }
} // namespace mozilla::dom } // namespace mozilla::dom

View File

@@ -120,7 +120,8 @@ class ScrollTimeline : public AnimationTimeline {
// scroll-timeline-name property. // scroll-timeline-name property.
static already_AddRefed<ScrollTimeline> MakeNamed( static already_AddRefed<ScrollTimeline> MakeNamed(
Document* aDocument, Element* aReferenceElement, Document* aDocument, Element* aReferenceElement,
PseudoStyleType aPseudoType, const StyleScrollTimeline& aStyleTimeline); const PseudoStyleRequest& aPseudoRequest,
const StyleScrollTimeline& aStyleTimeline);
bool operator==(const ScrollTimeline& aOther) const { bool operator==(const ScrollTimeline& aOther) const {
return mDocument == aOther.mDocument && mSource == aOther.mSource && return mDocument == aOther.mDocument && mSource == aOther.mSource &&
@@ -195,7 +196,7 @@ class ScrollTimeline : public AnimationTimeline {
bool ScrollingDirectionIsAvailable() const; bool ScrollingDirectionIsAvailable() const;
void ReplacePropertiesWith(const Element* aReferenceElement, void ReplacePropertiesWith(const Element* aReferenceElement,
PseudoStyleType aPseudoType, const PseudoStyleRequest& aPseudoRequest,
const StyleScrollTimeline& aNew); const StyleScrollTimeline& aNew);
void NotifyAnimationContentVisibilityChanged(Animation* aAnimation, void NotifyAnimationContentVisibilityChanged(Animation* aAnimation,
@@ -252,11 +253,12 @@ class ProgressTimelineScheduler {
ProgressTimelineScheduler() { MOZ_COUNT_CTOR(ProgressTimelineScheduler); } ProgressTimelineScheduler() { MOZ_COUNT_CTOR(ProgressTimelineScheduler); }
~ProgressTimelineScheduler() { MOZ_COUNT_DTOR(ProgressTimelineScheduler); } ~ProgressTimelineScheduler() { MOZ_COUNT_DTOR(ProgressTimelineScheduler); }
static ProgressTimelineScheduler* Get(const Element* aElement, static ProgressTimelineScheduler* Get(
PseudoStyleType aPseudoType); const Element* aElement, const PseudoStyleRequest& aPseudoRequest);
static ProgressTimelineScheduler& Ensure(Element* aElement, static ProgressTimelineScheduler& Ensure(
PseudoStyleType aPseudoType); Element* aElement, const PseudoStyleRequest& aPseudoRequest);
static void Destroy(const Element* aElement, PseudoStyleType aPseudoType); static void Destroy(const Element* aElement,
const PseudoStyleRequest& aPseudoRequest);
void AddTimeline(ScrollTimeline* aScrollTimeline) { void AddTimeline(ScrollTimeline* aScrollTimeline) {
Unused << mTimelines.put(aScrollTimeline); Unused << mTimelines.put(aScrollTimeline);

View File

@@ -18,21 +18,21 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(ViewTimeline, ScrollTimeline)
/* static */ /* static */
already_AddRefed<ViewTimeline> ViewTimeline::MakeNamed( already_AddRefed<ViewTimeline> ViewTimeline::MakeNamed(
Document* aDocument, Element* aSubject, PseudoStyleType aPseudoType, Document* aDocument, Element* aSubject,
const PseudoStyleRequest& aPseudoRequest,
const StyleViewTimeline& aStyleTimeline) { const StyleViewTimeline& aStyleTimeline) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
// 1. Lookup scroller. We have to find the nearest scroller from |aSubject| // 1. Lookup scroller. We have to find the nearest scroller from |aSubject|
// and |aPseudoType|. // and |aPseudoType|.
auto [element, pseudo] = auto [element, pseudo] = FindNearestScroller(aSubject, aPseudoRequest);
FindNearestScroller(aSubject, PseudoStyleRequest(aPseudoType));
auto scroller = auto scroller =
Scroller::Nearest(const_cast<Element*>(element), pseudo.mType); Scroller::Nearest(const_cast<Element*>(element), pseudo.mType);
// 2. Create timeline. // 2. Create timeline.
return MakeAndAddRef<ViewTimeline>(aDocument, scroller, return MakeAndAddRef<ViewTimeline>(
aStyleTimeline.GetAxis(), aSubject, aDocument, scroller, aStyleTimeline.GetAxis(), aSubject,
aPseudoType, aStyleTimeline.GetInset()); aPseudoRequest.mType, aStyleTimeline.GetInset());
} }
/* static */ /* static */
@@ -49,11 +49,11 @@ already_AddRefed<ViewTimeline> ViewTimeline::MakeAnonymous(
aTarget.mPseudoRequest.mType, aInset); aTarget.mPseudoRequest.mType, aInset);
} }
void ViewTimeline::ReplacePropertiesWith(Element* aSubjectElement, void ViewTimeline::ReplacePropertiesWith(
PseudoStyleType aPseudoType, Element* aSubjectElement, const PseudoStyleRequest& aPseudoRequest,
const StyleViewTimeline& aNew) { const StyleViewTimeline& aNew) {
mSubject = aSubjectElement; mSubject = aSubjectElement;
mSubjectPseudoType = aPseudoType; mSubjectPseudoType = aPseudoRequest.mType;
mAxis = aNew.GetAxis(); mAxis = aNew.GetAxis();
// FIXME: Bug 1817073. We assume it is a non-animatable value for now. // FIXME: Bug 1817073. We assume it is a non-animatable value for now.
mInset = aNew.GetInset(); mInset = aNew.GetInset();

View File

@@ -34,7 +34,8 @@ class ViewTimeline final : public ScrollTimeline {
// Note: |aSubject| is used as the subject which specifies view-timeline-name // Note: |aSubject| is used as the subject which specifies view-timeline-name
// property, and we use this subject to look up its nearest scroll container. // property, and we use this subject to look up its nearest scroll container.
static already_AddRefed<ViewTimeline> MakeNamed( static already_AddRefed<ViewTimeline> MakeNamed(
Document* aDocument, Element* aSubject, PseudoStyleType aPseudoType, Document* aDocument, Element* aSubject,
const PseudoStyleRequest& aPseudoRequest,
const StyleViewTimeline& aStyleTimeline); const StyleViewTimeline& aStyleTimeline);
static already_AddRefed<ViewTimeline> MakeAnonymous( static already_AddRefed<ViewTimeline> MakeAnonymous(
@@ -49,7 +50,7 @@ class ViewTimeline final : public ScrollTimeline {
bool IsViewTimeline() const override { return true; } bool IsViewTimeline() const override { return true; }
void ReplacePropertiesWith(Element* aSubjectElement, void ReplacePropertiesWith(Element* aSubjectElement,
PseudoStyleType aPseudoType, const PseudoStyleRequest& aPseudoRequest,
const StyleViewTimeline& aNew); const StyleViewTimeline& aNew);
private: private:

View File

@@ -2106,8 +2106,8 @@ void RestyleManager::AnimationsWithDestroyedFrame ::StopAnimationsWithoutFrame(
// FIXME: Bug 1922095. Revisit here to make sure we destroy the view // FIXME: Bug 1922095. Revisit here to make sure we destroy the view
// transitions if the associated frames are destroyed. // transitions if the associated frames are destroyed.
animationManager->StopAnimationsForElement(element, aPseudoRequest.mType); animationManager->StopAnimationsForElement(element, aPseudoRequest);
transitionManager->StopAnimationsForElement(element, aPseudoRequest.mType); transitionManager->StopAnimationsForElement(element, aPseudoRequest);
// All other animations should keep running but not running on the // All other animations should keep running but not running on the
// *compositor* at this point. // *compositor* at this point.

View File

@@ -8065,12 +8065,9 @@ void ScrollContainerFrame::ScheduleScrollAnimations() {
return; return;
} }
// TODO: We will tweak ProgressTimelineScheduler::Get() to handle
// PseudoStyleRequest better in the following patches.
const auto [element, request] = const auto [element, request] =
AnimationUtils::GetElementPseudoPair(elementOrPseudo); AnimationUtils::GetElementPseudoPair(elementOrPseudo);
const auto* scheduler = const auto* scheduler = ProgressTimelineScheduler::Get(element, request);
ProgressTimelineScheduler::Get(element, request.mType);
if (!scheduler) { if (!scheduler) {
// We don't have scroll timelines associated with this frame. // We don't have scroll timelines associated with this frame.
return; return;

View File

@@ -37,25 +37,25 @@ void AnimationCollection<AnimationType>::Destroy() {
auto* data = mElement.GetAnimationData(); auto* data = mElement.GetAnimationData();
MOZ_ASSERT(data); MOZ_ASSERT(data);
if constexpr (std::is_same_v<AnimationType, dom::CSSAnimation>) { if constexpr (std::is_same_v<AnimationType, dom::CSSAnimation>) {
MOZ_ASSERT(data->GetAnimationCollection(mPseudo) == this); MOZ_ASSERT(data->GetAnimationCollection(mPseudo.mType) == this);
data->ClearAnimationCollectionFor(mPseudo); data->ClearAnimationCollectionFor(mPseudo.mType);
} else { } else {
MOZ_ASSERT(data->GetTransitionCollection(mPseudo) == this); MOZ_ASSERT(data->GetTransitionCollection(mPseudo.mType) == this);
data->ClearTransitionCollectionFor(mPseudo); data->ClearTransitionCollectionFor(mPseudo.mType);
} }
} }
template <class AnimationType> template <class AnimationType>
AnimationCollection<AnimationType>* AnimationCollection<AnimationType>::Get( AnimationCollection<AnimationType>* AnimationCollection<AnimationType>::Get(
const dom::Element* aElement, const PseudoStyleType aType) { const dom::Element* aElement, const PseudoStyleRequest& aRequest) {
auto* data = aElement->GetAnimationData(); auto* data = aElement->GetAnimationData();
if (!data) { if (!data) {
return nullptr; return nullptr;
} }
if constexpr (std::is_same_v<AnimationType, dom::CSSAnimation>) { if constexpr (std::is_same_v<AnimationType, dom::CSSAnimation>) {
return data->GetAnimationCollection(aType); return data->GetAnimationCollection(aRequest.mType);
} else { } else {
return data->GetTransitionCollection(aType); return data->GetTransitionCollection(aRequest.mType);
} }
} }
@@ -68,7 +68,7 @@ AnimationCollection<AnimationType>::Get(const nsIFrame* aFrame) {
return nullptr; return nullptr;
} }
return Get(target->mElement, target->mPseudoRequest.mType); return Get(target->mElement, target->mPseudoRequest);
} }
// Explicit class instantiations // Explicit class instantiations

View File

@@ -9,6 +9,7 @@
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/LinkedList.h" #include "mozilla/LinkedList.h"
#include "mozilla/PseudoStyleType.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "nsCSSPseudoElements.h" #include "nsCSSPseudoElements.h"
#include "nsTArrayForwardDeclare.h" #include "nsTArrayForwardDeclare.h"
@@ -21,7 +22,6 @@ namespace mozilla {
namespace dom { namespace dom {
class Element; class Element;
} }
enum class PseudoStyleType : uint8_t;
template <class AnimationType> template <class AnimationType>
class AnimationCollection class AnimationCollection
@@ -29,8 +29,9 @@ class AnimationCollection
typedef AnimationCollection<AnimationType> SelfType; typedef AnimationCollection<AnimationType> SelfType;
public: public:
AnimationCollection(dom::Element& aOwner, PseudoStyleType aPseudoType) AnimationCollection(dom::Element& aOwner,
: mElement(aOwner), mPseudo(aPseudoType) { const PseudoStyleRequest& aPseudoRequest)
: mElement(aOwner), mPseudo(aPseudoRequest) {
MOZ_COUNT_CTOR(AnimationCollection); MOZ_COUNT_CTOR(AnimationCollection);
} }
@@ -44,13 +45,13 @@ class AnimationCollection
// animations. // animations.
static AnimationCollection* Get(const nsIFrame* aFrame); static AnimationCollection* Get(const nsIFrame* aFrame);
static AnimationCollection* Get(const dom::Element* aElement, static AnimationCollection* Get(const dom::Element* aElement,
PseudoStyleType aPseudoType); const PseudoStyleRequest& aPseudoRequest);
// The element. Weak reference is fine since it owns us. // The element. Weak reference is fine since it owns us.
// FIXME(emilio): These are only needed for Destroy(), so maybe remove and // FIXME(emilio): These are only needed for Destroy(), so maybe remove and
// rely on the caller clearing us properly? // rely on the caller clearing us properly?
dom::Element& mElement; dom::Element& mElement;
const PseudoStyleType mPseudo; const PseudoStyleRequest mPseudo;
nsTArray<RefPtr<AnimationType>> mAnimations; nsTArray<RefPtr<AnimationType>> mAnimations;

View File

@@ -52,10 +52,10 @@ class CommonAnimationManager {
* ::before, ::after and ::marker. * ::before, ::after and ::marker.
*/ */
void StopAnimationsForElement(dom::Element* aElement, void StopAnimationsForElement(dom::Element* aElement,
PseudoStyleType aPseudoType) { const PseudoStyleRequest& aPseudoRequest) {
MOZ_ASSERT(aElement); MOZ_ASSERT(aElement);
auto* collection = auto* collection =
AnimationCollection<AnimationType>::Get(aElement, aPseudoType); AnimationCollection<AnimationType>::Get(aElement, aPseudoRequest);
if (!collection) { if (!collection) {
return; return;
} }

View File

@@ -542,19 +542,19 @@ void Gecko_UpdateAnimations(const Element* aElement,
// timeline defined by itself. // timeline defined by itself.
if (aTasks & UpdateAnimationsTasks::ScrollTimelines) { if (aTasks & UpdateAnimationsTasks::ScrollTimelines) {
presContext->TimelineManager()->UpdateTimelines( presContext->TimelineManager()->UpdateTimelines(
const_cast<Element*>(element), pseudoRequest.mType, aComputedData, const_cast<Element*>(element), pseudoRequest, aComputedData,
TimelineManager::ProgressTimelineType::Scroll); TimelineManager::ProgressTimelineType::Scroll);
} }
if (aTasks & UpdateAnimationsTasks::ViewTimelines) { if (aTasks & UpdateAnimationsTasks::ViewTimelines) {
presContext->TimelineManager()->UpdateTimelines( presContext->TimelineManager()->UpdateTimelines(
const_cast<Element*>(element), pseudoRequest.mType, aComputedData, const_cast<Element*>(element), pseudoRequest, aComputedData,
TimelineManager::ProgressTimelineType::View); TimelineManager::ProgressTimelineType::View);
} }
if (aTasks & UpdateAnimationsTasks::CSSAnimations) { if (aTasks & UpdateAnimationsTasks::CSSAnimations) {
presContext->AnimationManager()->UpdateAnimations( presContext->AnimationManager()->UpdateAnimations(
const_cast<Element*>(element), pseudoRequest.mType, aComputedData); const_cast<Element*>(element), pseudoRequest, aComputedData);
} }
// aComputedData might be nullptr if the target element is now in a // aComputedData might be nullptr if the target element is now in a
@@ -619,21 +619,21 @@ bool Gecko_ElementHasAnimations(const Element* aElement) {
bool Gecko_ElementHasCSSAnimations(const Element* aElement) { bool Gecko_ElementHasCSSAnimations(const Element* aElement) {
const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement); const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
auto* collection = auto* collection =
nsAnimationManager::CSSAnimationCollection::Get(element, pseudo.mType); nsAnimationManager::CSSAnimationCollection::Get(element, pseudo);
return collection && !collection->mAnimations.IsEmpty(); return collection && !collection->mAnimations.IsEmpty();
} }
bool Gecko_ElementHasCSSTransitions(const Element* aElement) { bool Gecko_ElementHasCSSTransitions(const Element* aElement) {
const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement); const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
auto* collection = auto* collection =
nsTransitionManager::CSSTransitionCollection::Get(element, pseudo.mType); nsTransitionManager::CSSTransitionCollection::Get(element, pseudo);
return collection && !collection->mAnimations.IsEmpty(); return collection && !collection->mAnimations.IsEmpty();
} }
size_t Gecko_ElementTransitions_Length(const Element* aElement) { size_t Gecko_ElementTransitions_Length(const Element* aElement) {
const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement); const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
auto* collection = auto* collection =
nsTransitionManager::CSSTransitionCollection::Get(element, pseudo.mType); nsTransitionManager::CSSTransitionCollection::Get(element, pseudo);
return collection ? collection->mAnimations.Length() : 0; return collection ? collection->mAnimations.Length() : 0;
} }
@@ -641,7 +641,7 @@ static CSSTransition* GetCurrentTransitionAt(const Element* aElement,
size_t aIndex) { size_t aIndex) {
const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement); const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
auto* collection = auto* collection =
nsTransitionManager::CSSTransitionCollection ::Get(element, pseudo.mType); nsTransitionManager::CSSTransitionCollection ::Get(element, pseudo);
if (!collection) { if (!collection) {
return nullptr; return nullptr;
} }

View File

@@ -29,11 +29,11 @@ void TimelineCollection<TimelineType>::Destroy() {
auto* data = mElement.GetAnimationData(); auto* data = mElement.GetAnimationData();
MOZ_ASSERT(data); MOZ_ASSERT(data);
if constexpr (std::is_same_v<TimelineType, dom::ScrollTimeline>) { if constexpr (std::is_same_v<TimelineType, dom::ScrollTimeline>) {
MOZ_ASSERT(data->GetScrollTimelineCollection(mPseudo) == this); MOZ_ASSERT(data->GetScrollTimelineCollection(mPseudo.mType) == this);
data->ClearScrollTimelineCollectionFor(mPseudo); data->ClearScrollTimelineCollectionFor(mPseudo.mType);
} else if constexpr (std::is_same_v<TimelineType, dom::ViewTimeline>) { } else if constexpr (std::is_same_v<TimelineType, dom::ViewTimeline>) {
MOZ_ASSERT(data->GetViewTimelineCollection(mPseudo) == this); MOZ_ASSERT(data->GetViewTimelineCollection(mPseudo.mType) == this);
data->ClearViewTimelineCollectionFor(mPseudo); data->ClearViewTimelineCollectionFor(mPseudo.mType);
} else { } else {
MOZ_ASSERT_UNREACHABLE("Unsupported TimelienType"); MOZ_ASSERT_UNREACHABLE("Unsupported TimelienType");
} }
@@ -41,8 +41,8 @@ void TimelineCollection<TimelineType>::Destroy() {
template <class TimelineType> template <class TimelineType>
/* static */ TimelineCollection<TimelineType>* /* static */ TimelineCollection<TimelineType>*
TimelineCollection<TimelineType>::Get(const dom::Element* aElement, TimelineCollection<TimelineType>::Get(
const PseudoStyleType aPseudoType) { const dom::Element* aElement, const PseudoStyleRequest& aPseudoRequest) {
MOZ_ASSERT(aElement); MOZ_ASSERT(aElement);
auto* data = aElement->GetAnimationData(); auto* data = aElement->GetAnimationData();
if (!data) { if (!data) {
@@ -50,11 +50,11 @@ TimelineCollection<TimelineType>::Get(const dom::Element* aElement,
} }
if constexpr (std::is_same_v<TimelineType, dom::ScrollTimeline>) { if constexpr (std::is_same_v<TimelineType, dom::ScrollTimeline>) {
return data->GetScrollTimelineCollection(aPseudoType); return data->GetScrollTimelineCollection(aPseudoRequest.mType);
} }
if constexpr (std::is_same_v<TimelineType, dom::ViewTimeline>) { if constexpr (std::is_same_v<TimelineType, dom::ViewTimeline>) {
return data->GetViewTimelineCollection(aPseudoType); return data->GetViewTimelineCollection(aPseudoRequest.mType);
} }
return nullptr; return nullptr;

View File

@@ -10,6 +10,7 @@
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/LinkedList.h" #include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/PseudoStyleType.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "nsAtomHashKeys.h" #include "nsAtomHashKeys.h"
#include "nsTHashMap.h" #include "nsTHashMap.h"
@@ -20,7 +21,6 @@ namespace mozilla {
namespace dom { namespace dom {
class Element; class Element;
} }
enum class PseudoStyleType : uint8_t;
// The collection of ScrollTimeline or ViewTimeline. We use the template class // The collection of ScrollTimeline or ViewTimeline. We use the template class
// to share the implementation for these two timeline types. // to share the implementation for these two timeline types.
@@ -31,8 +31,9 @@ class TimelineCollection final
using SelfType = TimelineCollection<TimelineType>; using SelfType = TimelineCollection<TimelineType>;
using TimelineMap = nsTHashMap<RefPtr<nsAtom>, RefPtr<TimelineType>>; using TimelineMap = nsTHashMap<RefPtr<nsAtom>, RefPtr<TimelineType>>;
TimelineCollection(dom::Element& aElement, PseudoStyleType aPseudoType) TimelineCollection(dom::Element& aElement,
: mElement(aElement), mPseudo(aPseudoType) { const PseudoStyleRequest& aPseudoRequest)
: mElement(aElement), mPseudo(aPseudoRequest) {
MOZ_COUNT_CTOR(TimelineCollection); MOZ_COUNT_CTOR(TimelineCollection);
} }
@@ -54,13 +55,13 @@ class TimelineCollection final
// Get the collection of timelines for the given |aElement| and or create it // Get the collection of timelines for the given |aElement| and or create it
// if it does not already exist. // if it does not already exist.
static TimelineCollection* Get(const dom::Element* aElement, static TimelineCollection* Get(const dom::Element* aElement,
PseudoStyleType aPseudoType); const PseudoStyleRequest& aPseudoRequest);
const TimelineMap& Timelines() const { return mTimelines; } const TimelineMap& Timelines() const { return mTimelines; }
private: private:
// The element. Weak reference is fine since it owns us. // The element. Weak reference is fine since it owns us.
dom::Element& mElement; dom::Element& mElement;
const PseudoStyleType mPseudo; const PseudoStyleRequest mPseudo;
TimelineMap mTimelines; TimelineMap mTimelines;
}; };

View File

@@ -18,9 +18,10 @@ using dom::ScrollTimeline;
using dom::ViewTimeline; using dom::ViewTimeline;
template <typename TimelineType> template <typename TimelineType>
void TryDestroyTimeline(Element* aElement, PseudoStyleType aPseudoType) { static void TryDestroyTimeline(Element* aElement,
const PseudoStyleRequest& aPseudoRequest) {
auto* collection = auto* collection =
TimelineCollection<TimelineType>::Get(aElement, aPseudoType); TimelineCollection<TimelineType>::Get(aElement, aPseudoRequest);
if (!collection) { if (!collection) {
return; return;
} }
@@ -28,7 +29,7 @@ void TryDestroyTimeline(Element* aElement, PseudoStyleType aPseudoType) {
} }
void TimelineManager::UpdateTimelines(Element* aElement, void TimelineManager::UpdateTimelines(Element* aElement,
PseudoStyleType aPseudoType, const PseudoStyleRequest& aPseudoRequest,
const ComputedStyle* aComputedStyle, const ComputedStyle* aComputedStyle,
ProgressTimelineType aType) { ProgressTimelineType aType) {
MOZ_ASSERT( MOZ_ASSERT(
@@ -46,22 +47,22 @@ void TimelineManager::UpdateTimelines(Element* aElement,
switch (aType) { switch (aType) {
case ProgressTimelineType::Scroll: case ProgressTimelineType::Scroll:
if (shouldDestroyTimelines) { if (shouldDestroyTimelines) {
TryDestroyTimeline<ScrollTimeline>(aElement, aPseudoType); TryDestroyTimeline<ScrollTimeline>(aElement, aPseudoRequest);
return; return;
} }
DoUpdateTimelines<StyleScrollTimeline, ScrollTimeline>( DoUpdateTimelines<StyleScrollTimeline, ScrollTimeline>(
mPresContext, aElement, aPseudoType, mPresContext, aElement, aPseudoRequest,
aComputedStyle->StyleUIReset()->mScrollTimelines, aComputedStyle->StyleUIReset()->mScrollTimelines,
aComputedStyle->StyleUIReset()->mScrollTimelineNameCount); aComputedStyle->StyleUIReset()->mScrollTimelineNameCount);
break; break;
case ProgressTimelineType::View: case ProgressTimelineType::View:
if (shouldDestroyTimelines) { if (shouldDestroyTimelines) {
TryDestroyTimeline<ViewTimeline>(aElement, aPseudoType); TryDestroyTimeline<ViewTimeline>(aElement, aPseudoRequest);
return; return;
} }
DoUpdateTimelines<StyleViewTimeline, ViewTimeline>( DoUpdateTimelines<StyleViewTimeline, ViewTimeline>(
mPresContext, aElement, aPseudoType, mPresContext, aElement, aPseudoRequest,
aComputedStyle->StyleUIReset()->mViewTimelines, aComputedStyle->StyleUIReset()->mViewTimelines,
aComputedStyle->StyleUIReset()->mViewTimelineNameCount); aComputedStyle->StyleUIReset()->mViewTimelineNameCount);
break; break;
@@ -79,7 +80,7 @@ static already_AddRefed<TimelineType> PopExistingTimeline(
template <typename StyleType, typename TimelineType> template <typename StyleType, typename TimelineType>
static auto BuildTimelines(nsPresContext* aPresContext, Element* aElement, static auto BuildTimelines(nsPresContext* aPresContext, Element* aElement,
PseudoStyleType aPseudoType, const PseudoStyleRequest& aPseudoRequest,
const nsStyleAutoArray<StyleType>& aTimelines, const nsStyleAutoArray<StyleType>& aTimelines,
size_t aTimelineCount, size_t aTimelineCount,
TimelineCollection<TimelineType>* aCollection) { TimelineCollection<TimelineType>* aCollection) {
@@ -97,10 +98,10 @@ static auto BuildTimelines(nsPresContext* aPresContext, Element* aElement,
RefPtr<TimelineType> dest = RefPtr<TimelineType> dest =
PopExistingTimeline(timeline.GetName(), aCollection); PopExistingTimeline(timeline.GetName(), aCollection);
if (dest) { if (dest) {
dest->ReplacePropertiesWith(aElement, aPseudoType, timeline); dest->ReplacePropertiesWith(aElement, aPseudoRequest, timeline);
} else { } else {
dest = TimelineType::MakeNamed(aPresContext->Document(), aElement, dest = TimelineType::MakeNamed(aPresContext->Document(), aElement,
aPseudoType, timeline); aPseudoRequest, timeline);
} }
MOZ_ASSERT(dest); MOZ_ASSERT(dest);
@@ -130,10 +131,11 @@ ViewTimelineCollection& EnsureTimelineCollection<ViewTimeline>(
template <typename StyleType, typename TimelineType> template <typename StyleType, typename TimelineType>
void TimelineManager::DoUpdateTimelines( void TimelineManager::DoUpdateTimelines(
nsPresContext* aPresContext, Element* aElement, PseudoStyleType aPseudoType, nsPresContext* aPresContext, Element* aElement,
const PseudoStyleRequest& aPseudoRequest,
const nsStyleAutoArray<StyleType>& aStyleTimelines, size_t aTimelineCount) { const nsStyleAutoArray<StyleType>& aStyleTimelines, size_t aTimelineCount) {
auto* collection = auto* collection =
TimelineCollection<TimelineType>::Get(aElement, aPseudoType); TimelineCollection<TimelineType>::Get(aElement, aPseudoRequest);
if (!collection && aTimelineCount == 1 && if (!collection && aTimelineCount == 1 &&
aStyleTimelines[0].GetName() == nsGkAtoms::_empty) { aStyleTimelines[0].GetName() == nsGkAtoms::_empty) {
return; return;
@@ -142,7 +144,7 @@ void TimelineManager::DoUpdateTimelines(
// We create a new timeline list based on its computed style and the existing // We create a new timeline list based on its computed style and the existing
// timelines. // timelines.
auto newTimelines = BuildTimelines<StyleType, TimelineType>( auto newTimelines = BuildTimelines<StyleType, TimelineType>(
aPresContext, aElement, aPseudoType, aStyleTimelines, aTimelineCount, aPresContext, aElement, aPseudoRequest, aStyleTimelines, aTimelineCount,
collection); collection);
if (newTimelines.IsEmpty()) { if (newTimelines.IsEmpty()) {
@@ -153,8 +155,8 @@ void TimelineManager::DoUpdateTimelines(
} }
if (!collection) { if (!collection) {
collection = collection = &EnsureTimelineCollection<TimelineType>(*aElement,
&EnsureTimelineCollection<TimelineType>(*aElement, aPseudoType); aPseudoRequest.mType);
if (!collection->isInList()) { if (!collection->isInList()) {
AddTimelineCollection(collection); AddTimelineCollection(collection);
} }

View File

@@ -15,7 +15,7 @@ class nsPresContext;
namespace mozilla { namespace mozilla {
class ComputedStyle; class ComputedStyle;
enum class PseudoStyleType : uint8_t; struct PseudoStyleRequest;
namespace dom { namespace dom {
class Element; class Element;
@@ -47,7 +47,8 @@ class TimelineManager {
Scroll, Scroll,
View, View,
}; };
void UpdateTimelines(dom::Element* aElement, PseudoStyleType aPseudoType, void UpdateTimelines(dom::Element* aElement,
const PseudoStyleRequest& aPseudoRequest,
const ComputedStyle* aComputedStyle, const ComputedStyle* aComputedStyle,
ProgressTimelineType aType); ProgressTimelineType aType);
@@ -56,7 +57,7 @@ class TimelineManager {
private: private:
template <typename StyleType, typename TimelineType> template <typename StyleType, typename TimelineType>
void DoUpdateTimelines(nsPresContext* aPresContext, dom::Element* aElement, void DoUpdateTimelines(nsPresContext* aPresContext, dom::Element* aElement,
PseudoStyleType aPseudoType, const PseudoStyleRequest& aPseudoRequest,
const nsStyleAutoArray<StyleType>& aStyleTimelines, const nsStyleAutoArray<StyleType>& aStyleTimelines,
size_t aTimelineCount); size_t aTimelineCount);

View File

@@ -230,17 +230,15 @@ static already_AddRefed<dom::AnimationTimeline> GetNamedProgressTimeline(
// In case of a name conflict on the same element, scroll progress // In case of a name conflict on the same element, scroll progress
// timelines take precedence over view progress timelines. // timelines take precedence over view progress timelines.
const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(e); const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(e);
// TODO: Tweak TimelineCollection to handle PseudoStyleRequest well in the
// following patches.
if (auto* collection = if (auto* collection =
TimelineCollection<ScrollTimeline>::Get(element, pseudo.mType)) { TimelineCollection<ScrollTimeline>::Get(element, pseudo)) {
if (RefPtr<ScrollTimeline> timeline = collection->Lookup(aName)) { if (RefPtr<ScrollTimeline> timeline = collection->Lookup(aName)) {
return timeline.forget(); return timeline.forget();
} }
} }
if (auto* collection = if (auto* collection =
TimelineCollection<ViewTimeline>::Get(element, pseudo.mType)) { TimelineCollection<ViewTimeline>::Get(element, pseudo)) {
if (RefPtr<ViewTimeline> timeline = collection->Lookup(aName)) { if (RefPtr<ViewTimeline> timeline = collection->Lookup(aName)) {
return timeline.forget(); return timeline.forget();
} }
@@ -394,9 +392,9 @@ static nsAnimationManager::OwningCSSAnimationPtrArray BuildAnimations(
return result; return result;
} }
void nsAnimationManager::UpdateAnimations(dom::Element* aElement, void nsAnimationManager::UpdateAnimations(
PseudoStyleType aPseudoType, dom::Element* aElement, const PseudoStyleRequest& aPseudoRequest,
const ComputedStyle* aComputedStyle) { const ComputedStyle* aComputedStyle) {
MOZ_ASSERT(mPresContext->IsDynamic(), MOZ_ASSERT(mPresContext->IsDynamic(),
"Should not update animations for print or print preview"); "Should not update animations for print or print preview");
MOZ_ASSERT(aElement->IsInComposedDoc(), MOZ_ASSERT(aElement->IsInComposedDoc(),
@@ -411,11 +409,11 @@ void nsAnimationManager::UpdateAnimations(dom::Element* aElement,
// In either case, since CSS animations should not run in display:none // In either case, since CSS animations should not run in display:none
// subtrees we should stop (actually, destroy) any animations on this // subtrees we should stop (actually, destroy) any animations on this
// element here. // element here.
StopAnimationsForElement(aElement, aPseudoType); StopAnimationsForElement(aElement, aPseudoRequest);
return; return;
} }
NonOwningAnimationTarget target(aElement, PseudoStyleRequest(aPseudoType)); NonOwningAnimationTarget target(aElement, aPseudoRequest);
ServoCSSAnimationBuilder builder(aComputedStyle); ServoCSSAnimationBuilder builder(aComputedStyle);
DoUpdateAnimations(target, *aComputedStyle->StyleUIReset(), builder); DoUpdateAnimations(target, *aComputedStyle->StyleUIReset(), builder);
@@ -429,8 +427,8 @@ void nsAnimationManager::DoUpdateAnimations(
// Likewise, when we initially construct frames, we're not in a // Likewise, when we initially construct frames, we're not in a
// style change, but also not in an animation restyle. // style change, but also not in an animation restyle.
auto* collection = CSSAnimationCollection::Get(aTarget.mElement, auto* collection =
aTarget.mPseudoRequest.mType); CSSAnimationCollection::Get(aTarget.mElement, aTarget.mPseudoRequest);
if (!collection && aStyle.mAnimationNameCount == 1 && if (!collection && aStyle.mAnimationNameCount == 1 &&
aStyle.mAnimations[0].GetName() == nsGkAtoms::_empty) { aStyle.mAnimations[0].GetName() == nsGkAtoms::_empty) {
return; return;

View File

@@ -21,8 +21,8 @@ struct nsStyleUIReset;
namespace mozilla { namespace mozilla {
class ComputedStyle; class ComputedStyle;
enum class PseudoStyleType : uint8_t;
struct NonOwningAnimationTarget; struct NonOwningAnimationTarget;
struct PseudoStyleRequest;
} /* namespace mozilla */ } /* namespace mozilla */
@@ -45,7 +45,7 @@ class nsAnimationManager final
* but with servo's computed values. * but with servo's computed values.
*/ */
void UpdateAnimations(mozilla::dom::Element* aElement, void UpdateAnimations(mozilla::dom::Element* aElement,
mozilla::PseudoStyleType aPseudoType, const mozilla::PseudoStyleRequest& aPseudoRequest,
const mozilla::ComputedStyle* aComputedValues); const mozilla::ComputedStyle* aComputedValues);
// Utility function to walk through |aIter| to find the Keyframe with // Utility function to walk through |aIter| to find the Keyframe with

View File

@@ -49,11 +49,12 @@ bool nsTransitionManager::UpdateTransitions(dom::Element* aElement,
MOZ_ASSERT(mPresContext->IsDynamic()); MOZ_ASSERT(mPresContext->IsDynamic());
if (aNewStyle.StyleDisplay()->mDisplay == StyleDisplay::None) { if (aNewStyle.StyleDisplay()->mDisplay == StyleDisplay::None) {
StopAnimationsForElement(aElement, aPseudoType); StopAnimationsForElement(aElement, PseudoStyleRequest(aPseudoType));
return false; return false;
} }
auto* collection = CSSTransitionCollection::Get(aElement, aPseudoType); auto* collection =
CSSTransitionCollection::Get(aElement, PseudoStyleRequest(aPseudoType));
return DoUpdateTransitions(*aNewStyle.StyleUIReset(), aElement, aPseudoType, return DoUpdateTransitions(*aNewStyle.StyleUIReset(), aElement, aPseudoType,
collection, aOldStyle, aNewStyle); collection, aOldStyle, aNewStyle);
} }