author | Hiroyuki Ikezoe <hikezoe@mozilla.com> |
Sat, 27 Jan 2018 21:17:27 +0900 | |
changeset 401190 | 3e89823dbf4641c2e413736d4a06a1502fb8515d |
parent 401189 | ca2c833ff617b7066920161087cff2abc8f88367 |
child 401191 | 71e7e9e19c258b16b871e2a3167b8e7c4f8aed21 |
push id | 99310 |
push user | shindli@mozilla.com |
push date | Mon, 29 Jan 2018 10:00:52 +0000 |
treeherder | mozilla-inbound@47f092f7aa12 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | birtles, masayuki |
bugs | 1415780, 1433008 |
milestone | 60.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/animation/AnimationEventDispatcher.h +++ b/dom/animation/AnimationEventDispatcher.h @@ -4,49 +4,126 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_AnimationEventDispatcher_h #define mozilla_AnimationEventDispatcher_h #include <algorithm> // For <std::stable_sort> #include "mozilla/AnimationComparator.h" +#include "mozilla/Assertions.h" +#include "mozilla/ContentEvents.h" #include "mozilla/EventDispatcher.h" +#include "mozilla/Variant.h" +#include "nsCSSProps.h" #include "nsCycleCollectionParticipant.h" class nsPresContext; namespace mozilla { -template <class EventInfo> +struct AnimationEventInfo +{ + RefPtr<dom::Element> mElement; + RefPtr<dom::Animation> mAnimation; + TimeStamp mTimeStamp; + + typedef Variant<InternalTransitionEvent, InternalAnimationEvent> EventVariant; + EventVariant mEvent; + + // For CSS animation events + AnimationEventInfo(nsAtom* aAnimationName, + const NonOwningAnimationTarget& aTarget, + EventMessage aMessage, + double aElapsedTime, + const TimeStamp& aTimeStamp, + dom::Animation* aAnimation) + : mElement(aTarget.mElement) + , mAnimation(aAnimation) + , mTimeStamp(aTimeStamp) + , mEvent(EventVariant(InternalAnimationEvent(true, aMessage))) + { + InternalAnimationEvent& event = mEvent.as<InternalAnimationEvent>(); + + aAnimationName->ToString(event.mAnimationName); + // XXX Looks like nobody initialize WidgetEvent::time + event.mElapsedTime = aElapsedTime; + event.mPseudoElement = + nsCSSPseudoElements::PseudoTypeAsString(aTarget.mPseudoType); + } + + // For CSS transition events + AnimationEventInfo(nsCSSPropertyID aProperty, + const NonOwningAnimationTarget& aTarget, + EventMessage aMessage, + double aElapsedTime, + const TimeStamp& aTimeStamp, + dom::Animation* aAnimation) + : mElement(aTarget.mElement) + , mAnimation(aAnimation) + , mTimeStamp(aTimeStamp) + , mEvent(EventVariant(InternalTransitionEvent(true, aMessage))) + { + InternalTransitionEvent& event = mEvent.as<InternalTransitionEvent>(); + + event.mPropertyName = + NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aProperty)); + // XXX Looks like nobody initialize WidgetEvent::time + event.mElapsedTime = aElapsedTime; + event.mPseudoElement = + nsCSSPseudoElements::PseudoTypeAsString(aTarget.mPseudoType); + } + + // InternalAnimationEvent and InternalTransitionEvent don't support + // copy-construction, so we need to ourselves in order to work with nsTArray. + // + // FIXME: Drop this copy constructor and copy assignment below once + // WidgetEvent have move constructor and move assignment (bug 1433008). + AnimationEventInfo(const AnimationEventInfo& aOther) = default; + AnimationEventInfo& operator=(const AnimationEventInfo& aOther) = default; + + WidgetEvent* AsWidgetEvent() + { + if (mEvent.is<InternalTransitionEvent>()) { + return &mEvent.as<InternalTransitionEvent>(); + } + if (mEvent.is<InternalAnimationEvent>()) { + return &mEvent.as<InternalAnimationEvent>(); + } + + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected event type"); + return nullptr; + } +}; + class AnimationEventDispatcher final { public: AnimationEventDispatcher() : mIsSorted(true) { } - void QueueEvents(nsTArray<EventInfo>&& aEvents) + void QueueEvents(nsTArray<AnimationEventInfo>&& aEvents) { - mPendingEvents.AppendElements(Forward<nsTArray<EventInfo>>(aEvents)); + mPendingEvents.AppendElements(Move(aEvents)); mIsSorted = false; } // This is exposed as a separate method so that when we are dispatching // *both* transition events and animation events we can sort both lists // once using the current state of the document before beginning any // dispatch. void SortEvents() { if (mIsSorted) { return; } // FIXME: Replace with mPendingEvents.StableSort when bug 1147091 is // fixed. std::stable_sort(mPendingEvents.begin(), mPendingEvents.end(), - EventInfoLessThan()); + AnimationEventInfoLessThan()); mIsSorted = true; } // Takes a reference to the owning manager's pres context so it can // detect if the pres context is destroyed while dispatching one of // the events. // // This will call SortEvents automatically if it has not already been @@ -58,18 +135,23 @@ public: } SortEvents(); EventArray events; mPendingEvents.SwapElements(events); // mIsSorted will be set to true by SortEvents above, and we leave it // that way since mPendingEvents is now empty - for (EventInfo& info : events) { - EventDispatcher::Dispatch(info.mElement, aPresContext, &info.mEvent); + for (AnimationEventInfo& info : events) { + MOZ_ASSERT(!info.AsWidgetEvent()->mFlags.mIsBeingDispatched && + !info.AsWidgetEvent()->mFlags.mDispatchedAtLeastOnce, + "The WidgetEvent should be fresh"); + EventDispatcher::Dispatch(info.mElement, + aPresContext, + info.AsWidgetEvent()); if (!aPresContext) { break; } } } void ClearEventQueue() @@ -78,59 +160,57 @@ public: mIsSorted = true; } bool HasQueuedEvents() const { return !mPendingEvents.IsEmpty(); } // Methods for supporting cycle-collection void Traverse(nsCycleCollectionTraversalCallback* aCallback, const char* aName) { - for (EventInfo& info : mPendingEvents) { + for (AnimationEventInfo& info : mPendingEvents) { ImplCycleCollectionTraverse(*aCallback, info.mElement, aName); ImplCycleCollectionTraverse(*aCallback, info.mAnimation, aName); } } void Unlink() { ClearEventQueue(); } protected: - class EventInfoLessThan + class AnimationEventInfoLessThan { public: - bool operator()(const EventInfo& a, const EventInfo& b) const + bool operator()(const AnimationEventInfo& a, const AnimationEventInfo& b) const { if (a.mTimeStamp != b.mTimeStamp) { // Null timestamps sort first if (a.mTimeStamp.IsNull() || b.mTimeStamp.IsNull()) { return a.mTimeStamp.IsNull(); } else { return a.mTimeStamp < b.mTimeStamp; } } AnimationPtrComparator<RefPtr<dom::Animation>> comparator; return comparator.LessThan(a.mAnimation, b.mAnimation); } }; - typedef nsTArray<EventInfo> EventArray; + typedef nsTArray<AnimationEventInfo> EventArray; EventArray mPendingEvents; bool mIsSorted; }; -template <class EventInfo> inline void -ImplCycleCollectionUnlink(AnimationEventDispatcher<EventInfo>& aField) +ImplCycleCollectionUnlink(AnimationEventDispatcher& aField) { aField.Unlink(); } -template <class EventInfo> inline void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, - AnimationEventDispatcher<EventInfo>& aField, + AnimationEventDispatcher& aField, const char* aName, uint32_t aFlags = 0) { aField.Traverse(&aCallback, aName); } } // namespace mozilla
--- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -16,23 +16,23 @@ #include "mozilla/TimingParams.h" #include "nsContentUtils.h" class nsIFrame; class nsPresContext; namespace mozilla { enum class CSSPseudoElementType : uint8_t; -template <class EventInfo> class AnimationEventDispatcher; +class AnimationEventDispatcher; namespace dom { class Element; } -template <class AnimationType, class AnimationEventType> +template <class AnimationType> class CommonAnimationManager { public: explicit CommonAnimationManager(nsPresContext *aPresContext) : mPresContext(aPresContext) { } // NOTE: This can return null after Disconnect(). @@ -67,20 +67,19 @@ public: nsAutoAnimationMutationBatch mb(aElement->OwnerDoc()); collection->Destroy(); } /** * Add pending events. */ - void QueueEvents(nsTArray<AnimationEventType>&& aEvents) + void QueueEvents(nsTArray<AnimationEventInfo>&& aEvents) { - mEventDispatcher.QueueEvents( - mozilla::Forward<nsTArray<AnimationEventType>>(aEvents)); + mEventDispatcher.QueueEvents(Move(aEvents)); } void SortEvents() { mEventDispatcher.SortEvents(); } void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); } protected: virtual ~CommonAnimationManager() { @@ -97,17 +96,17 @@ protected: mElementCollections.getFirst()) { head->Destroy(); // Note: this removes 'head' from mElementCollections. } } LinkedList<AnimationCollection<AnimationType>> mElementCollections; nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect) - mozilla::AnimationEventDispatcher<AnimationEventType> mEventDispatcher; + mozilla::AnimationEventDispatcher mEventDispatcher; }; /** * Utility class for referencing the element that created a CSS animation or * transition. It is non-owning (i.e. it uses a raw pointer) since it is only * expected to be set by the owned animation while it actually being managed * by the owning element. *
--- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -237,19 +237,19 @@ CSSAnimation::QueueEvents(const StickyTi auto appendAnimationEvent = [&](EventMessage aMessage, const StickyTimeDuration& aElapsedTime, const TimeStamp& aTimeStamp) { double elapsedTime = aElapsedTime.ToSeconds(); if (aMessage == eAnimationCancel) { elapsedTime = nsRFPService::ReduceTimePrecisionAsSecs(elapsedTime); } - events.AppendElement(AnimationEventInfo(mOwningElement.Target(), + events.AppendElement(AnimationEventInfo(mAnimationName, + mOwningElement.Target(), aMessage, - mAnimationName, elapsedTime, aTimeStamp, this)); }; // Handle cancel event first if ((mPreviousPhase != AnimationPhase::Idle && mPreviousPhase != AnimationPhase::After) &&
--- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -29,52 +29,16 @@ class KeyframeEffectReadOnly; class Promise; } /* namespace dom */ class GeckoStyleContext; class ServoStyleContext; enum class CSSPseudoElementType : uint8_t; struct NonOwningAnimationTarget; -struct AnimationEventInfo { - RefPtr<dom::Element> mElement; - RefPtr<dom::Animation> mAnimation; - InternalAnimationEvent mEvent; - TimeStamp mTimeStamp; - - AnimationEventInfo(const NonOwningAnimationTarget& aTarget, - EventMessage aMessage, - nsAtom* aAnimationName, - double aElapsedTime, - const TimeStamp& aTimeStamp, - dom::Animation* aAnimation) - : mElement(aTarget.mElement) - , mAnimation(aAnimation) - , mEvent(true, aMessage) - , mTimeStamp(aTimeStamp) - { - // XXX Looks like nobody initialize WidgetEvent::time - aAnimationName->ToString(mEvent.mAnimationName); - mEvent.mElapsedTime = aElapsedTime; - mEvent.mPseudoElement = - nsCSSPseudoElements::PseudoTypeAsString(aTarget.mPseudoType); - } - - // InternalAnimationEvent doesn't support copy-construction, so we need - // to ourselves in order to work with nsTArray - AnimationEventInfo(const AnimationEventInfo& aOther) - : mElement(aOther.mElement) - , mAnimation(aOther.mAnimation) - , mEvent(true, aOther.mEvent.mMessage) - , mTimeStamp(aOther.mTimeStamp) - { - mEvent.AssignAnimationEventData(aOther.mEvent, false); - } -}; - namespace dom { class CSSAnimation final : public Animation { public: explicit CSSAnimation(nsIGlobalObject* aGlobal, nsAtom* aAnimationName) : dom::Animation(aGlobal) @@ -305,23 +269,21 @@ struct AnimationTypeTraits<dom::CSSAnima { return nsGkAtoms::animationsOfAfterProperty; } }; } /* namespace mozilla */ class nsAnimationManager final - : public mozilla::CommonAnimationManager<mozilla::dom::CSSAnimation, - mozilla::AnimationEventInfo> + : public mozilla::CommonAnimationManager<mozilla::dom::CSSAnimation> { public: explicit nsAnimationManager(nsPresContext *aPresContext) - : mozilla::CommonAnimationManager<mozilla::dom::CSSAnimation, - mozilla::AnimationEventInfo>(aPresContext) + : mozilla::CommonAnimationManager<mozilla::dom::CSSAnimation>(aPresContext) { } NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsAnimationManager) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsAnimationManager) typedef mozilla::AnimationCollection<mozilla::dom::CSSAnimation> CSSAnimationCollection;
--- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -244,31 +244,31 @@ CSSTransition::QueueEvents(const StickyT if (mPendingState != PendingState::NotPending && (mPreviousTransitionPhase == TransitionPhase::Idle || mPreviousTransitionPhase == TransitionPhase::Pending)) { currentPhase = TransitionPhase::Pending; } - AutoTArray<TransitionEventInfo, 3> events; + AutoTArray<AnimationEventInfo, 3> events; auto appendTransitionEvent = [&](EventMessage aMessage, const StickyTimeDuration& aElapsedTime, const TimeStamp& aTimeStamp) { double elapsedTime = aElapsedTime.ToSeconds(); if (aMessage == eTransitionCancel) { elapsedTime = nsRFPService::ReduceTimePrecisionAsSecs(elapsedTime); } - events.AppendElement(TransitionEventInfo(mOwningElement.Target(), - aMessage, - TransitionProperty(), - elapsedTime, - aTimeStamp, - this)); + events.AppendElement(AnimationEventInfo(TransitionProperty(), + mOwningElement.Target(), + aMessage, + elapsedTime, + aTimeStamp, + this)); }; // Handle cancel events first if ((mPreviousTransitionPhase != TransitionPhase::Idle && mPreviousTransitionPhase != TransitionPhase::After) && currentPhase == TransitionPhase::Idle) { TimeStamp activeTimeStamp = ElapsedTimeToTimeStamp(aActiveTime); appendTransitionEvent(eTransitionCancel, aActiveTime, activeTimeStamp);
--- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -5,23 +5,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Code to start and animate CSS transitions. */ #ifndef nsTransitionManager_h_ #define nsTransitionManager_h_ #include "mozilla/ComputedTiming.h" -#include "mozilla/ContentEvents.h" #include "mozilla/EffectCompositor.h" // For EffectCompositor::CascadeLevel -#include "mozilla/MemoryReporting.h" #include "mozilla/dom/Animation.h" #include "mozilla/dom/KeyframeEffectReadOnly.h" #include "AnimationCommon.h" -#include "nsCSSProps.h" class nsIGlobalObject; class nsStyleContext; class nsPresContext; class nsCSSPropertyIDSet; namespace mozilla { enum class CSSPseudoElementType : uint8_t; @@ -296,63 +293,24 @@ struct AnimationTypeTraits<dom::CSSTrans return nsGkAtoms::transitionsOfBeforeProperty; } static nsAtom* AfterPropertyAtom() { return nsGkAtoms::transitionsOfAfterProperty; } }; -struct TransitionEventInfo { - RefPtr<dom::Element> mElement; - RefPtr<dom::Animation> mAnimation; - InternalTransitionEvent mEvent; - TimeStamp mTimeStamp; - - TransitionEventInfo(const NonOwningAnimationTarget& aTarget, - EventMessage aMessage, - nsCSSPropertyID aProperty, - double aElapsedTime, - const TimeStamp& aTimeStamp, - dom::Animation* aAnimation) - : mElement(aTarget.mElement) - , mAnimation(aAnimation) - , mEvent(true, aMessage) - , mTimeStamp(aTimeStamp) - { - // XXX Looks like nobody initialize WidgetEvent::time - mEvent.mPropertyName = - NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aProperty)); - mEvent.mElapsedTime = aElapsedTime; - mEvent.mPseudoElement = - nsCSSPseudoElements::PseudoTypeAsString(aTarget.mPseudoType); - } - - // InternalTransitionEvent doesn't support copy-construction, so we need - // to ourselves in order to work with nsTArray - TransitionEventInfo(const TransitionEventInfo& aOther) - : mElement(aOther.mElement) - , mAnimation(aOther.mAnimation) - , mEvent(aOther.mEvent) - , mTimeStamp(aOther.mTimeStamp) - { - mEvent.AssignTransitionEventData(aOther.mEvent, false); - } -}; - } // namespace mozilla class nsTransitionManager final - : public mozilla::CommonAnimationManager<mozilla::dom::CSSTransition, - mozilla::TransitionEventInfo> + : public mozilla::CommonAnimationManager<mozilla::dom::CSSTransition> { public: explicit nsTransitionManager(nsPresContext *aPresContext) - : mozilla::CommonAnimationManager<mozilla::dom::CSSTransition, - mozilla::TransitionEventInfo>(aPresContext) + : mozilla::CommonAnimationManager<mozilla::dom::CSSTransition>(aPresContext) , mInAnimationOnlyStyleUpdate(false) { } NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsTransitionManager) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransitionManager) typedef mozilla::AnimationCollection<mozilla::dom::CSSTransition>