Bug 1067769 - Part 8: Implement SetTarget(), when the original target is non-null
We have two cases when the original target is non-null:
1. New target is null. We have to make sure the value of the animation
properties of of the original target is back to the base value.
2. New target is another valid element. Call ResetTarget() to the original
target and then assign the new target.
MozReview-Commit-ID: Zxmc7YdfFY
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -760,16 +760,24 @@ void
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
{
for (AnimationProperty& property : mProperties) {
property.mIsRunningOnCompositor = false;
}
}
void
+KeyframeEffectReadOnly::ResetWinsInCascade()
+{
+ for (AnimationProperty& property : mProperties) {
+ property.mWinsInCascade = false;
+ }
+}
+
+void
KeyframeEffectReadOnly::UpdateTargetRegistration()
{
if (!mTarget) {
return;
}
bool isRelevant = mAnimation && mAnimation->IsRelevant();
@@ -1376,34 +1384,66 @@ KeyframeEffect::SetTarget(const Nullable
UnpackTarget(aTarget, newTarget, newPseudoType);
if (mTarget == newTarget && mPseudoType == newPseudoType) {
// Assign the same target, skip it.
return;
}
if (mTarget) {
- // TODO: fix in the next patch
- MOZ_ASSERT(false, "not implemented yet");
- } else if (newTarget) {
- // Replace null target with a valid element
+ ResetTarget();
+ }
+
+ if (newTarget) {
AssignTarget(newTarget, newPseudoType);
}
}
KeyframeEffect::~KeyframeEffect()
{
// mTiming is cycle collected, so we have to do null check first even though
// mTiming shouldn't be null during the lifetime of KeyframeEffect.
if (mTiming) {
mTiming->Unlink();
}
}
void
+KeyframeEffect::ResetTarget()
+{
+ MOZ_ASSERT(mTarget, "Only reset valid target");
+
+ // Remove the effect from its EffectSet.
+ EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType);
+ if (effectSet) {
+ effectSet->RemoveEffect(*this);
+ if (effectSet->IsEmpty()) {
+ EffectSet::DestroyEffectSet(mTarget, mPseudoType);
+ }
+ }
+
+ ResetIsRunningOnCompositor();
+ ResetWinsInCascade();
+
+ // Restyle original target, so the animation properties of original target
+ // will be reset to its base value.
+ nsPresContext* presContext = GetPresContext();
+ if (presContext && mAnimation) {
+ presContext->EffectCompositor()->
+ RequestRestyle(mTarget, mPseudoType,
+ EffectCompositor::RestyleType::Layer,
+ mAnimation->CascadeLevel());
+ }
+
+ // Set the target to null last.
+ mTarget = nullptr;
+ mPseudoType = CSSPseudoElementType::NotPseudo;
+}
+
+void
KeyframeEffect::AssignTarget(Element* aNewTarget,
CSSPseudoElementType aNewPseudoType)
{
MOZ_ASSERT(aNewTarget, "Only assign a valid target");
// Assign new target first, so we can handle mTarget properly.
mTarget = aNewTarget;
mPseudoType = aNewPseudoType;
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -346,16 +346,17 @@ protected:
static already_AddRefed<KeyframeEffectType>
ConstructKeyframeEffect(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const OptionsType& aOptions,
ErrorResult& aRv);
void ResetIsRunningOnCompositor();
+ void ResetWinsInCascade();
// This effect is registered with its target element so long as:
//
// (a) It has a target element, and
// (b) It is "relevant" (i.e. yet to finish but not idle, or finished but
// filling forwards)
//
// As a result, we need to make sure this gets called whenever anything
@@ -432,15 +433,16 @@ public:
void NotifySpecifiedTimingUpdated();
void SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget);
protected:
~KeyframeEffect() override;
private:
+ void ResetTarget();
void AssignTarget(Element* aNewTarget, CSSPseudoElementType aNewPseudoType);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_KeyframeEffect_h