Bug 1264125 part 4 - Add transitioncancel handlilng process. r?birtles draft
authorMantaroh Yoshinaga <mantaroh@gmail.com>
Thu, 20 Oct 2016 14:19:09 +0900
changeset 427858 c227b8b60b0e686dd6a1e60993f00c6302e043f6
parent 427857 be361e3d3a331ed308dcb838092daae1d442d360
child 427859 ce3a69425dce8f6295dc65cde11b7b0cdda2fbba
push id33142
push usermantaroh@gmail.com
push dateFri, 21 Oct 2016 00:27:27 +0000
reviewersbirtles
bugs1264125
milestone52.0a1
Bug 1264125 part 4 - Add transitioncancel handlilng process. r?birtles MozReview-Commit-ID: IQevmMeCe3I
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -206,19 +206,20 @@ CSSTransition::QueueEvents()
     std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay),
                       computedTiming.mActiveDuration), zeroDuration);
 
   // TimeStamps to use for ordering the events when they are dispatched. We
   // use a TimeStamp so we can compare events produced by different elements,
   // perhaps even with different timelines.
   // The zero timestamp is for transitionrun events where we ignore the delay
   // for the purpose of ordering events.
-  TimeStamp zeroTimeStamp  = AnimationTimeToTimeStamp(zeroDuration);
-  TimeStamp startTimeStamp = ElapsedTimeToTimeStamp(intervalStartTime);
-  TimeStamp endTimeStamp   = ElapsedTimeToTimeStamp(intervalEndTime);
+  TimeStamp zeroTimeStamp   = AnimationTimeToTimeStamp(zeroDuration);
+  TimeStamp startTimeStamp  = ElapsedTimeToTimeStamp(intervalStartTime);
+  TimeStamp endTimeStamp    = ElapsedTimeToTimeStamp(intervalEndTime);
+  TimeStamp activeTimeStamp = ElapsedTimeToTimeStamp(computedTiming.mActiveTime);
 
   TransitionPhase currentPhase;
   if (mPendingState != PendingState::NotPending &&
       (mPreviousTransitionPhase == TransitionPhase::Idle ||
        mPreviousTransitionPhase == TransitionPhase::Pending))
   {
     currentPhase = TransitionPhase::Pending;
   } else {
@@ -226,78 +227,90 @@ CSSTransition::QueueEvents()
   }
 
   AutoTArray<TransitionEventParams, 3> events;
   switch (mPreviousTransitionPhase) {
     case TransitionPhase::Idle:
       if (currentPhase == TransitionPhase::Pending ||
           currentPhase == TransitionPhase::Before) {
         events.AppendElement(TransitionEventParams{ eTransitionRun,
-                                                   intervalStartTime,
-                                                   zeroTimeStamp });
+                                                    intervalStartTime,
+                                                    zeroTimeStamp });
       } else if (currentPhase == TransitionPhase::Active) {
         events.AppendElement(TransitionEventParams{ eTransitionRun,
-                                                   intervalStartTime,
-                                                   zeroTimeStamp });
+                                                    intervalStartTime,
+                                                    zeroTimeStamp });
         events.AppendElement(TransitionEventParams{ eTransitionStart,
-                                                   intervalStartTime,
-                                                   startTimeStamp });
+                                                    intervalStartTime,
+                                                    startTimeStamp });
       } else if (currentPhase == TransitionPhase::After) {
         events.AppendElement(TransitionEventParams{ eTransitionRun,
-                                                   intervalStartTime,
-                                                   zeroTimeStamp });
+                                                    intervalStartTime,
+                                                    zeroTimeStamp });
         events.AppendElement(TransitionEventParams{ eTransitionStart,
-                                                   intervalStartTime,
-                                                   startTimeStamp });
+                                                    intervalStartTime,
+                                                    startTimeStamp });
         events.AppendElement(TransitionEventParams{ eTransitionEnd,
-                                                   intervalEndTime,
-                                                   endTimeStamp });
+                                                    intervalEndTime,
+                                                    endTimeStamp });
       }
       break;
 
     case TransitionPhase::Pending:
     case TransitionPhase::Before:
-      if (currentPhase == TransitionPhase::Active) {
+      if (currentPhase == TransitionPhase::Idle) {
+        events.AppendElement(TransitionEventParams{ eTransitionCancel,
+                                                    computedTiming.mActiveTime,
+                                                    activeTimeStamp });
+      } else if (currentPhase == TransitionPhase::Active) {
         events.AppendElement(TransitionEventParams{ eTransitionStart,
-                                                   intervalStartTime,
-                                                   startTimeStamp });
+                                                    intervalStartTime,
+                                                    startTimeStamp });
       } else if (currentPhase == TransitionPhase::After) {
         events.AppendElement(TransitionEventParams{ eTransitionStart,
-                                                   intervalStartTime,
-                                                   startTimeStamp });
+                                                    intervalStartTime,
+                                                    startTimeStamp });
         events.AppendElement(TransitionEventParams{ eTransitionEnd,
-                                                   intervalEndTime,
-                                                   endTimeStamp });
+                                                    intervalEndTime,
+                                                    endTimeStamp });
       }
       break;
 
     case TransitionPhase::Active:
-      if (currentPhase == TransitionPhase::After) {
+      if (currentPhase == TransitionPhase::Idle) {
+        events.AppendElement(TransitionEventParams{ eTransitionCancel,
+                                                    computedTiming.mActiveTime,
+                                                    activeTimeStamp });
+      } else if (currentPhase == TransitionPhase::After) {
         events.AppendElement(TransitionEventParams{ eTransitionEnd,
-                                                   intervalEndTime,
-                                                   endTimeStamp });
+                                                    intervalEndTime,
+                                                    endTimeStamp });
       } else if (currentPhase == TransitionPhase::Before) {
         events.AppendElement(TransitionEventParams{ eTransitionEnd,
-                                                   intervalStartTime,
-                                                   startTimeStamp });
+                                                    intervalStartTime,
+                                                    startTimeStamp });
       }
       break;
 
     case TransitionPhase::After:
-      if (currentPhase == TransitionPhase::Active) {
+      if (currentPhase == TransitionPhase::Idle) {
+        events.AppendElement(TransitionEventParams{ eTransitionCancel,
+                                                    computedTiming.mActiveTime,
+                                                    activeTimeStamp });
+      } else if (currentPhase == TransitionPhase::Active) {
         events.AppendElement(TransitionEventParams{ eTransitionStart,
-                                                   intervalEndTime,
-                                                   startTimeStamp });
+                                                    intervalEndTime,
+                                                    startTimeStamp });
       } else if (currentPhase == TransitionPhase::Before) {
         events.AppendElement(TransitionEventParams{ eTransitionStart,
-                                                   intervalEndTime,
-                                                   startTimeStamp });
+                                                    intervalEndTime,
+                                                    startTimeStamp });
         events.AppendElement(TransitionEventParams{ eTransitionEnd,
-                                                   intervalStartTime,
-                                                   endTimeStamp });
+                                                    intervalStartTime,
+                                                    endTimeStamp });
       }
       break;
   }
   mPreviousTransitionPhase = currentPhase;
 
   nsTransitionManager* manager = presContext->TransitionManager();
   for (const TransitionEventParams& evt : events) {
     manager->QueueEvent(TransitionEventInfo(owningElement, owningPseudoType,
@@ -384,16 +397,24 @@ CSSTransition::SetEffectFromStyle(Animat
   // Initialize transition property.
   ElementPropertyTransition* pt = aEffect ? aEffect->AsTransition() : nullptr;
   if (eCSSProperty_UNKNOWN == mTransitionProperty && pt) {
     mTransitionProperty = pt->TransitionProperty();
     mTransitionToValue = pt->ToValue();
   }
 }
 
+void
+CSSTransition::RequestTickOnce()
+{
+  if (mTimeline) {
+    mTimeline->NotifyAnimationUpdated(*this);
+  }
+}
+
 ////////////////////////// nsTransitionManager ////////////////////////////
 
 NS_IMPL_CYCLE_COLLECTION(nsTransitionManager, mEventDispatcher)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTransitionManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransitionManager, Release)
 
 static inline bool
@@ -1071,10 +1092,13 @@ nsTransitionManager::StopTransitionsForE
   MOZ_ASSERT(aElement);
   CSSTransitionCollection* collection =
     CSSTransitionCollection::GetAnimationCollection(aElement, aPseudoType);
   if (!collection) {
     return;
   }
 
   nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
+  for (size_t animIdx = collection->mAnimations.Length(); animIdx-- != 0; ) {
+     collection->mAnimations[animIdx]->RequestTickOnce();
+  }
   collection->Destroy();
 }
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -157,16 +157,21 @@ public:
     // defined until that moment.
     //
     // See longer explanation in CSSAnimation::CancelFromStyle.
     mAnimationIndex = sNextAnimationIndex++;
     mNeedsNewAnimationIndexWhenRun = true;
 
     Animation::CancelFromStyle();
 
+    // We will need to queue the transitioncancel event before
+    // removing the element. We will ignore queing event when
+    // we don't have the related element.
+    QueueEvents();
+
     // It is important we do this *after* calling CancelFromStyle().
     // This is because CancelFromStyle() will end up posting a restyle and
     // that restyle should target the *transitions* level of the cascade.
     // However, once we clear the owning element, CascadeLevel() will begin
     // returning CascadeLevel::Animations.
     mOwningElement = OwningElementRef();
   }
 
@@ -209,16 +214,21 @@ public:
   // because the animation on the compositor may be running ahead while
   // main-thread is busy.
   static Nullable<TimeDuration> GetCurrentTimeAt(
       const DocumentTimeline& aTimeline,
       const TimeStamp& aBaseTime,
       const TimeDuration& aStartTime,
       double aPlaybackRate);
 
+  // To request tick via related timeline.
+  // This is for transitioncancel, because transition won't tick after
+  // canceling own transition.
+  void RequestTickOnce();
+
 protected:
   virtual ~CSSTransition()
   {
     MOZ_ASSERT(!mOwningElement.IsSet(), "Owning element should be cleared "
                                         "before a CSS transition is destroyed");
   }
 
   // Animation overrides