From 99f98b1bd65f19c342430a147270ad56cfd08cba Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Sat, 27 Jan 2018 16:55:45 +0900 Subject: [PATCH] Bug 1415780 - Let nsPresContext have AnimationEventDispatcher. r=birtles Now we sort CSS animation/transition events by scheduled event time prior to compositor order. SortEvents() will be a private method in the next patch in this patch series. MozReview-Commit-ID: ICkOayquN0f --HG-- extra : rebase_source : 52226c33a511451c31d4c3fef94ff02de8462256 --- dom/animation/AnimationEventDispatcher.h | 32 ++++++++++++++---------- layout/base/PresShell.cpp | 4 +-- layout/base/nsPresContext.cpp | 12 ++++++--- layout/base/nsPresContext.h | 6 +++++ layout/base/nsRefreshDriver.cpp | 12 ++------- layout/style/AnimationCommon.h | 16 ------------ layout/style/nsAnimationManager.cpp | 8 ++---- layout/style/nsAnimationManager.h | 10 ++------ layout/style/nsTransitionManager.cpp | 8 ++---- layout/style/nsTransitionManager.h | 10 ++------ 10 files changed, 45 insertions(+), 73 deletions(-) diff --git a/dom/animation/AnimationEventDispatcher.h b/dom/animation/AnimationEventDispatcher.h index 001412ccccb7..d59350b6fd4e 100644 --- a/dom/animation/AnimationEventDispatcher.h +++ b/dom/animation/AnimationEventDispatcher.h @@ -97,21 +97,28 @@ struct AnimationEventInfo class AnimationEventDispatcher final { public: - AnimationEventDispatcher() : mIsSorted(true) { } + explicit AnimationEventDispatcher(nsPresContext* aPresContext) + : mPresContext(aPresContext) + , mIsSorted(true) + { + } NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEventDispatcher) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnimationEventDispatcher) + void Disconnect() { + mPresContext = nullptr; + } + void QueueEvents(nsTArray&& 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. + // Sort all pending CSS animation/transition events by scheduled event time + // and composite order. + // https://drafts.csswg.org/web-animations/#update-animations-and-send-events void SortEvents() { if (mIsSorted) { @@ -125,15 +132,11 @@ public: 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 // called. - void DispatchEvents(nsPresContext* const & aPresContext) + void DispatchEvents() { - if (!aPresContext || mPendingEvents.IsEmpty()) { + if (!mPresContext || mPendingEvents.IsEmpty()) { return; } @@ -148,10 +151,12 @@ public: !info.AsWidgetEvent()->mFlags.mDispatchedAtLeastOnce, "The WidgetEvent should be fresh"); EventDispatcher::Dispatch(info.mElement, - aPresContext, + mPresContext, info.AsWidgetEvent()); - if (!aPresContext) { + // Bail out if our mPresContext was nullified due to destroying the pres + // context. + if (!mPresContext) { break; } } @@ -186,6 +191,7 @@ private: } }; + nsPresContext* mPresContext; typedef nsTArray EventArray; EventArray mPendingEvents; bool mIsSorted; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 6770ced9b4e7..6ae70b501d3d 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -8,6 +8,7 @@ #include "mozilla/PresShell.h" +#include "mozilla/AnimationEventDispatcher.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" #include "mozilla/StyleSheetInlines.h" @@ -1362,8 +1363,7 @@ PresShell::Destroy() } if (mPresContext) { - mPresContext->AnimationManager()->ClearEventQueue(); - mPresContext->TransitionManager()->ClearEventQueue(); + mPresContext->AnimationEventDispatcher()->ClearEventQueue(); } // Revoke any pending events. We need to do this and cancel pending reflows diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index ffb183bf25a5..e25ef4ff4a8d 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -48,6 +48,7 @@ #include "gfxPlatform.h" #include "nsCSSRules.h" #include "nsFontFaceLoader.h" +#include "mozilla/AnimationEventDispatcher.h" #include "mozilla/EffectCompositor.h" #include "mozilla/EventListenerManager.h" #include "prenv.h" @@ -442,8 +443,7 @@ nsPresContext::LastRelease() NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnimationManager); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransitionManager); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnimationEventDispatcher); NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument); // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // not xpcom NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEffectCompositor); @@ -457,8 +457,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnimationManager); - NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransitionManager); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnimationEventDispatcher); NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument); NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeviceContext); // worth bothering? NS_IMPL_CYCLE_COLLECTION_UNLINK(mEffectCompositor); @@ -888,6 +887,7 @@ nsPresContext::Init(nsDeviceContext* aDeviceContext) mEventManager = new mozilla::EventStateManager(); + mAnimationEventDispatcher = new mozilla::AnimationEventDispatcher(this); mEffectCompositor = new mozilla::EffectCompositor(this); mTransitionManager = new nsTransitionManager(this); mAnimationManager = new nsAnimationManager(this); @@ -1066,6 +1066,10 @@ nsPresContext::DetachShell() mShell = nullptr; + if (mAnimationEventDispatcher) { + mAnimationEventDispatcher->Disconnect(); + mAnimationEventDispatcher = nullptr; + } if (mEffectCompositor) { mEffectCompositor->Disconnect(); mEffectCompositor = nullptr; diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index b200c6e86966..d6b6a3903e58 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -73,6 +73,7 @@ class nsDeviceContext; class gfxMissingFontRecorder; namespace mozilla { +class AnimationEventDispatcher; class EffectCompositor; class Encoding; class EventStateManager; @@ -236,6 +237,10 @@ public: nsCSSFrameConstructor* FrameConstructor() { return PresShell()->FrameConstructor(); } + mozilla::AnimationEventDispatcher* AnimationEventDispatcher() + { + return mAnimationEventDispatcher; + } mozilla::EffectCompositor* EffectCompositor() { return mEffectCompositor; } nsTransitionManager* TransitionManager() { return mTransitionManager; } nsAnimationManager* AnimationManager() { return mAnimationManager; } @@ -1296,6 +1301,7 @@ protected: // from gfx back to layout. RefPtr mEventManager; RefPtr mRefreshDriver; + RefPtr mAnimationEventDispatcher; RefPtr mEffectCompositor; RefPtr mTransitionManager; RefPtr mAnimationManager; diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 31c9839fd58a..df86f3b78e01 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -25,6 +25,7 @@ #include "WinUtils.h" #endif +#include "mozilla/AnimationEventDispatcher.h" #include "mozilla/ArrayUtils.h" #include "mozilla/AutoRestore.h" #include "mozilla/IntegerRange.h" @@ -1652,16 +1653,7 @@ nsRefreshDriver::DispatchAnimationEvents() continue; } - context->TransitionManager()->SortEvents(); - context->AnimationManager()->SortEvents(); - - // Dispatch transition events first since transitions conceptually sit - // below animations in terms of compositing order. - context->TransitionManager()->DispatchEvents(); - // Check that the presshell has not been destroyed - if (context->GetPresShell()) { - context->AnimationManager()->DispatchEvents(); - } + context->AnimationEventDispatcher()->DispatchEvents(); } } diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index f4124635e4e6..7b8c61533fb4 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -8,7 +8,6 @@ #define mozilla_css_AnimationCommon_h #include "mozilla/AnimationCollection.h" -#include "mozilla/AnimationEventDispatcher.h" #include "mozilla/LinkedList.h" #include "mozilla/dom/Animation.h" #include "mozilla/Attributes.h" // For MOZ_NON_OWNING_REF @@ -21,7 +20,6 @@ class nsPresContext; namespace mozilla { enum class CSSPseudoElementType : uint8_t; -class AnimationEventDispatcher; namespace dom { class Element; @@ -33,7 +31,6 @@ public: explicit CommonAnimationManager(nsPresContext *aPresContext) : mPresContext(aPresContext) { - mEventDispatcher = new AnimationEventDispatcher(); } // NOTE: This can return null after Disconnect(). @@ -70,17 +67,6 @@ public: collection->Destroy(); } - /** - * Add pending events. - */ - void QueueEvents(nsTArray&& aEvents) - { - mEventDispatcher->QueueEvents(Move(aEvents)); - } - - void SortEvents() { mEventDispatcher->SortEvents(); } - void ClearEventQueue() { mEventDispatcher->ClearEventQueue(); } - protected: virtual ~CommonAnimationManager() { @@ -101,8 +87,6 @@ protected: LinkedList> mElementCollections; nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect) - - RefPtr mEventDispatcher; }; /** diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index ba9b71fd55d2..6d636937148b 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -8,6 +8,7 @@ #include "nsTransitionManager.h" #include "mozilla/dom/CSSAnimationBinding.h" +#include "mozilla/AnimationEventDispatcher.h" #include "mozilla/AnimationTarget.h" #include "mozilla/EffectCompositor.h" #include "mozilla/EffectSet.h" @@ -299,7 +300,7 @@ CSSAnimation::QueueEvents(const StickyTimeDuration& aActiveTime) mPreviousIteration = currentIteration; if (!events.IsEmpty()) { - presContext->AnimationManager()->QueueEvents(Move(events)); + presContext->AnimationEventDispatcher()->QueueEvents(Move(events)); } } @@ -317,11 +318,6 @@ CSSAnimation::UpdateTiming(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag) ////////////////////////// nsAnimationManager //////////////////////////// -NS_IMPL_CYCLE_COLLECTION(nsAnimationManager, mEventDispatcher) - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsAnimationManager, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsAnimationManager, Release) - // Find the matching animation by |aName| in the old list // of animations and remove the matched animation from the list. static already_AddRefed diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index df803eb8695b..39dac93ab4f6 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -14,6 +14,7 @@ #include "mozilla/Keyframe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/TimeStamp.h" +#include "nsISupportsImpl.h" class nsIGlobalObject; class nsStyleContext; @@ -282,8 +283,7 @@ public: { } - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsAnimationManager) - NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsAnimationManager) + NS_INLINE_DECL_REFCOUNTING(nsAnimationManager) typedef mozilla::AnimationCollection CSSAnimationCollection; @@ -310,12 +310,6 @@ public: mozilla::CSSPseudoElementType aPseudoType, const mozilla::ServoStyleContext* aComputedValues); - void DispatchEvents() - { - RefPtr kungFuDeathGrip(this); - mEventDispatcher->DispatchEvents(mPresContext); - } - // Utility function to walk through |aIter| to find the Keyframe with // matching offset and timing function but stopping as soon as the offset // differs from |aOffset| (i.e. it assumes a sorted iterator). diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 3b5c541884fe..13991bd86e01 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -19,6 +19,7 @@ #include "nsRuleProcessorData.h" #include "nsRuleWalker.h" #include "nsCSSPropertyIDSet.h" +#include "mozilla/AnimationEventDispatcher.h" #include "mozilla/EffectCompositor.h" #include "mozilla/EffectSet.h" #include "mozilla/EventDispatcher.h" @@ -336,7 +337,7 @@ CSSTransition::QueueEvents(const StickyTimeDuration& aActiveTime) mPreviousTransitionPhase = currentPhase; if (!events.IsEmpty()) { - presContext->TransitionManager()->QueueEvents(Move(events)); + presContext->AnimationEventDispatcher()->QueueEvents(Move(events)); } } @@ -422,11 +423,6 @@ CSSTransition::SetEffectFromStyle(dom::AnimationEffectReadOnly* aEffect) ////////////////////////// nsTransitionManager //////////////////////////// -NS_IMPL_CYCLE_COLLECTION(nsTransitionManager, mEventDispatcher) - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTransitionManager, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransitionManager, Release) - static inline bool ExtractNonDiscreteComputedValue(nsCSSPropertyID aProperty, GeckoStyleContext* aStyleContext, diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 09b298def5e0..67621abeb963 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -14,6 +14,7 @@ #include "mozilla/dom/Animation.h" #include "mozilla/dom/KeyframeEffectReadOnly.h" #include "AnimationCommon.h" +#include "nsISupportsImpl.h" class nsIGlobalObject; class nsStyleContext; @@ -310,8 +311,7 @@ public: { } - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsTransitionManager) - NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransitionManager) + NS_INLINE_DECL_REFCOUNTING(nsTransitionManager) typedef mozilla::AnimationCollection CSSTransitionCollection; @@ -363,12 +363,6 @@ public: return mInAnimationOnlyStyleUpdate; } - void DispatchEvents() - { - RefPtr kungFuDeathGrip(this); - mEventDispatcher->DispatchEvents(mPresContext); - } - protected: virtual ~nsTransitionManager() {}