зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1415780 - Let AnimationEventDispatcher observe nsRefreshDriver. r=birtles
So that we can now ensure nsRefreshDriver ticks (i.e. nsRefreshDriver doesn't stop its timer) for all queued events. Before this patch, dispatching CSS animation/transition events relied on the fact that DocumentTimeline observes nsRefreshDriver. For this fact, animationcancel or transitioncancel event did not dispatch properly in some cases, i.e. the case where the animation was dropped from the DocumentTimeline. MozReview-Commit-ID: 7JYro0MY2U2 --HG-- extra : rebase_source : e1963d9eef996cdf5d64c64f80eb1b93ac6fd18a
This commit is contained in:
Родитель
9e4cc95a63
Коммит
51d411f1b6
|
@ -7,6 +7,7 @@
|
|||
#include "mozilla/AnimationEventDispatcher.h"
|
||||
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -26,5 +27,32 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEventDispatcher, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEventDispatcher, Release)
|
||||
|
||||
void
|
||||
AnimationEventDispatcher::Disconnect()
|
||||
{
|
||||
if (mIsObserving) {
|
||||
MOZ_ASSERT(mPresContext && mPresContext->RefreshDriver(),
|
||||
"The pres context and the refresh driver should be still "
|
||||
"alive if we haven't disassociated from the refresh driver");
|
||||
mPresContext->RefreshDriver()->CancelPendingAnimationEvents(this);
|
||||
mIsObserving = false;
|
||||
}
|
||||
mPresContext = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
AnimationEventDispatcher::QueueEvents(nsTArray<AnimationEventInfo>&& aEvents)
|
||||
{
|
||||
MOZ_ASSERT(mPresContext,
|
||||
"The pres context should be valid");
|
||||
|
||||
mPendingEvents.AppendElements(Move(aEvents));
|
||||
mIsSorted = false;
|
||||
if (!mIsObserving) {
|
||||
mPresContext->RefreshDriver()->ScheduleAnimationEventDispatch(this);
|
||||
mIsObserving = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsPresContext;
|
||||
class nsRefreshDriver;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -100,26 +101,22 @@ public:
|
|||
explicit AnimationEventDispatcher(nsPresContext* aPresContext)
|
||||
: mPresContext(aPresContext)
|
||||
, mIsSorted(true)
|
||||
, mIsObserving(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEventDispatcher)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnimationEventDispatcher)
|
||||
|
||||
void Disconnect() {
|
||||
mPresContext = nullptr;
|
||||
}
|
||||
void Disconnect();
|
||||
|
||||
void QueueEvents(nsTArray<AnimationEventInfo>&& aEvents)
|
||||
{
|
||||
mPendingEvents.AppendElements(Move(aEvents));
|
||||
mIsSorted = false;
|
||||
}
|
||||
void QueueEvents(nsTArray<AnimationEventInfo>&& aEvents);
|
||||
|
||||
// This will call SortEvents automatically if it has not already been
|
||||
// called.
|
||||
void DispatchEvents()
|
||||
{
|
||||
mIsObserving = false;
|
||||
if (!mPresContext || mPendingEvents.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -154,7 +151,16 @@ public:
|
|||
bool HasQueuedEvents() const { return !mPendingEvents.IsEmpty(); }
|
||||
|
||||
private:
|
||||
#ifndef DEBUG
|
||||
~AnimationEventDispatcher() = default;
|
||||
#else
|
||||
~AnimationEventDispatcher()
|
||||
{
|
||||
MOZ_ASSERT(!mIsObserving,
|
||||
"AnimationEventDispatcher should have disassociated from "
|
||||
"nsRefreshDriver");
|
||||
}
|
||||
#endif
|
||||
|
||||
class AnimationEventInfoLessThan
|
||||
{
|
||||
|
@ -195,6 +201,7 @@ private:
|
|||
typedef nsTArray<AnimationEventInfo> EventArray;
|
||||
EventArray mPendingEvents;
|
||||
bool mIsSorted;
|
||||
bool mIsObserving;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include "mozilla/PresShell.h"
|
||||
|
||||
#include "mozilla/AnimationEventDispatcher.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
|
@ -1363,7 +1362,7 @@ PresShell::Destroy()
|
|||
}
|
||||
|
||||
if (mPresContext) {
|
||||
mPresContext->AnimationEventDispatcher()->ClearEventQueue();
|
||||
rd->CancelPendingAnimationEvents(mPresContext->AnimationEventDispatcher());
|
||||
}
|
||||
|
||||
// Revoke any pending events. We need to do this and cancel pending reflows
|
||||
|
|
|
@ -241,6 +241,7 @@ public:
|
|||
{
|
||||
return mAnimationEventDispatcher;
|
||||
}
|
||||
|
||||
mozilla::EffectCompositor* EffectCompositor() { return mEffectCompositor; }
|
||||
nsTransitionManager* TransitionManager() { return mTransitionManager; }
|
||||
nsAnimationManager* AnimationManager() { return mAnimationManager; }
|
||||
|
|
|
@ -1429,6 +1429,7 @@ nsRefreshDriver::ObserverCount() const
|
|||
// changes can trigger transitions which fire events when they complete, and
|
||||
// layout changes can affect media queries on child documents, triggering
|
||||
// style changes, etc.
|
||||
sum += mAnimationEventFlushObservers.Length();
|
||||
sum += mResizeEventFlushObservers.Length();
|
||||
sum += mStyleFlushObservers.Length();
|
||||
sum += mLayoutFlushObservers.Length();
|
||||
|
@ -1452,6 +1453,7 @@ nsRefreshDriver::HasObservers() const
|
|||
return mViewManagerFlushIsPending ||
|
||||
!mStyleFlushObservers.IsEmpty() ||
|
||||
!mLayoutFlushObservers.IsEmpty() ||
|
||||
!mAnimationEventFlushObservers.IsEmpty() ||
|
||||
!mResizeEventFlushObservers.IsEmpty() ||
|
||||
!mPendingEvents.IsEmpty() ||
|
||||
!mFrameRequestCallbackDocs.IsEmpty() ||
|
||||
|
@ -1638,22 +1640,19 @@ nsRefreshDriver::DispatchAnimationEvents()
|
|||
return;
|
||||
}
|
||||
|
||||
AutoTArray<nsCOMPtr<nsIDocument>, 32> documents;
|
||||
CollectDocuments(mPresContext->Document(), &documents);
|
||||
// Hold all AnimationEventDispatcher in mAnimationEventFlushObservers as
|
||||
// a RefPtr<> array since each AnimationEventDispatcher might be destroyed
|
||||
// during processing the previous dispatcher.
|
||||
size_t len = mAnimationEventFlushObservers.Length();
|
||||
AutoTArray<RefPtr<AnimationEventDispatcher>, 16> dispatchers;
|
||||
RefPtr<AnimationEventDispatcher>* elems = dispatchers.AppendElements(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
elems[i] = mAnimationEventFlushObservers[i];
|
||||
}
|
||||
mAnimationEventFlushObservers.Clear();
|
||||
|
||||
for (uint32_t i = 0; i < documents.Length(); ++i) {
|
||||
nsIDocument* doc = documents[i];
|
||||
nsIPresShell* shell = doc->GetShell();
|
||||
if (!shell) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<nsPresContext> context = shell->GetPresContext();
|
||||
if (!context || context->RefreshDriver() != this) {
|
||||
continue;
|
||||
}
|
||||
|
||||
context->AnimationEventDispatcher()->DispatchEvents();
|
||||
for (auto& dispatcher : dispatchers) {
|
||||
dispatcher->DispatchEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2412,6 +2411,14 @@ nsRefreshDriver::CancelPendingEvents(nsIDocument* aDocument)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::CancelPendingAnimationEvents(AnimationEventDispatcher* aDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(aDispatcher);
|
||||
aDispatcher->ClearEventQueue();
|
||||
mAnimationEventFlushObservers.RemoveElement(aDispatcher);
|
||||
}
|
||||
|
||||
/* static */ TimeStamp
|
||||
nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "nsTObserverArray.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "mozilla/AnimationEventDispatcher.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/layers/TransactionIdAllocator.h"
|
||||
|
@ -243,6 +244,24 @@ public:
|
|||
*/
|
||||
void CancelPendingEvents(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Queue new animation events to dispatch in next tick.
|
||||
*/
|
||||
void ScheduleAnimationEventDispatch(
|
||||
mozilla::AnimationEventDispatcher* aDispatcher)
|
||||
{
|
||||
NS_ASSERTION(!mAnimationEventFlushObservers.Contains(aDispatcher),
|
||||
"Double-adding animation event flush observer");
|
||||
mAnimationEventFlushObservers.AppendElement(aDispatcher);
|
||||
EnsureTimerStarted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all pending animation events associated with |aDispatcher|.
|
||||
*/
|
||||
void CancelPendingAnimationEvents(
|
||||
mozilla::AnimationEventDispatcher* aDispatcher);
|
||||
|
||||
/**
|
||||
* Schedule a frame visibility update "soon", subject to the heuristics and
|
||||
* throttling we apply to visibility updates.
|
||||
|
@ -496,6 +515,8 @@ private:
|
|||
nsTArray<nsIDocument*> mThrottledFrameRequestCallbackDocs;
|
||||
nsTObserverArray<nsAPostRefreshObserver*> mPostRefreshObservers;
|
||||
nsTArray<PendingEvent> mPendingEvents;
|
||||
AutoTArray<mozilla::AnimationEventDispatcher*, 16>
|
||||
mAnimationEventFlushObservers;
|
||||
|
||||
void BeginRefreshingImages(RequestTable& aEntries,
|
||||
mozilla::TimeStamp aDesired);
|
||||
|
|
Загрузка…
Ссылка в новой задаче