1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_css_AnimationCommon_h
8 #define mozilla_css_AnimationCommon_h
10 #include "mozilla/AnimationCollection.h"
11 #include "mozilla/LinkedList.h"
12 #include "mozilla/dom/Animation.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/TimingParams.h"
15 #include "mozilla/dom/Nullable.h"
16 #include "nsContentUtils.h"
17 #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
22 enum class PseudoStyleType
: uint8_t;
28 template <class AnimationType
>
29 class CommonAnimationManager
{
31 explicit CommonAnimationManager(nsPresContext
* aPresContext
)
32 : mPresContext(aPresContext
) {}
34 // NOTE: This can return null after Disconnect().
35 nsPresContext
* PresContext() const { return mPresContext
; }
38 * Notify the manager that the pres context is going away.
41 // Content nodes might outlive the transition or animation manager.
42 RemoveAllElementCollections();
44 mPresContext
= nullptr;
48 * Stop animations on the element. This method takes the real element
49 * rather than the element for the generated content for animations on
50 * ::before, ::after and ::marker.
52 void StopAnimationsForElement(dom::Element
* aElement
,
53 PseudoStyleType aPseudoType
) {
55 AnimationCollection
<AnimationType
>* collection
=
56 AnimationCollection
<AnimationType
>::GetAnimationCollection(aElement
,
62 nsAutoAnimationMutationBatch
mb(aElement
->OwnerDoc());
63 collection
->Destroy();
67 virtual ~CommonAnimationManager() {
68 MOZ_ASSERT(!mPresContext
, "Disconnect should have been called");
71 void AddElementCollection(AnimationCollection
<AnimationType
>* aCollection
) {
72 mElementCollections
.insertBack(aCollection
);
74 void RemoveAllElementCollections() {
75 while (AnimationCollection
<AnimationType
>* head
=
76 mElementCollections
.getFirst()) {
77 head
->Destroy(); // Note: this removes 'head' from mElementCollections.
81 LinkedList
<AnimationCollection
<AnimationType
>> mElementCollections
;
82 nsPresContext
* mPresContext
; // weak (non-null from ctor to Disconnect)
86 * Utility class for referencing the element that created a CSS animation or
87 * transition. It is non-owning (i.e. it uses a raw pointer) since it is only
88 * expected to be set by the owned animation while it actually being managed
89 * by the owning element.
91 * This class also abstracts the comparison of an element/pseudo-class pair
92 * for the sake of composite ordering since this logic is common to both CSS
93 * animations and transitions.
95 * (We call this OwningElementRef instead of just OwningElement so that we can
96 * call the getter on CSSAnimation/CSSTransition OwningElement() without
97 * clashing with this object's contructor.)
99 class OwningElementRef final
{
101 OwningElementRef() = default;
103 explicit OwningElementRef(const NonOwningAnimationTarget
& aTarget
)
104 : mTarget(aTarget
) {}
106 OwningElementRef(dom::Element
& aElement
, PseudoStyleType aPseudoType
)
107 : mTarget(&aElement
, aPseudoType
) {}
109 bool Equals(const OwningElementRef
& aOther
) const {
110 return mTarget
== aOther
.mTarget
;
113 bool LessThan(int32_t& aChildIndex
, const OwningElementRef
& aOther
,
114 int32_t& aOtherChildIndex
) const {
115 MOZ_ASSERT(mTarget
.mElement
&& aOther
.mTarget
.mElement
,
116 "Elements to compare should not be null");
118 if (mTarget
.mElement
!= aOther
.mTarget
.mElement
) {
119 return nsContentUtils::PositionIsBefore(mTarget
.mElement
,
120 aOther
.mTarget
.mElement
,
121 &aChildIndex
, &aOtherChildIndex
);
124 return mTarget
.mPseudoType
== PseudoStyleType::NotPseudo
||
125 (mTarget
.mPseudoType
== PseudoStyleType::before
&&
126 aOther
.mTarget
.mPseudoType
== PseudoStyleType::after
) ||
127 (mTarget
.mPseudoType
== PseudoStyleType::marker
&&
128 aOther
.mTarget
.mPseudoType
== PseudoStyleType::before
) ||
129 (mTarget
.mPseudoType
== PseudoStyleType::marker
&&
130 aOther
.mTarget
.mPseudoType
== PseudoStyleType::after
);
133 bool IsSet() const { return !!mTarget
.mElement
; }
135 void GetElement(dom::Element
*& aElement
, PseudoStyleType
& aPseudoType
) const {
136 aElement
= mTarget
.mElement
;
137 aPseudoType
= mTarget
.mPseudoType
;
140 const NonOwningAnimationTarget
& Target() const { return mTarget
; }
142 nsPresContext
* GetPresContext() const {
143 return nsContentUtils::GetContextForContent(mTarget
.mElement
);
147 NonOwningAnimationTarget mTarget
;
150 // Return the TransitionPhase or AnimationPhase to use when the animation
151 // doesn't have a target effect.
152 template <typename PhaseType
>
153 PhaseType
GetAnimationPhaseWithoutEffect(const dom::Animation
& aAnimation
) {
154 MOZ_ASSERT(!aAnimation
.GetEffect(),
155 "Should only be called when we do not have an effect");
157 dom::Nullable
<TimeDuration
> currentTime
=
158 aAnimation
.GetCurrentTimeAsDuration();
159 if (currentTime
.IsNull()) {
160 return PhaseType::Idle
;
163 // If we don't have a target effect, the duration will be zero so the phase is
164 // 'before' if the current time is less than zero.
165 return currentTime
.Value() < TimeDuration() ? PhaseType::Before
169 inline TimingParams
TimingParamsFromCSSParams(float aDuration
, float aDelay
,
170 float aIterationCount
,
171 dom::PlaybackDirection aDirection
,
172 dom::FillMode aFillMode
) {
173 MOZ_ASSERT(aIterationCount
>= 0.0 && !IsNaN(aIterationCount
),
174 "aIterations should be nonnegative & finite, as ensured by "
177 return TimingParams
{aDuration
, aDelay
, aIterationCount
, aDirection
,
181 } // namespace mozilla
183 #endif /* !defined(mozilla_css_AnimationCommon_h) */