Bug 1180125 part 3 - Extract DelayedEventDispatcher; r=dbaron

This patch extracts a utility class for queueing up a series of EventInfo
objects (of templated type) and then dispatching them. This covers the event
queuing behavior in nsAnimationManager so that we can reuse it in
nsTransitionManager.
This commit is contained in:
Brian Birtles 2015-07-29 10:57:39 +09:00
Родитель 9b391b0177
Коммит 6f36a11791
3 изменённых файлов: 86 добавлений и 58 удалений

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

@ -13,6 +13,7 @@
#include "nsChangeHint.h"
#include "nsCSSProperty.h"
#include "nsDisplayList.h" // For nsDisplayItem::Type
#include "mozilla/EventDispatcher.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/dom/Animation.h"
@ -511,6 +512,72 @@ private:
nsCSSPseudoElements::Type mPseudoType;
};
template <class EventInfo>
class DelayedEventDispatcher
{
public:
void QueueEvent(EventInfo&& aEventInfo)
{
mPendingEvents.AppendElement(mozilla::Forward<EventInfo>(aEventInfo));
}
// 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.
void DispatchEvents(nsPresContext* const & aPresContext)
{
if (!aPresContext || mPendingEvents.IsEmpty()) {
return;
}
EventArray events;
mPendingEvents.SwapElements(events);
// FIXME: Sort events here in timeline order, then document order
for (EventInfo& info : events) {
EventDispatcher::Dispatch(info.mElement, aPresContext, &info.mEvent);
if (!aPresContext) {
break;
}
}
}
void ClearEventQueue() { mPendingEvents.Clear(); }
bool HasQueuedEvents() const { return !mPendingEvents.IsEmpty(); }
// Methods for supporting cycle-collection
void Traverse(nsCycleCollectionTraversalCallback* aCallback,
const char* aName)
{
for (EventInfo& info : mPendingEvents) {
ImplCycleCollectionTraverse(*aCallback, info.mElement, aName);
}
}
void Unlink() { mPendingEvents.Clear(); }
protected:
typedef nsTArray<EventInfo> EventArray;
EventArray mPendingEvents;
};
template <class EventInfo>
inline void
ImplCycleCollectionUnlink(DelayedEventDispatcher<EventInfo>& aField)
{
aField.Unlink();
}
template <class EventInfo>
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
DelayedEventDispatcher<EventInfo>& aField,
const char* aName,
uint32_t aFlags = 0)
{
aField.Traverse(&aCallback, aName);
}
} // namespace mozilla
#endif /* !defined(mozilla_css_AnimationCommon_h) */

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

