Bug 1264125 part 6 - Queue CSS related event when setting null target effect. r?birtles
MozReview-Commit-ID: 6KILkmNInbm
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -724,18 +724,20 @@ Animation::AnimationTimeToTimeStamp(cons
result = mTimeline->ToTimeStamp(timelineTime);
return result;
}
TimeStamp
Animation::ElapsedTimeToTimeStamp(
const StickyTimeDuration& aElapsedTime) const
{
- return AnimationTimeToTimeStamp(aElapsedTime +
- mEffect->SpecifiedTiming().mDelay);
+ TimeDuration delay = mEffect
+ ? mEffect->SpecifiedTiming().mDelay
+ : TimeDuration();
+ return AnimationTimeToTimeStamp(aElapsedTime + delay);
}
// https://w3c.github.io/web-animations/#silently-set-the-current-time
void
Animation::SilentlySetCurrentTime(const TimeDuration& aSeekTime)
{
if (!mHoldTime.IsNull() ||
mStartTime.IsNull() ||
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -177,57 +177,66 @@ CSSTransition::UpdateTiming(SeekFlag aSe
}
Animation::UpdateTiming(aSeekFlag, aSyncNotifyFlag);
}
void
CSSTransition::QueueEvents(StickyTimeDuration aActiveTime)
{
- if (!mEffect ||
- !mOwningElement.IsSet()) {
+ if (!mOwningElement.IsSet()) {
return;
}
dom::Element* owningElement;
CSSPseudoElementType owningPseudoType;
mOwningElement.GetElement(owningElement, owningPseudoType);
MOZ_ASSERT(owningElement, "Owning element should be set");
nsPresContext* presContext = mOwningElement.GetRenderedPresContext();
if (!presContext) {
return;
}
- ComputedTiming computedTiming = mEffect->GetComputedTiming();
- 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);
+ const StickyTimeDuration zeroDuration = StickyTimeDuration();
+
+ TransitionPhase currentPhase;
+ StickyTimeDuration intervalStartTime;
+ StickyTimeDuration intervalEndTime;
+
+ if (!mEffect) {
+ currentPhase = GetTransitionPhaseWithoutEffect();
+ intervalStartTime = zeroDuration;
+ intervalEndTime = zeroDuration;
+ } else {
+ ComputedTiming computedTiming = mEffect->GetComputedTiming();
+
+ currentPhase = static_cast<TransitionPhase>(computedTiming.mPhase);
+ intervalStartTime =
+ std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay),
+ computedTiming.mActiveDuration), zeroDuration);
+ intervalEndTime =
+ 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);
- TransitionPhase currentPhase;
if (mPendingState != PendingState::NotPending &&
(mPreviousTransitionPhase == TransitionPhase::Idle ||
mPreviousTransitionPhase == TransitionPhase::Pending))
{
currentPhase = TransitionPhase::Pending;
- } else {
- currentPhase = static_cast<TransitionPhase>(computedTiming.mPhase);
}
AutoTArray<TransitionEventParams, 3> events;
// Handle cancel events firts
if (mPreviousTransitionPhase != TransitionPhase::Idle &&
currentPhase == TransitionPhase::Idle) {
TimeStamp activeTimeStamp = ElapsedTimeToTimeStamp(aActiveTime);
@@ -315,16 +324,33 @@ CSSTransition::QueueEvents(StickyTimeDur
evt.mMessage,
TransitionProperty(),
evt.mElapsedTime,
evt.mTimeStamp,
this));
}
}
+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()
{
Animation::Tick();
QueueEvents();
}
nsCSSPropertyID
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -238,16 +238,22 @@ protected:
}
// Animation overrides
void UpdateTiming(SeekFlag aSeekFlag,
SyncNotifyFlag aSyncNotifyFlag) override;
void QueueEvents(StickyTimeDuration activeTime = StickyTimeDuration());
+
+ 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).
//
// This is used for determining the relative composite order of transitions
// generated from CSS markup.
//
// Typically this will be the same as the target element of the keyframe
// effect associated with this transition. However, it can differ in the