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 : 405c8232e93c54a073c722a4332873af02daa870
This commit is contained in:
Hiroyuki Ikezoe 2018-01-27 21:17:27 +09:00
Родитель 21a53275cd
Коммит 7828b6be59
10 изменённых файлов: 45 добавлений и 73 удалений

Просмотреть файл

@ -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<AnimationEventInfo>&& 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<AnimationEventInfo> EventArray;
EventArray mPendingEvents;
bool mIsSorted;

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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<mozilla::EventStateManager> mEventManager;
RefPtr<nsRefreshDriver> mRefreshDriver;
RefPtr<mozilla::AnimationEventDispatcher> mAnimationEventDispatcher;
RefPtr<mozilla::EffectCompositor> mEffectCompositor;
RefPtr<nsTransitionManager> mTransitionManager;
RefPtr<nsAnimationManager> mAnimationManager;

Просмотреть файл

@ -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();
}
}

Просмотреть файл

@ -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<AnimationEventInfo>&& aEvents)
{
mEventDispatcher->QueueEvents(Move(aEvents));
}
void SortEvents() { mEventDispatcher->SortEvents(); }
void ClearEventQueue() { mEventDispatcher->ClearEventQueue(); }
protected:
virtual ~CommonAnimationManager()
{
@ -101,8 +87,6 @@ protected:
LinkedList<AnimationCollection<AnimationType>> mElementCollections;
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
RefPtr<mozilla::AnimationEventDispatcher> mEventDispatcher;
};
/**

Просмотреть файл

@ -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<CSSAnimation>

Просмотреть файл

@ -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<mozilla::dom::CSSAnimation>
CSSAnimationCollection;
@ -310,12 +310,6 @@ public:
mozilla::CSSPseudoElementType aPseudoType,
const mozilla::ServoStyleContext* aComputedValues);
void DispatchEvents()
{
RefPtr<nsAnimationManager> 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).

Просмотреть файл

@ -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,

Просмотреть файл

@ -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<mozilla::dom::CSSTransition>
CSSTransitionCollection;
@ -363,12 +363,6 @@ public:
return mInAnimationOnlyStyleUpdate;
}
void DispatchEvents()
{
RefPtr<nsTransitionManager> kungFuDeathGrip(this);
mEventDispatcher->DispatchEvents(mPresContext);
}
protected:
virtual ~nsTransitionManager() {}