Bug 1698238 return default dictionary from GetUserMediaRequest#getConstraints() if...
[gecko.git] / dom / animation / CSSAnimation.h
blob9210dfd04bd321fd29d98753fff320201464ccf2
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 Effect = Keyframes | Duration | IterationCount | Direction | Delay | FillMode,
29 PlayState = 1 << 6,
31 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CSSAnimationProperties)
33 namespace dom {
35 class CSSAnimation final : public Animation {
36 public:
37 explicit CSSAnimation(nsIGlobalObject* aGlobal, nsAtom* aAnimationName)
38 : dom::Animation(aGlobal),
39 mAnimationName(aAnimationName),
40 mNeedsNewAnimationIndexWhenRun(false),
41 mPreviousPhase(ComputedTiming::AnimationPhase::Idle),
42 mPreviousIteration(0) {
43 // We might need to drop this assertion once we add a script-accessible
44 // constructor but for animations generated from CSS markup the
45 // animation-name should never be empty.
46 MOZ_ASSERT(mAnimationName != nsGkAtoms::_empty,
47 "animation-name should not be 'none'");
50 JSObject* WrapObject(JSContext* aCx,
51 JS::Handle<JSObject*> aGivenProto) override;
53 CSSAnimation* AsCSSAnimation() override { return this; }
54 const CSSAnimation* AsCSSAnimation() const override { return this; }
56 // CSSAnimation interface
57 void GetAnimationName(nsString& aRetVal) const {
58 mAnimationName->ToString(aRetVal);
61 nsAtom* AnimationName() const { return mAnimationName; }
63 // Animation interface overrides
64 void SetEffect(AnimationEffect* aEffect) override;
65 void SetStartTimeAsDouble(const Nullable<double>& aStartTime) override;
66 Promise* GetReady(ErrorResult& aRv) override;
67 void Reverse(ErrorResult& aRv) override;
69 // NOTE: tabbrowser.xml currently relies on the fact that reading the
70 // currentTime of a CSSAnimation does *not* flush style (whereas reading the
71 // playState does). If CSS Animations 2 specifies that reading currentTime
72 // also flushes style we will need to find another way to detect canceled
73 // animations in tabbrowser.xml. On the other hand, if CSS Animations 2
74 // specifies that reading playState does *not* flush style (and we drop the
75 // following override), then we should update tabbrowser.xml to check
76 // the playState instead.
77 AnimationPlayState PlayStateFromJS() const override;
78 bool PendingFromJS() const override;
79 void PlayFromJS(ErrorResult& aRv) override;
80 void PauseFromJS(ErrorResult& aRv) override;
82 void PlayFromStyle();
83 void PauseFromStyle();
84 void CancelFromStyle(PostRestyleMode aPostRestyle) {
85 // When an animation is disassociated with style it enters an odd state
86 // where its composite order is undefined until it first transitions
87 // out of the idle state.
89 // Even if the composite order isn't defined we don't want it to be random
90 // in case we need to determine the order to dispatch events associated
91 // with an animation in this state. To solve this we treat the animation as
92 // if it had been added to the end of the global animation list so that
93 // its sort order is defined. We'll update this index again once the
94 // animation leaves the idle state.
95 mAnimationIndex = sNextAnimationIndex++;
96 mNeedsNewAnimationIndexWhenRun = true;
98 Animation::Cancel(aPostRestyle);
100 // We need to do this *after* calling Cancel() since
101 // Cancel() might synchronously trigger a cancel event for which
102 // we need an owning element to target the event at.
103 mOwningElement = OwningElementRef();
106 void Tick() override;
107 void QueueEvents(
108 const StickyTimeDuration& aActiveTime = StickyTimeDuration());
110 bool HasLowerCompositeOrderThan(const CSSAnimation& aOther) const;
112 void SetAnimationIndex(uint64_t aIndex) {
113 MOZ_ASSERT(IsTiedToMarkup());
114 if (IsRelevant() && mAnimationIndex != aIndex) {
115 MutationObservers::NotifyAnimationChanged(this);
116 PostUpdate();
118 mAnimationIndex = aIndex;
121 // Sets the owning element which is used for determining the composite
122 // order of CSSAnimation objects generated from CSS markup.
124 // @see mOwningElement
125 void SetOwningElement(const OwningElementRef& aElement) {
126 mOwningElement = aElement;
128 // True for animations that are generated from CSS markup and continue to
129 // reflect changes to that markup.
130 bool IsTiedToMarkup() const { return mOwningElement.IsSet(); }
132 void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) override {
133 QueueEvents(aActiveTime);
136 CSSAnimationProperties GetOverriddenProperties() const {
137 return mOverriddenProperties;
139 void AddOverriddenProperties(CSSAnimationProperties aProperties) {
140 mOverriddenProperties |= aProperties;
143 protected:
144 virtual ~CSSAnimation() {
145 MOZ_ASSERT(!mOwningElement.IsSet(),
146 "Owning element should be cleared "
147 "before a CSS animation is destroyed");
150 // Animation overrides
151 void UpdateTiming(SeekFlag aSeekFlag,
152 SyncNotifyFlag aSyncNotifyFlag) override;
154 // Returns the duration from the start of the animation's source effect's
155 // active interval to the point where the animation actually begins playback.
156 // This is zero unless the animation's source effect has a negative delay in
157 // which case it is the absolute value of that delay.
158 // This is used for setting the elapsedTime member of CSS AnimationEvents.
159 TimeDuration InitialAdvance() const {
160 return mEffect ? std::max(TimeDuration(),
161 mEffect->SpecifiedTiming().Delay() * -1)
162 : TimeDuration();
165 RefPtr<nsAtom> mAnimationName;
167 // The (pseudo-)element whose computed animation-name refers to this
168 // animation (if any).
170 // This is used for determining the relative composite order of animations
171 // generated from CSS markup.
173 // Typically this will be the same as the target element of the keyframe
174 // effect associated with this animation. However, it can differ in the
175 // following circumstances:
177 // a) If script removes or replaces the effect of this animation,
178 // b) If this animation is cancelled (e.g. by updating the
179 // animation-name property or removing the owning element from the
180 // document),
181 // c) If this object is generated from script using the CSSAnimation
182 // constructor.
184 // For (b) and (c) the owning element will return !IsSet().
185 OwningElementRef mOwningElement;
187 // When true, indicates that when this animation next leaves the idle state,
188 // its animation index should be updated.
189 bool mNeedsNewAnimationIndexWhenRun;
191 // Phase and current iteration from the previous time we queued events.
192 // This is used to determine what new events to dispatch.
193 ComputedTiming::AnimationPhase mPreviousPhase;
194 uint64_t mPreviousIteration;
196 // Properties that would normally be defined by the cascade but which have
197 // since been explicitly set via the Web Animations API.
198 CSSAnimationProperties mOverriddenProperties = CSSAnimationProperties::None;
201 // A subclass of KeyframeEffect that reports when specific properties have been
202 // overridden via the Web Animations API.
203 class CSSAnimationKeyframeEffect : public KeyframeEffect {
204 public:
205 CSSAnimationKeyframeEffect(Document* aDocument,
206 OwningAnimationTarget&& aTarget,
207 TimingParams&& aTiming,
208 const KeyframeEffectParams& aOptions)
209 : KeyframeEffect(aDocument, std::move(aTarget), std::move(aTiming),
210 aOptions) {}
212 void GetTiming(EffectTiming& aRetVal) const override;
213 void GetComputedTimingAsDict(ComputedEffectTiming& aRetVal) const override;
214 void UpdateTiming(const OptionalEffectTiming& aTiming,
215 ErrorResult& aRv) override;
216 void SetKeyframes(JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
217 ErrorResult& aRv) override;
219 private:
220 CSSAnimation* GetOwningCSSAnimation() {
221 return mAnimation ? mAnimation->AsCSSAnimation() : nullptr;
223 const CSSAnimation* GetOwningCSSAnimation() const {
224 return mAnimation ? mAnimation->AsCSSAnimation() : nullptr;
227 // Flushes styles if our owning animation is a CSSAnimation
228 void MaybeFlushUnanimatedStyle() const;
231 } // namespace dom
233 template <>
234 struct AnimationTypeTraits<dom::CSSAnimation> {
235 static nsAtom* ElementPropertyAtom() { return nsGkAtoms::animationsProperty; }
236 static nsAtom* BeforePropertyAtom() {
237 return nsGkAtoms::animationsOfBeforeProperty;
239 static nsAtom* AfterPropertyAtom() {
240 return nsGkAtoms::animationsOfAfterProperty;
242 static nsAtom* MarkerPropertyAtom() {
243 return nsGkAtoms::animationsOfMarkerProperty;
247 } // namespace mozilla
249 #endif // mozilla_dom_CSSAnimation_h