Bug 1910248 - Remove nsIFrame::LayerIsPrerenderedDataKey r=layout-reviewers,TYLin
[gecko.git] / dom / animation / CSSAnimation.h
blob742a554c677a0e085298246a4919b73916aa4105
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_dom_CSSAnimation_h
8 #define mozilla_dom_CSSAnimation_h
10 #include "mozilla/dom/Animation.h"
11 #include "mozilla/dom/KeyframeEffect.h"
12 #include "mozilla/dom/MutationObservers.h"
13 #include "mozilla/StyleAnimationValue.h"
14 #include "AnimationCommon.h"
16 namespace mozilla {
17 // Properties of CSS Animations that can be overridden by the Web Animations API
18 // in a manner that means we should ignore subsequent changes to markup for that
19 // property.
20 enum class CSSAnimationProperties {
21 None = 0,
22 Keyframes = 1 << 0,
23 Duration = 1 << 1,
24 IterationCount = 1 << 2,
25 Direction = 1 << 3,
26 Delay = 1 << 4,
27 FillMode = 1 << 5,
28 Composition = 1 << 6,
29 Effect = Keyframes | Duration | IterationCount | Direction | Delay |
30 FillMode | Composition,
31 PlayState = 1 << 7,
33 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CSSAnimationProperties)
35 namespace dom {
37 class CSSAnimation final : public Animation {
38 public:
39 explicit CSSAnimation(nsIGlobalObject* aGlobal, nsAtom* aAnimationName)
40 : dom::Animation(aGlobal),
41 mAnimationName(aAnimationName),
42 mNeedsNewAnimationIndexWhenRun(false),
43 mPreviousPhase(ComputedTiming::AnimationPhase::Idle),
44 mPreviousIteration(0) {
45 // We might need to drop this assertion once we add a script-accessible
46 // constructor but for animations generated from CSS markup the
47 // animation-name should never be empty.
48 MOZ_ASSERT(mAnimationName != nsGkAtoms::_empty,
49 "animation-name should not be 'none'");
52 JSObject* WrapObject(JSContext* aCx,
53 JS::Handle<JSObject*> aGivenProto) override;
55 CSSAnimation* AsCSSAnimation() override { return this; }
56 const CSSAnimation* AsCSSAnimation() const override { return this; }
58 // CSSAnimation interface
59 void GetAnimationName(nsString& aRetVal) const {
60 mAnimationName->ToString(aRetVal);
63 nsAtom* AnimationName() const { return mAnimationName; }
65 // Animation interface overrides
66 void SetEffect(AnimationEffect* aEffect) override;
67 void SetStartTimeAsDouble(const Nullable<double>& aStartTime) override;
68 Promise* GetReady(ErrorResult& aRv) override;
69 void Reverse(ErrorResult& aRv) override;
71 // NOTE: tabbrowser.xml currently relies on the fact that reading the
72 // currentTime of a CSSAnimation does *not* flush style (whereas reading the
73 // playState does). If CSS Animations 2 specifies that reading currentTime
74 // also flushes style we will need to find another way to detect canceled
75 // animations in tabbrowser.xml. On the other hand, if CSS Animations 2
76 // specifies that reading playState does *not* flush style (and we drop the
77 // following override), then we should update tabbrowser.xml to check
78 // the playState instead.
79 AnimationPlayState PlayStateFromJS() const override;
80 bool PendingFromJS() const override;
81 void PlayFromJS(ErrorResult& aRv) override;
82 void PauseFromJS(ErrorResult& aRv) override;
84 void PlayFromStyle();
85 void PauseFromStyle();
86 void CancelFromStyle(PostRestyleMode aPostRestyle) {
87 // When an animation is disassociated with style it enters an odd state
88 // where its composite order is undefined until it first transitions
89 // out of the idle state.
91 // Even if the composite order isn't defined we don't want it to be random
92 // in case we need to determine the order to dispatch events associated
93 // with an animation in this state. To solve this we treat the animation as
94 // if it had been added to the end of the global animation list so that
95 // its sort order is defined. We'll update this index again once the
96 // animation leaves the idle state.
97 mAnimationIndex = sNextAnimationIndex++;
98 mNeedsNewAnimationIndexWhenRun = true;
100 Animation::Cancel(aPostRestyle);
102 // We need to do this *after* calling Cancel() since
103 // Cancel() might synchronously trigger a cancel event for which
104 // we need an owning element to target the event at.
105 mOwningElement = OwningElementRef();
108 void Tick(TickState&) override;
109 void QueueEvents(
110 const StickyTimeDuration& aActiveTime = StickyTimeDuration());
112 bool HasLowerCompositeOrderThan(const CSSAnimation& aOther) const;
114 void SetAnimationIndex(uint64_t aIndex) {
115 MOZ_ASSERT(IsTiedToMarkup());
116 if (IsRelevant() && mAnimationIndex != aIndex) {
117 MutationObservers::NotifyAnimationChanged(this);
118 PostUpdate();
120 mAnimationIndex = aIndex;
123 // Sets the owning element which is used for determining the composite
124 // order of CSSAnimation objects generated from CSS markup.
126 // @see mOwningElement
127 void SetOwningElement(const OwningElementRef& aElement) {
128 mOwningElement = aElement;
130 // True for animations that are generated from CSS markup and continue to
131 // reflect changes to that markup.
132 bool IsTiedToMarkup() const { return mOwningElement.IsSet(); }
134 void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) override {
135 QueueEvents(aActiveTime);
138 CSSAnimationProperties GetOverriddenProperties() const {
139 return mOverriddenProperties;
141 void AddOverriddenProperties(CSSAnimationProperties aProperties) {
142 mOverriddenProperties |= aProperties;
145 protected:
146 virtual ~CSSAnimation() {
147 MOZ_ASSERT(!mOwningElement.IsSet(),
148 "Owning element should be cleared "
149 "before a CSS animation is destroyed");
152 // Animation overrides
153 void UpdateTiming(SeekFlag aSeekFlag,
154 SyncNotifyFlag aSyncNotifyFlag) override;
156 // Returns the duration from the start of the animation's source effect's
157 // active interval to the point where the animation actually begins playback.
158 // This is zero unless the animation's source effect has a negative delay in
159 // which case it is the absolute value of that delay.
160 // This is used for setting the elapsedTime member of CSS AnimationEvents.
161 TimeDuration InitialAdvance() const {
162 return mEffect ? std::max(TimeDuration(),
163 mEffect->NormalizedTiming().Delay() * -1)
164 : TimeDuration();
167 RefPtr<nsAtom> mAnimationName;
169 // The (pseudo-)element whose computed animation-name refers to this
170 // animation (if any).
172 // This is used for determining the relative composite order of animations
173 // generated from CSS markup.
175 // Typically this will be the same as the target element of the keyframe
176 // effect associated with this animation. However, it can differ in the
177 // following circumstances:
179 // a) If script removes or replaces the effect of this animation,
180 // b) If this animation is cancelled (e.g. by updating the
181 // animation-name property or removing the owning element from the
182 // document),
183 // c) If this object is generated from script using the CSSAnimation
184 // constructor.
186 // For (b) and (c) the owning element will return !IsSet().
187 OwningElementRef mOwningElement;
189 // When true, indicates that when this animation next leaves the idle state,
190 // its animation index should be updated.
191 bool mNeedsNewAnimationIndexWhenRun;
193 // Phase and current iteration from the previous time we queued events.
194 // This is used to determine what new events to dispatch.
195 ComputedTiming::AnimationPhase mPreviousPhase;
196 uint64_t mPreviousIteration;
198 // Properties that would normally be defined by the cascade but which have
199 // since been explicitly set via the Web Animations API.
200 CSSAnimationProperties mOverriddenProperties = CSSAnimationProperties::None;
203 // A subclass of KeyframeEffect that reports when specific properties have been
204 // overridden via the Web Animations API.
205 class CSSAnimationKeyframeEffect : public KeyframeEffect {
206 public:
207 CSSAnimationKeyframeEffect(Document* aDocument,
208 OwningAnimationTarget&& aTarget,
209 TimingParams&& aTiming,
210 const KeyframeEffectParams& aOptions)
211 : KeyframeEffect(aDocument, std::move(aTarget), std::move(aTiming),
212 aOptions) {}
214 void GetTiming(EffectTiming& aRetVal) const override;
215 void GetComputedTimingAsDict(ComputedEffectTiming& aRetVal) const override;
216 void UpdateTiming(const OptionalEffectTiming& aTiming,
217 ErrorResult& aRv) override;
218 void SetKeyframes(JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
219 ErrorResult& aRv) override;
220 void SetComposite(const CompositeOperation& aComposite) override;
222 private:
223 CSSAnimation* GetOwningCSSAnimation() {
224 return mAnimation ? mAnimation->AsCSSAnimation() : nullptr;
226 const CSSAnimation* GetOwningCSSAnimation() const {
227 return mAnimation ? mAnimation->AsCSSAnimation() : nullptr;
230 // Flushes styles if our owning animation is a CSSAnimation
231 void MaybeFlushUnanimatedStyle() const;
234 } // namespace dom
236 } // namespace mozilla
238 #endif // mozilla_dom_CSSAnimation_h