Bug 1302648 part 5 - Queue animationcancel when animation status is idle. r=birtles

MozReview-Commit-ID: DRjWboQwR0A

--HG--
extra : rebase_source : 17a92668519bdf7a4d7c58c97bd8f23b889767a7
This commit is contained in:
Mantaroh Yoshinaga 2017-02-10 12:32:44 +09:00
parent fa7dee3362
commit f0550caaae
5 changed files with 70 additions and 49 deletions

View File

@ -251,6 +251,26 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
aField.Traverse(&aCallback, aName);
}
// Return the TransitionPhase or AnimationPhase to use when the animation
// doesn't have a target effect.
template <typename PhaseType>
PhaseType GetAnimationPhaseWithoutEffect(const dom::Animation& aAnimation)
{
MOZ_ASSERT(!aAnimation.GetEffect(),
"Should only be called when we do not have an effect");
Nullable<TimeDuration> currentTime = aAnimation.GetCurrentTime();
if (currentTime.IsNull()) {
return PhaseType::Idle;
}
// If we don't have a target effect, the duration will be zero so the phase is
// 'before' if the current time is less than zero.
return currentTime.Value() < TimeDuration()
? PhaseType::Before
: PhaseType::After;
};
} // namespace mozilla
#endif /* !defined(mozilla_css_AnimationCommon_h) */

View File

@ -161,12 +161,8 @@ CSSAnimation::HasLowerCompositeOrderThan(const CSSAnimation& aOther) const
}
void
CSSAnimation::QueueEvents()
CSSAnimation::QueueEvents(StickyTimeDuration aActiveTime)
{
if (!mEffect) {
return;
}
// If the animation is pending, we ignore animation events until we finish
// pending.
if (mPendingState != PendingState::NotPending) {
@ -200,37 +196,58 @@ CSSAnimation::QueueEvents()
return;
}
nsAnimationManager* manager = presContext->AnimationManager();
ComputedTiming computedTiming = mEffect->GetComputedTiming();
AnimationPhase currentPhase = computedTiming.mPhase;
uint64_t currentIteration = computedTiming.mCurrentIteration;
if (currentPhase == mPreviousPhase &&
currentIteration == mPreviousIteration) {
return;
}
const StickyTimeDuration zeroDuration;
StickyTimeDuration intervalStartTime =
std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay),
computedTiming.mActiveDuration),
zeroDuration);
StickyTimeDuration intervalEndTime =
std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay),
computedTiming.mActiveDuration),
zeroDuration);
uint64_t currentIteration = 0;
ComputedTiming::AnimationPhase currentPhase;
StickyTimeDuration intervalStartTime;
StickyTimeDuration intervalEndTime;
StickyTimeDuration iterationStartTime;
uint64_t iterationBoundary = mPreviousIteration > currentIteration
? currentIteration + 1
: currentIteration;
StickyTimeDuration iterationStartTime =
computedTiming.mDuration.MultDouble(
(iterationBoundary - computedTiming.mIterationStart));
if (!mEffect) {
currentPhase = GetAnimationPhaseWithoutEffect
<ComputedTiming::AnimationPhase>(*this);
} else {
ComputedTiming computedTiming = mEffect->GetComputedTiming();
currentPhase = computedTiming.mPhase;
currentIteration = computedTiming.mCurrentIteration;
if (currentPhase == mPreviousPhase &&
currentIteration == mPreviousIteration) {
return;
}
intervalStartTime =
std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay),
computedTiming.mActiveDuration),
zeroDuration);
intervalEndTime =
std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay),
computedTiming.mActiveDuration),
zeroDuration);
uint64_t iterationBoundary = mPreviousIteration > currentIteration
? currentIteration + 1
: currentIteration;
iterationStartTime =
computedTiming.mDuration.MultDouble(
(iterationBoundary - computedTiming.mIterationStart));
}
TimeStamp startTimeStamp = ElapsedTimeToTimeStamp(intervalStartTime);
TimeStamp endTimeStamp = ElapsedTimeToTimeStamp(intervalEndTime);
TimeStamp iterationTimeStamp = ElapsedTimeToTimeStamp(iterationStartTime);
AutoTArray<AnimationEventParams, 2> events;
// Handle cancel event first
if ((mPreviousPhase != AnimationPhase::Idle &&
mPreviousPhase != AnimationPhase::After) &&
currentPhase == AnimationPhase::Idle) {
TimeStamp activeTimeStamp = ElapsedTimeToTimeStamp(aActiveTime);
events.AppendElement(AnimationEventParams{ eAnimationCancel,
aActiveTime,
activeTimeStamp });
}
switch (mPreviousPhase) {
case AnimationPhase::Idle:
case AnimationPhase::Before:

View File

@ -132,7 +132,7 @@ public:
}
void Tick() override;
void QueueEvents();
void QueueEvents(StickyTimeDuration aActiveTime = StickyTimeDuration());
bool IsStylePaused() const { return mIsStylePaused; }
@ -161,6 +161,10 @@ public:
// reflect changes to that markup.
bool IsTiedToMarkup() const { return mOwningElement.IsSet(); }
void MaybeQueueCancelEvent(StickyTimeDuration aActiveTime) override {
QueueEvents(aActiveTime);
}
protected:
virtual ~CSSAnimation()
{

View File

@ -201,7 +201,7 @@ CSSTransition::QueueEvents(StickyTimeDuration aActiveTime)
StickyTimeDuration intervalEndTime;
if (!mEffect) {
currentPhase = GetTransitionPhaseWithoutEffect();
currentPhase = GetAnimationPhaseWithoutEffect<TransitionPhase>(*this);
} else {
ComputedTiming computedTiming = mEffect->GetComputedTiming();
@ -326,23 +326,6 @@ CSSTransition::QueueEvents(StickyTimeDuration aActiveTime)
}
}
CSSTransition::TransitionPhase
CSSTransition::GetTransitionPhaseWithoutEffect() const
{
MOZ_ASSERT(!mEffect, "Should only be called when we do not have an effect");
Nullable<TimeDuration> currentTime = GetCurrentTime();
if (currentTime.IsNull()) {
return TransitionPhase::Idle;
}
// If we don't have a target effect, the duration will be zero so the phase is
// 'before' if the current time is less than zero.
return currentTime.Value() < TimeDuration()
? TransitionPhase::Before
: TransitionPhase::After;
}
void
CSSTransition::Tick()
{

View File

@ -233,9 +233,6 @@ protected:
enum class TransitionPhase;
// Return the TransitionPhase to use when the transition doesn't have a target
// effect.
TransitionPhase GetTransitionPhaseWithoutEffect() const;
// The (pseudo-)element whose computed transition-property refers to this
// transition (if any).