Bug 1067769 - Part 8: Implement SetTarget(), when the original target is non-null draft
authorBoris Chiou <boris.chiou@gmail.com>
Fri, 22 Apr 2016 18:22:54 +0800
changeset 355294 e44bb61727e48034e3152b09276cee2d8702fd1c
parent 355293 440c4db725e5f416fcc1bcdc4c8ea7b6bd8a1853
child 355295 0dd5a6e22c1597aa59db4725278b63821f91a442
push id16260
push userbchiou@mozilla.com
push dateFri, 22 Apr 2016 10:24:57 +0000
bugs1067769
milestone48.0a1
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
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeEffect.h
--- 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