From 3ce242ee4845df3b8be9e34c94b4c150c620cd38 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 28 May 2014 16:51:49 +0900 Subject: [PATCH] Bug 1004871 part 7 - Remove event queueing from GetPositionInIteration and do it in GetEventsAt; r=dholbert This patch simply shifts the event-related code from GetPositionInIteration to GetEventsAt. Although there are simplifications that could be done to GetEventsAt, they are deferred to a subsequent patch so as not to obscure the translation of code from one function to another. As a result of moving event-related handling from GetPositionInIteration it no longer needs to support different main-thread vs compositor modes. --- layout/style/nsAnimationManager.cpp | 73 +++++++++++++++++-------------------- layout/style/nsAnimationManager.h | 14 ++----- 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index 2086684b1209..2cb5b5d06ce6 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -51,32 +51,16 @@ ElementAnimationsPropertyDtor(void *aObject, ComputedTiming ElementAnimations::GetPositionInIteration(TimeDuration aElapsedDuration, - const AnimationTiming& aTiming, - ElementAnimation* aAnimation, - ElementAnimations* aEa, - EventArray* aEventsToDispatch) + const AnimationTiming& aTiming) { - MOZ_ASSERT(!aAnimation == !aEa && !aAnimation == !aEventsToDispatch); - // Always return the same object to benefit from return-value optimization. ComputedTiming result; // Set |currentIterationCount| to the (fractional) number of // iterations we've completed up to the current position. double currentIterationCount = aElapsedDuration / aTiming.mIterationDuration; - bool dispatchStartOrIteration = false; if (currentIterationCount >= aTiming.mIterationCount) { result.mPhase = ComputedTiming::AnimationPhase_After; - if (aAnimation) { - // Dispatch 'animationend' when needed. - if (aAnimation->mLastNotification != - ElementAnimation::LAST_NOTIFICATION_END) { - aAnimation->mLastNotification = ElementAnimation::LAST_NOTIFICATION_END; - AnimationEventInfo ei(aEa->mElement, aAnimation->mName, NS_ANIMATION_END, - aElapsedDuration, aEa->PseudoElement()); - aEventsToDispatch->AppendElement(ei); - } - } if (!aTiming.FillsForwards()) { // The animation isn't active or filling at this time. result.mTimeFraction = ComputedTiming::kNullTimeFraction; @@ -93,7 +77,6 @@ ElementAnimations::GetPositionInIteration(TimeDuration aElapsedDuration, currentIterationCount = 0.0; } else { result.mPhase = ComputedTiming::AnimationPhase_Active; - dispatchStartOrIteration = aAnimation && !aAnimation->IsPaused(); } // Set |positionInIteration| to the position from 0% to 100% along @@ -143,25 +126,6 @@ ElementAnimations::GetPositionInIteration(TimeDuration aElapsedDuration, positionInIteration = 1.0 - positionInIteration; } - // Dispatch 'animationstart' or 'animationiteration' when needed. - if (aAnimation && dispatchStartOrIteration && - whichIteration != aAnimation->mLastNotification) { - // Notify 'animationstart' even if a negative delay puts us - // past the first iteration. - // Note that when somebody changes the animation-duration - // dynamically, this will fire an extra iteration event - // immediately in many cases. It's not clear to me if that's the - // right thing to do. - uint32_t message = - aAnimation->mLastNotification == ElementAnimation::LAST_NOTIFICATION_NONE - ? NS_ANIMATION_START : NS_ANIMATION_ITERATION; - - aAnimation->mLastNotification = whichIteration; - AnimationEventInfo ei(aEa->mElement, aAnimation->mName, message, - aElapsedDuration, aEa->PseudoElement()); - aEventsToDispatch->AppendElement(ei); - } - result.mTimeFraction = positionInIteration; result.mCurrentIteration = whichIteration; return result; @@ -347,8 +311,39 @@ ElementAnimations::GetEventsAt(TimeStamp aRefreshTime, continue; } - GetPositionInIteration(anim->ElapsedDurationAt(aRefreshTime), - anim->mTiming, anim, this, &aEventsToDispatch); + TimeDuration elapsedDuration = anim->ElapsedDurationAt(aRefreshTime); + ComputedTiming computedTiming = + GetPositionInIteration(elapsedDuration, anim->mTiming); + + if (computedTiming.mPhase == ComputedTiming::AnimationPhase_After) { + // Dispatch 'animationend' when needed. + if (anim->mLastNotification != ElementAnimation::LAST_NOTIFICATION_END) { + anim->mLastNotification = ElementAnimation::LAST_NOTIFICATION_END; + AnimationEventInfo ei(mElement, anim->mName, NS_ANIMATION_END, + elapsedDuration, PseudoElement()); + aEventsToDispatch.AppendElement(ei); + } + } else if (computedTiming.mPhase == ComputedTiming::AnimationPhase_Active) { + if (!anim->IsPaused()) { + // Dispatch 'animationstart' or 'animationiteration' when needed. + if (computedTiming.mCurrentIteration != anim->mLastNotification) { + // Notify 'animationstart' even if a negative delay puts us + // past the first iteration. + // Note that when somebody changes the animation-duration + // dynamically, this will fire an extra iteration event + // immediately in many cases. It's not clear to me if that's the + // right thing to do. + uint32_t message = + anim->mLastNotification == ElementAnimation::LAST_NOTIFICATION_NONE + ? NS_ANIMATION_START : NS_ANIMATION_ITERATION; + + anim->mLastNotification = computedTiming.mCurrentIteration; + AnimationEventInfo ei(mElement, anim->mName, message, + elapsedDuration, PseudoElement()); + aEventsToDispatch.AppendElement(ei); + } + } + } } } diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 33408d95a343..315e023ad155 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -64,21 +64,15 @@ struct ElementAnimations MOZ_FINAL // returns a ComputedTiming struct representing the animation's progress at // the given moment. // - // When this function is called from the main thread with an actual - // ElementAnimation* pointer, animation events are also queued. // This function returns ComputedTiming::kNullTimeFraction for the // mTimeFraction member of the return value if the animation should not be - // run (because it is not currently active and has no fill behavior). - // - // After calling GetPositionInIteration with non-null aAnimation and aEa, be - // sure to call CheckNeedsRefresh on the animation manager afterwards. + // run (because it is not currently active and is not filling at this time). static mozilla::ComputedTiming GetPositionInIteration( TimeDuration aElapsedDuration, - const mozilla::AnimationTiming& aTiming, - mozilla::ElementAnimation* aAnimation = nullptr, - ElementAnimations* aEa = nullptr, - EventArray* aEventsToDispatch = nullptr); + const mozilla::AnimationTiming& aTiming); + // After calling this, be sure to call CheckNeedsRefresh on the animation + // manager afterwards. void EnsureStyleRuleFor(TimeStamp aRefreshTime, bool aIsThrottled); void GetEventsAt(TimeStamp aRefreshTime, EventArray &aEventsToDispatch); -- 2.11.4.GIT