mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-28 18:17:29 +09:00
parent
c8ee9f4f48
commit
901d2a277f
11 changed files with 99 additions and 73 deletions
|
|
@ -787,12 +787,21 @@ Animation::CancelNoUpdate()
|
||||||
mHoldTime.SetNull();
|
mHoldTime.SetNull();
|
||||||
mStartTime.SetNull();
|
mStartTime.SetNull();
|
||||||
|
|
||||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
|
||||||
|
|
||||||
if (mTimeline) {
|
if (mTimeline) {
|
||||||
mTimeline->RemoveAnimation(this);
|
mTimeline->RemoveAnimation(this);
|
||||||
}
|
}
|
||||||
MaybeQueueCancelEvent(activeTime);
|
MaybeQueueCancelEvent(activeTime);
|
||||||
|
|
||||||
|
// When an animation is cancelled it no longer needs further ticks from the
|
||||||
|
// timeline. However, if we queued a cancel event and this was the last
|
||||||
|
// animation attached to the timeline, the timeline will stop observing the
|
||||||
|
// refresh driver and there may be no subsequent refresh driver tick for
|
||||||
|
// dispatching the queued event.
|
||||||
|
//
|
||||||
|
// By calling UpdateTiming *after* removing ourselves from our timeline, we
|
||||||
|
// ensure the timeline will register with the refresh driver for at least one
|
||||||
|
// more tick.
|
||||||
|
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,12 @@ struct ComputedTiming
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class AnimationPhase {
|
enum class AnimationPhase {
|
||||||
Null, // Not sampled (null sample time)
|
Idle, // Not sampled (null sample time)
|
||||||
Before, // Sampled prior to the start of the active interval
|
Before, // Sampled prior to the start of the active interval
|
||||||
Active, // Sampled within the active interval
|
Active, // Sampled within the active interval
|
||||||
After // Sampled after (or at) the end of the active interval
|
After // Sampled after (or at) the end of the active interval
|
||||||
};
|
};
|
||||||
AnimationPhase mPhase = AnimationPhase::Null;
|
AnimationPhase mPhase = AnimationPhase::Idle;
|
||||||
|
|
||||||
ComputedTimingFunction::BeforeFlag mBeforeFlag =
|
ComputedTimingFunction::BeforeFlag mBeforeFlag =
|
||||||
ComputedTimingFunction::BeforeFlag::Unset;
|
ComputedTimingFunction::BeforeFlag::Unset;
|
||||||
|
|
|
||||||
|
|
@ -694,6 +694,7 @@ GK_ATOM(onadapterremoved, "onadapterremoved")
|
||||||
GK_ATOM(onafterprint, "onafterprint")
|
GK_ATOM(onafterprint, "onafterprint")
|
||||||
GK_ATOM(onafterscriptexecute, "onafterscriptexecute")
|
GK_ATOM(onafterscriptexecute, "onafterscriptexecute")
|
||||||
GK_ATOM(onalerting, "onalerting")
|
GK_ATOM(onalerting, "onalerting")
|
||||||
|
GK_ATOM(onanimationcancel, "onanimationcancel")
|
||||||
GK_ATOM(onanimationend, "onanimationend")
|
GK_ATOM(onanimationend, "onanimationend")
|
||||||
GK_ATOM(onanimationiteration, "onanimationiteration")
|
GK_ATOM(onanimationiteration, "onanimationiteration")
|
||||||
GK_ATOM(onanimationstart, "onanimationstart")
|
GK_ATOM(onanimationstart, "onanimationstart")
|
||||||
|
|
|
||||||
|
|
@ -1023,6 +1023,10 @@ EVENT(animationiteration,
|
||||||
eAnimationIteration,
|
eAnimationIteration,
|
||||||
EventNameType_All,
|
EventNameType_All,
|
||||||
eAnimationEventClass)
|
eAnimationEventClass)
|
||||||
|
EVENT(animationcancel,
|
||||||
|
eAnimationCancel,
|
||||||
|
EventNameType_All,
|
||||||
|
eAnimationEventClass)
|
||||||
|
|
||||||
// Webkit-prefixed versions of Transition & Animation events, for web compat:
|
// Webkit-prefixed versions of Transition & Animation events, for web compat:
|
||||||
EVENT(webkitAnimationEnd,
|
EVENT(webkitAnimationEnd,
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ interface GlobalEventHandlers {
|
||||||
attribute EventHandler onmozpointerlockerror;
|
attribute EventHandler onmozpointerlockerror;
|
||||||
|
|
||||||
// CSS-Animation and CSS-Transition handlers.
|
// CSS-Animation and CSS-Transition handlers.
|
||||||
|
attribute EventHandler onanimationcancel;
|
||||||
attribute EventHandler onanimationend;
|
attribute EventHandler onanimationend;
|
||||||
attribute EventHandler onanimationiteration;
|
attribute EventHandler onanimationiteration;
|
||||||
attribute EventHandler onanimationstart;
|
attribute EventHandler onanimationstart;
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,26 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||||
aField.Traverse(&aCallback, aName);
|
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
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif /* !defined(mozilla_css_AnimationCommon_h) */
|
#endif /* !defined(mozilla_css_AnimationCommon_h) */
|
||||||
|
|
|
||||||
|
|
@ -158,12 +158,8 @@ CSSAnimation::HasLowerCompositeOrderThan(const CSSAnimation& aOther) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CSSAnimation::QueueEvents()
|
CSSAnimation::QueueEvents(StickyTimeDuration aActiveTime)
|
||||||
{
|
{
|
||||||
if (!mEffect) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the animation is pending, we ignore animation events until we finish
|
// If the animation is pending, we ignore animation events until we finish
|
||||||
// pending.
|
// pending.
|
||||||
if (mPendingState != PendingState::NotPending) {
|
if (mPendingState != PendingState::NotPending) {
|
||||||
|
|
@ -198,39 +194,60 @@ CSSAnimation::QueueEvents()
|
||||||
}
|
}
|
||||||
nsAnimationManager* manager = presContext->AnimationManager();
|
nsAnimationManager* manager = presContext->AnimationManager();
|
||||||
|
|
||||||
ComputedTiming computedTiming = mEffect->GetComputedTiming();
|
|
||||||
|
|
||||||
ComputedTiming::AnimationPhase currentPhase = computedTiming.mPhase;
|
|
||||||
uint64_t currentIteration = computedTiming.mCurrentIteration;
|
|
||||||
if (currentPhase == mPreviousPhase &&
|
|
||||||
currentIteration == mPreviousIteration) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const StickyTimeDuration zeroDuration;
|
const StickyTimeDuration zeroDuration;
|
||||||
StickyTimeDuration intervalStartTime =
|
uint64_t currentIteration = 0;
|
||||||
std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay),
|
ComputedTiming::AnimationPhase currentPhase;
|
||||||
computedTiming.mActiveDuration),
|
StickyTimeDuration intervalStartTime;
|
||||||
zeroDuration);
|
StickyTimeDuration intervalEndTime;
|
||||||
StickyTimeDuration intervalEndTime =
|
StickyTimeDuration iterationStartTime;
|
||||||
std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay),
|
|
||||||
computedTiming.mActiveDuration),
|
|
||||||
zeroDuration);
|
|
||||||
|
|
||||||
uint64_t iterationBoundary = mPreviousIteration > currentIteration
|
if (!mEffect) {
|
||||||
? currentIteration + 1
|
currentPhase = GetAnimationPhaseWithoutEffect
|
||||||
: currentIteration;
|
<ComputedTiming::AnimationPhase>(*this);
|
||||||
StickyTimeDuration iterationStartTime =
|
} else {
|
||||||
computedTiming.mDuration.MultDouble(
|
ComputedTiming computedTiming = mEffect->GetComputedTiming();
|
||||||
(iterationBoundary - computedTiming.mIterationStart));
|
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 startTimeStamp = ElapsedTimeToTimeStamp(intervalStartTime);
|
||||||
TimeStamp endTimeStamp = ElapsedTimeToTimeStamp(intervalEndTime);
|
TimeStamp endTimeStamp = ElapsedTimeToTimeStamp(intervalEndTime);
|
||||||
TimeStamp iterationTimeStamp = ElapsedTimeToTimeStamp(iterationStartTime);
|
TimeStamp iterationTimeStamp = ElapsedTimeToTimeStamp(iterationStartTime);
|
||||||
|
|
||||||
AutoTArray<AnimationEventParams, 2> events;
|
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) {
|
switch (mPreviousPhase) {
|
||||||
case AnimationPhase::Null:
|
case AnimationPhase::Idle:
|
||||||
case AnimationPhase::Before:
|
case AnimationPhase::Before:
|
||||||
if (currentPhase == AnimationPhase::Active) {
|
if (currentPhase == AnimationPhase::Active) {
|
||||||
events.AppendElement(AnimationEventParams{ eAnimationStart,
|
events.AppendElement(AnimationEventParams{ eAnimationStart,
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ public:
|
||||||
, mIsStylePaused(false)
|
, mIsStylePaused(false)
|
||||||
, mPauseShouldStick(false)
|
, mPauseShouldStick(false)
|
||||||
, mNeedsNewAnimationIndexWhenRun(false)
|
, mNeedsNewAnimationIndexWhenRun(false)
|
||||||
, mPreviousPhase(ComputedTiming::AnimationPhase::Null)
|
, mPreviousPhase(ComputedTiming::AnimationPhase::Idle)
|
||||||
, mPreviousIteration(0)
|
, mPreviousIteration(0)
|
||||||
{
|
{
|
||||||
// We might need to drop this assertion once we add a script-accessible
|
// We might need to drop this assertion once we add a script-accessible
|
||||||
|
|
@ -110,8 +110,6 @@ public:
|
||||||
void PauseFromStyle();
|
void PauseFromStyle();
|
||||||
void CancelFromStyle() override
|
void CancelFromStyle() override
|
||||||
{
|
{
|
||||||
mOwningElement = OwningElementRef();
|
|
||||||
|
|
||||||
// When an animation is disassociated with style it enters an odd state
|
// When an animation is disassociated with style it enters an odd state
|
||||||
// where its composite order is undefined until it first transitions
|
// where its composite order is undefined until it first transitions
|
||||||
// out of the idle state.
|
// out of the idle state.
|
||||||
|
|
@ -126,10 +124,15 @@ public:
|
||||||
mNeedsNewAnimationIndexWhenRun = true;
|
mNeedsNewAnimationIndexWhenRun = true;
|
||||||
|
|
||||||
Animation::CancelFromStyle();
|
Animation::CancelFromStyle();
|
||||||
|
|
||||||
|
// We need to do this *after* calling CancelFromStyle() since
|
||||||
|
// CancelFromStyle might synchronously trigger a cancel event for which
|
||||||
|
// we need an owning element to target the event at.
|
||||||
|
mOwningElement = OwningElementRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tick() override;
|
void Tick() override;
|
||||||
void QueueEvents();
|
void QueueEvents(StickyTimeDuration aActiveTime = StickyTimeDuration());
|
||||||
|
|
||||||
bool IsStylePaused() const { return mIsStylePaused; }
|
bool IsStylePaused() const { return mIsStylePaused; }
|
||||||
|
|
||||||
|
|
@ -158,6 +161,10 @@ public:
|
||||||
// reflect changes to that markup.
|
// reflect changes to that markup.
|
||||||
bool IsTiedToMarkup() const { return mOwningElement.IsSet(); }
|
bool IsTiedToMarkup() const { return mOwningElement.IsSet(); }
|
||||||
|
|
||||||
|
void MaybeQueueCancelEvent(StickyTimeDuration aActiveTime) override {
|
||||||
|
QueueEvents(aActiveTime);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~CSSAnimation()
|
virtual ~CSSAnimation()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,6 @@ using mozilla::dom::KeyframeEffectReadOnly;
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::css;
|
using namespace mozilla::css;
|
||||||
|
|
||||||
typedef mozilla::ComputedTiming::AnimationPhase AnimationPhase;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct TransitionEventParams {
|
struct TransitionEventParams {
|
||||||
EventMessage mMessage;
|
EventMessage mMessage;
|
||||||
|
|
@ -203,7 +201,7 @@ CSSTransition::QueueEvents(StickyTimeDuration aActiveTime)
|
||||||
StickyTimeDuration intervalEndTime;
|
StickyTimeDuration intervalEndTime;
|
||||||
|
|
||||||
if (!mEffect) {
|
if (!mEffect) {
|
||||||
currentPhase = GetTransitionPhaseWithoutEffect();
|
currentPhase = GetAnimationPhaseWithoutEffect<TransitionPhase>(*this);
|
||||||
intervalStartTime = zeroDuration;
|
intervalStartTime = zeroDuration;
|
||||||
intervalEndTime = zeroDuration;
|
intervalEndTime = zeroDuration;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -329,23 +327,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
|
void
|
||||||
CSSTransition::Tick()
|
CSSTransition::Tick()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -162,18 +162,6 @@ public:
|
||||||
|
|
||||||
Animation::CancelFromStyle();
|
Animation::CancelFromStyle();
|
||||||
|
|
||||||
// The above call to Animation::CancelFromStyle may cause a transitioncancel
|
|
||||||
// event to be queued. However, it will also remove the transition from its
|
|
||||||
// timeline. If this transition was the last animation attached to
|
|
||||||
// the timeline, the timeline will stop observing the refresh driver and
|
|
||||||
// there may be no subsequent tick fro dispatching animation events.
|
|
||||||
//
|
|
||||||
// To ensure the cancel event is dispatched we tell the timeline it needs to
|
|
||||||
// observe the refresh driver for at least one more tick.
|
|
||||||
if (mTimeline) {
|
|
||||||
mTimeline->NotifyAnimationUpdated(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is important we do this *after* calling CancelFromStyle().
|
// It is important we do this *after* calling CancelFromStyle().
|
||||||
// This is because CancelFromStyle() will end up posting a restyle and
|
// This is because CancelFromStyle() will end up posting a restyle and
|
||||||
// that restyle should target the *transitions* level of the cascade.
|
// that restyle should target the *transitions* level of the cascade.
|
||||||
|
|
@ -245,9 +233,6 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
enum class TransitionPhase;
|
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
|
// The (pseudo-)element whose computed transition-property refers to this
|
||||||
// transition (if any).
|
// transition (if any).
|
||||||
|
|
@ -272,7 +257,7 @@ protected:
|
||||||
// to be queued on this tick.
|
// to be queued on this tick.
|
||||||
// See: https://drafts.csswg.org/css-transitions-2/#transition-phase
|
// See: https://drafts.csswg.org/css-transitions-2/#transition-phase
|
||||||
enum class TransitionPhase {
|
enum class TransitionPhase {
|
||||||
Idle = static_cast<int>(ComputedTiming::AnimationPhase::Null),
|
Idle = static_cast<int>(ComputedTiming::AnimationPhase::Idle),
|
||||||
Before = static_cast<int>(ComputedTiming::AnimationPhase::Before),
|
Before = static_cast<int>(ComputedTiming::AnimationPhase::Before),
|
||||||
Active = static_cast<int>(ComputedTiming::AnimationPhase::Active),
|
Active = static_cast<int>(ComputedTiming::AnimationPhase::Active),
|
||||||
After = static_cast<int>(ComputedTiming::AnimationPhase::After),
|
After = static_cast<int>(ComputedTiming::AnimationPhase::After),
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,7 @@ NS_EVENT_MESSAGE(eTransitionCancel)
|
||||||
NS_EVENT_MESSAGE(eAnimationStart)
|
NS_EVENT_MESSAGE(eAnimationStart)
|
||||||
NS_EVENT_MESSAGE(eAnimationEnd)
|
NS_EVENT_MESSAGE(eAnimationEnd)
|
||||||
NS_EVENT_MESSAGE(eAnimationIteration)
|
NS_EVENT_MESSAGE(eAnimationIteration)
|
||||||
|
NS_EVENT_MESSAGE(eAnimationCancel)
|
||||||
|
|
||||||
// Webkit-prefixed versions of Transition & Animation events, for web compat:
|
// Webkit-prefixed versions of Transition & Animation events, for web compat:
|
||||||
NS_EVENT_MESSAGE(eWebkitTransitionEnd)
|
NS_EVENT_MESSAGE(eWebkitTransitionEnd)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue