зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
774abfc8fe
Коммит
cd380ce4a3
|
@ -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"
|
||||
|
@ -512,6 +513,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_) */
|
||||
|
|
Загрузка…
Ссылка в новой задаче