mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
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 : 28c8e2a50d29c5344e2c5ca3c43af41f4692fa0f
This commit is contained in:
parent
7061542dd0
commit
175bc2d176
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user