mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1183461 part 7 - Add EventInfoComparator and sort events; r=heycam
This patch also reworks the dispatch of events in nsRefreshDriver. Previously the refresh driver would dispatch the transition events for all subdocuments then the animation events. This arrangement is complicated and not obviously necessary. This patch simplifies this arrangement by dispatching transition events and animation events for each document before proceeding to subdocuments.
This commit is contained in:
parent
0a45589b29
commit
8304eb03e5
@ -1319,44 +1319,32 @@ nsRefreshDriver::DispatchPendingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
enum class AnimationEventType {
|
||||
CSSAnimations,
|
||||
CSSTransitions
|
||||
};
|
||||
|
||||
struct DispatchAnimationEventParams {
|
||||
AnimationEventType mEventType;
|
||||
nsRefreshDriver* mRefreshDriver;
|
||||
};
|
||||
}
|
||||
|
||||
static bool
|
||||
DispatchAnimationEventsOnSubDocuments(nsIDocument* aDocument,
|
||||
void* aParams)
|
||||
void* aRefreshDriver)
|
||||
{
|
||||
MOZ_ASSERT(aParams, "Animation event parameters should be set");
|
||||
auto params = static_cast<DispatchAnimationEventParams*>(aParams);
|
||||
|
||||
nsIPresShell* shell = aDocument->GetShell();
|
||||
if (!shell) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsPresContext* context = shell->GetPresContext();
|
||||
if (!context || context->RefreshDriver() != params->mRefreshDriver) {
|
||||
if (!context || context->RefreshDriver() != aRefreshDriver) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> kungFuDeathGrip(aDocument);
|
||||
|
||||
if (params->mEventType == AnimationEventType::CSSAnimations) {
|
||||
context->AnimationManager()->DispatchEvents();
|
||||
} else {
|
||||
context->TransitionManager()->DispatchEvents();
|
||||
}
|
||||
context->TransitionManager()->SortEvents();
|
||||
context->AnimationManager()->SortEvents();
|
||||
|
||||
// Dispatch transition events first since transitions conceptually sit
|
||||
// below animations in terms of compositing order.
|
||||
context->TransitionManager()->DispatchEvents();
|
||||
context->AnimationManager()->DispatchEvents();
|
||||
|
||||
aDocument->EnumerateSubDocuments(DispatchAnimationEventsOnSubDocuments,
|
||||
aParams);
|
||||
aRefreshDriver);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1368,19 +1356,7 @@ nsRefreshDriver::DispatchAnimationEvents()
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* doc = mPresContext->Document();
|
||||
|
||||
// Dispatch transition events first since transitions conceptually sit
|
||||
// below animations in terms of compositing order.
|
||||
DispatchAnimationEventParams params { AnimationEventType::CSSTransitions,
|
||||
this };
|
||||
DispatchAnimationEventsOnSubDocuments(doc, ¶ms);
|
||||
if (!mPresContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
params.mEventType = AnimationEventType::CSSAnimations;
|
||||
DispatchAnimationEventsOnSubDocuments(doc, ¶ms);
|
||||
DispatchAnimationEventsOnSubDocuments(mPresContext->Document(), this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -373,7 +373,7 @@ CommonAnimationManager::FlushAnimations()
|
||||
|
||||
MOZ_ASSERT(collection->mElement->GetComposedDoc() ==
|
||||
mPresContext->Document(),
|
||||
"Should not have a transition/animations collection for an "
|
||||
"Should not have a transition/animation collection for an "
|
||||
"element that is not part of the document tree");
|
||||
|
||||
collection->RequestRestyle(AnimationCollection::RestyleType::Standard);
|
||||
|
@ -6,12 +6,14 @@
|
||||
#ifndef mozilla_css_AnimationCommon_h
|
||||
#define mozilla_css_AnimationCommon_h
|
||||
|
||||
#include <algorithm> // For <std::stable_sort>
|
||||
#include "nsIStyleRuleProcessor.h"
|
||||
#include "nsIStyleRule.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsCSSProperty.h"
|
||||
#include "nsDisplayList.h" // For nsDisplayItem::Type
|
||||
#include "mozilla/AnimationComparator.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
@ -502,23 +504,49 @@ template <class EventInfo>
|
||||
class DelayedEventDispatcher
|
||||
{
|
||||
public:
|
||||
DelayedEventDispatcher() : mIsSorted(true) { }
|
||||
|
||||
void QueueEvent(EventInfo&& aEventInfo)
|
||||
{
|
||||
mPendingEvents.AppendElement(mozilla::Forward<EventInfo>(aEventInfo));
|
||||
mPendingEvents.AppendElement(Forward<EventInfo>(aEventInfo));
|
||||
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());
|
||||
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)
|
||||
{
|
||||
if (!aPresContext || mPendingEvents.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SortEvents();
|
||||
|
||||
EventArray events;
|
||||
mPendingEvents.SwapElements(events);
|
||||
// FIXME: Sort events here in timeline order, then document order
|
||||
// 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);
|
||||
|
||||
@ -528,7 +556,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void ClearEventQueue() { mPendingEvents.Clear(); }
|
||||
void ClearEventQueue()
|
||||
{
|
||||
mPendingEvents.Clear();
|
||||
mIsSorted = true;
|
||||
}
|
||||
bool HasQueuedEvents() const { return !mPendingEvents.IsEmpty(); }
|
||||
|
||||
// Methods for supporting cycle-collection
|
||||
@ -540,12 +572,31 @@ public:
|
||||
ImplCycleCollectionTraverse(*aCallback, info.mAnimation, aName);
|
||||
}
|
||||
}
|
||||
void Unlink() { mPendingEvents.Clear(); }
|
||||
void Unlink() { ClearEventQueue(); }
|
||||
|
||||
protected:
|
||||
typedef nsTArray<EventInfo> EventArray;
|
||||
class EventInfoLessThan
|
||||
{
|
||||
public:
|
||||
bool operator()(const EventInfo& a, const EventInfo& 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<nsRefPtr<dom::Animation>> comparator;
|
||||
return comparator.LessThan(a.mAnimation, b.mAnimation);
|
||||
}
|
||||
};
|
||||
|
||||
typedef nsTArray<EventInfo> EventArray;
|
||||
EventArray mPendingEvents;
|
||||
bool mIsSorted;
|
||||
};
|
||||
|
||||
template <class EventInfo>
|
||||
|
@ -330,6 +330,7 @@ public:
|
||||
* contexts are created.
|
||||
*/
|
||||
void DispatchEvents() { mEventDispatcher.DispatchEvents(mPresContext); }
|
||||
void SortEvents() { mEventDispatcher.SortEvents(); }
|
||||
void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); }
|
||||
|
||||
// Stop animations on the element. This method takes the real element
|
||||
|
@ -304,6 +304,7 @@ public:
|
||||
}
|
||||
|
||||
void DispatchEvents() { mEventDispatcher.DispatchEvents(mPresContext); }
|
||||
void SortEvents() { mEventDispatcher.SortEvents(); }
|
||||
void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); }
|
||||
|
||||
protected:
|
||||
|
Loading…
Reference in New Issue
Block a user