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/. */
8 #include "mozilla/dom/Element.h" // For Element
9 #include "mozilla/RestyleManager.h"
10 #include "mozilla/LayerAnimationInfo.h"
11 #include "nsCSSPseudoElements.h" // For PseudoStyleType
12 #include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
13 #include "nsPresContext.h"
14 #include "nsLayoutUtils.h"
19 void EffectSet::PropertyDtor(void* aObject
, nsAtom
* aPropertyName
,
20 void* aPropertyValue
, void* aData
) {
21 EffectSet
* effectSet
= static_cast<EffectSet
*>(aPropertyValue
);
24 MOZ_ASSERT(!effectSet
->mCalledPropertyDtor
, "Should not call dtor twice");
25 effectSet
->mCalledPropertyDtor
= true;
31 void EffectSet::Traverse(nsCycleCollectionTraversalCallback
& aCallback
) {
32 for (const auto& key
: mEffects
) {
33 CycleCollectionNoteChild(aCallback
, key
, "EffectSet::mEffects[]",
39 EffectSet
* EffectSet::GetEffectSet(const dom::Element
* aElement
,
40 PseudoStyleType aPseudoType
) {
41 if (!aElement
->MayHaveAnimations()) {
45 nsAtom
* propName
= GetEffectSetPropertyAtom(aPseudoType
);
46 return static_cast<EffectSet
*>(aElement
->GetProperty(propName
));
50 EffectSet
* EffectSet::GetOrCreateEffectSet(dom::Element
* aElement
,
51 PseudoStyleType aPseudoType
) {
52 EffectSet
* effectSet
= GetEffectSet(aElement
, aPseudoType
);
57 nsAtom
* propName
= GetEffectSetPropertyAtom(aPseudoType
);
58 effectSet
= new EffectSet();
60 nsresult rv
= aElement
->SetProperty(propName
, effectSet
,
61 &EffectSet::PropertyDtor
, true);
63 NS_WARNING("SetProperty failed");
64 // The set must be destroyed via PropertyDtor, otherwise
65 // mCalledPropertyDtor assertion is triggered in destructor.
66 EffectSet::PropertyDtor(aElement
, propName
, effectSet
, nullptr);
70 aElement
->SetMayHaveAnimations();
76 EffectSet
* EffectSet::GetEffectSetForFrame(
77 const nsIFrame
* aFrame
, const nsCSSPropertyIDSet
& aProperties
) {
80 // Transform animations are run on the primary frame (but stored on the
81 // content associated with the style frame).
82 const nsIFrame
* frameToQuery
= nullptr;
83 if (aProperties
.IsSubsetOf(nsCSSPropertyIDSet::TransformLikeProperties())) {
84 // Make sure to return nullptr if we're looking for transform animations on
85 // the inner table frame.
86 if (!aFrame
->IsFrameOfType(nsIFrame::eSupportsCSSTransforms
)) {
89 frameToQuery
= nsLayoutUtils::GetStyleFrame(aFrame
);
92 !aProperties
.Intersects(nsCSSPropertyIDSet::TransformLikeProperties()),
93 "We should have only transform properties or no transform properties");
94 // We don't need to explicitly return nullptr when |aFrame| is NOT the style
95 // frame since there will be no effect set in that case.
96 frameToQuery
= aFrame
;
99 Maybe
<NonOwningAnimationTarget
> target
=
100 EffectCompositor::GetAnimationElementAndPseudoForFrame(frameToQuery
);
105 return GetEffectSet(target
->mElement
, target
->mPseudoType
);
109 EffectSet
* EffectSet::GetEffectSetForFrame(const nsIFrame
* aFrame
,
110 DisplayItemType aDisplayItemType
) {
111 return EffectSet::GetEffectSetForFrame(
112 aFrame
, LayerAnimationInfo::GetCSSPropertiesFor(aDisplayItemType
));
116 EffectSet
* EffectSet::GetEffectSetForStyleFrame(const nsIFrame
* aStyleFrame
) {
117 Maybe
<NonOwningAnimationTarget
> target
=
118 EffectCompositor::GetAnimationElementAndPseudoForFrame(aStyleFrame
);
124 return GetEffectSet(target
->mElement
, target
->mPseudoType
);
128 EffectSet
* EffectSet::GetEffectSetForEffect(
129 const dom::KeyframeEffect
* aEffect
) {
130 NonOwningAnimationTarget target
= aEffect
->GetAnimationTarget();
135 return EffectSet::GetEffectSet(target
.mElement
, target
.mPseudoType
);
139 void EffectSet::DestroyEffectSet(dom::Element
* aElement
,
140 PseudoStyleType aPseudoType
) {
141 nsAtom
* propName
= GetEffectSetPropertyAtom(aPseudoType
);
142 EffectSet
* effectSet
=
143 static_cast<EffectSet
*>(aElement
->GetProperty(propName
));
148 MOZ_ASSERT(!effectSet
->IsBeingEnumerated(),
149 "Should not destroy an effect set while it is being enumerated");
152 aElement
->RemoveProperty(propName
);
155 void EffectSet::UpdateAnimationGeneration(nsPresContext
* aPresContext
) {
156 mAnimationGeneration
=
157 aPresContext
->RestyleManager()->GetAnimationGeneration();
161 nsAtom
** EffectSet::GetEffectSetPropertyAtoms() {
162 static nsAtom
* effectSetPropertyAtoms
[] = {
163 nsGkAtoms::animationEffectsProperty
,
164 nsGkAtoms::animationEffectsForBeforeProperty
,
165 nsGkAtoms::animationEffectsForAfterProperty
,
166 nsGkAtoms::animationEffectsForMarkerProperty
, nullptr};
168 return effectSetPropertyAtoms
;
172 nsAtom
* EffectSet::GetEffectSetPropertyAtom(PseudoStyleType aPseudoType
) {
173 switch (aPseudoType
) {
174 case PseudoStyleType::NotPseudo
:
175 return nsGkAtoms::animationEffectsProperty
;
177 case PseudoStyleType::before
:
178 return nsGkAtoms::animationEffectsForBeforeProperty
;
180 case PseudoStyleType::after
:
181 return nsGkAtoms::animationEffectsForAfterProperty
;
183 case PseudoStyleType::marker
:
184 return nsGkAtoms::animationEffectsForMarkerProperty
;
187 MOZ_ASSERT_UNREACHABLE(
188 "Should not try to get animation effects for "
189 "a pseudo other that :before, :after or ::marker");
194 void EffectSet::AddEffect(dom::KeyframeEffect
& aEffect
) {
195 if (!mEffects
.EnsureInserted(&aEffect
)) {
199 MarkCascadeNeedsUpdate();
202 void EffectSet::RemoveEffect(dom::KeyframeEffect
& aEffect
) {
203 if (!mEffects
.EnsureRemoved(&aEffect
)) {
207 MarkCascadeNeedsUpdate();
210 } // namespace mozilla