@ -7,7 +7,6 @@
#include "nsTransitionManager.h"
#include "mozilla/dom/CSSAnimationBinding.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/dom/DocumentTimeline.h"
@ -251,10 +250,9 @@ CSSAnimation::QueueEvents()
StickyTimeDuration elapsedTime =
std::min(StickyTimeDuration(mEffect->InitialAdvance()),
computedTiming.mActiveDuration);
AnimationEventInfo ei(owningElement, mAnimationName, NS_ANIMATION_START,
elapsedTime,
PseudoTypeAsString(owningPseudoType));
manager->QueueEvent(ei);
manager->QueueEvent(
AnimationEventInfo(owningElement, mAnimationName, NS_ANIMATION_START,
elapsedTime, PseudoTypeAsString(owningPseudoType)));
// Then have the shared code below append an 'animationend':
message = NS_ANIMATION_END;
} else {
@ -274,9 +272,9 @@ CSSAnimation::QueueEvents()
elapsedTime = computedTiming.mActiveDuration;
}
AnimationEventInfo ei(owningElement, mAnimationName, message, elapsedTime,
PseudoTypeAsString(owningPseudoType));
manager->QueueEvent(ei);
manager->QueueEvent(
AnimationEventInfo(owningElement, mAnimationName, message, elapsedTime,
PseudoTypeAsString(owningPseudoType)));
}
CommonAnimationManager*
@ -305,15 +303,7 @@ CSSAnimation::PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType)
////////////////////////// nsAnimationManager ////////////////////////////
NS_IMPL_CYCLE_COLLECTION_CLASS(nsAnimationManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsAnimationManager)
tmp->mPendingEvents.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsAnimationManager)
for (AnimationEventInfo& info : tmp->mPendingEvents) {
ImplCycleCollectionTraverse(cb, info.mElement, "mPendingEvents.mElement");
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION(nsAnimationManager, mEventDispatcher)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnimationManager)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnimationManager)
@ -366,7 +356,7 @@ nsAnimationManager::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mPendingEvents
// - mEventDispatcher
}
/* virtual */ size_t
@ -537,23 +527,17 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
collection->EnsureStyleRuleFor(refreshTime, EnsureStyleRule_IsNotThrottled);
// We don't actually dispatch the mPendingEvents now. We'll either
// We don't actually dispatch the pending events now. We'll either
// dispatch them the next time we get a refresh driver notification
// or the next time somebody calls
// nsPresShell::FlushPendingNotifications.
if (!mPendingEvents.IsEmpty()) {
if (mEventDispatcher.HasQueuedEvents()) {
mPresContext->Document()->SetNeedStyleFlush();
}
return GetAnimationRule(aElement, aStyleContext->GetPseudoType());
}
void
nsAnimationManager::QueueEvent(AnimationEventInfo& aEventInfo)
{
mPendingEvents.AppendElement(aEventInfo);
}
struct KeyframeData {
float mKey;
uint32_t mIndex; // store original order since sort algorithm is not stable
@ -1022,19 +1006,3 @@ nsAnimationManager::FlushAnimations(FlushFlags aFlags)
MaybeStartOrStopObservingRefreshDriver();
}
void
nsAnimationManager::DoDispatchEvents()
{
EventArray events;
mPendingEvents.SwapElements(events);
// FIXME: Sort events here in timeline order, then document order
for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
AnimationEventInfo &info = events[i];
EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
if (!mPresContext) {
break;
}
}
}

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

@ -50,8 +50,6 @@ struct AnimationEventInfo {
}
};
typedef InfallibleTArray<AnimationEventInfo> EventArray;
namespace dom {
class CSSAnimation final : public Animation
@ -281,7 +279,11 @@ public:
/**
* Add a pending event.
*/
void QueueEvent(mozilla::AnimationEventInfo& aEventInfo);
void QueueEvent(mozilla::AnimationEventInfo&& aEventInfo)
{
mEventDispatcher.QueueEvent(
mozilla::Forward<mozilla::AnimationEventInfo>(aEventInfo));
}
/**
* Dispatch any pending events. We accumulate animationend and
@ -290,14 +292,8 @@ public:
* accumulate animationstart events at other points when style
* contexts are created.
*/
void DispatchEvents() {
// Fast-path the common case: no events
if (!mPendingEvents.IsEmpty()) {
DoDispatchEvents();
}
}
void ClearEventQueue() { mPendingEvents.Clear(); }
void DispatchEvents() { mEventDispatcher.DispatchEvents(mPresContext); }
void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); }
protected:
virtual ~nsAnimationManager() {}
@ -315,6 +311,8 @@ protected:
return true;
}
mozilla::DelayedEventDispatcher<mozilla::AnimationEventInfo> mEventDispatcher;
private:
void BuildAnimations(nsStyleContext* aStyleContext,
mozilla::dom::Element* aTarget,
@ -331,11 +329,6 @@ private:
static void UpdateCascadeResults(nsStyleContext* aStyleContext,
mozilla::AnimationCollection*
aElementAnimations);
// The guts of DispatchEvents
void DoDispatchEvents();
mozilla::EventArray mPendingEvents;
};
#endif /* !defined(nsAnimationManager_h_) */