Bug 1324691 - Part 2: Move AnimationsWithDestroyedFrame into RestyleManagerBase.
Both ServoRestyleManager and RestyleManager need AnimationsWithDestroyedFrame,
so move it to the base class.
MozReview-Commit-ID: BswoDYm0gS1
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -88,17 +88,16 @@ RestyleManager::RestyleManager(nsPresCon
, mDoRebuildAllStyleData(false)
, mInRebuildAllStyleData(false)
, mSkipAnimationRules(false)
, mHavePendingNonAnimationRestyles(false)
, mRebuildAllExtraHint(nsChangeHint(0))
, mRebuildAllRestyleHint(nsRestyleHint(0))
, mAnimationGeneration(0)
, mReframingStyleContexts(nullptr)
- , mAnimationsWithDestroyedFrame(nullptr)
, mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR)
, mIsProcessingRestyles(false)
#ifdef RESTYLE_LOGGING
, mLoggingDepth(0)
#endif
{
@@ -188,63 +187,16 @@ RestyleManager::ReframingStyleContexts::
// Before we go away, we need to flush out any frame construction that
// was enqueued, so that we initiate transitions.
// Note that this is a little bit evil in that we're calling into code
// that calls our member functions from our destructor, but it's at
// the beginning of our destructor, so it shouldn't be too bad.
mRestyleManager->PresContext()->FrameConstructor()->CreateNeededFrames();
}
-RestyleManager::AnimationsWithDestroyedFrame::AnimationsWithDestroyedFrame(
- RestyleManager* aRestyleManager)
- : mRestyleManager(aRestyleManager)
- , mRestorePointer(mRestyleManager->mAnimationsWithDestroyedFrame)
-{
- MOZ_ASSERT(!mRestyleManager->mAnimationsWithDestroyedFrame,
- "shouldn't construct recursively");
- mRestyleManager->mAnimationsWithDestroyedFrame = this;
-}
-
-void
-RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsForElementsWithoutFrames()
-{
- StopAnimationsWithoutFrame(mContents, CSSPseudoElementType::NotPseudo);
- StopAnimationsWithoutFrame(mBeforeContents, CSSPseudoElementType::before);
- StopAnimationsWithoutFrame(mAfterContents, CSSPseudoElementType::after);
-}
-
-void
-RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame(
- nsTArray<RefPtr<nsIContent>>& aArray,
- CSSPseudoElementType aPseudoType)
-{
- nsAnimationManager* animationManager =
- mRestyleManager->PresContext()->AnimationManager();
- nsTransitionManager* transitionManager =
- mRestyleManager->PresContext()->TransitionManager();
- for (nsIContent* content : aArray) {
- if (content->GetPrimaryFrame()) {
- continue;
- }
- dom::Element* element = content->AsElement();
-
- animationManager->StopAnimationsForElement(element, aPseudoType);
- transitionManager->StopTransitionsForElement(element, aPseudoType);
-
- // All other animations should keep running but not running on the
- // *compositor* at this point.
- EffectSet* effectSet = EffectSet::GetEffectSet(element, aPseudoType);
- if (effectSet) {
- for (KeyframeEffectReadOnly* effect : *effectSet) {
- effect->ResetIsRunningOnCompositor();
- }
- }
- }
-}
-
static inline dom::Element*
ElementForStyleContext(nsIContent* aParentContent,
nsIFrame* aFrame,
CSSPseudoElementType aPseudoType);
// Forwarded nsIDocumentObserver method, to handle restyling (and
// passing the notification to the frame).
nsresult
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -45,18 +45,16 @@ public:
explicit RestyleManager(nsPresContext* aPresContext);
private:
// Private destructor, to discourage deletion outside of Release():
~RestyleManager()
{
MOZ_ASSERT(!mReframingStyleContexts,
"temporary member should be nulled out before destruction");
- MOZ_ASSERT(!mAnimationsWithDestroyedFrame,
- "leaving dangling pointers from AnimationsWithDestroyedFrame");
}
public:
NS_INLINE_DECL_REFCOUNTING(mozilla::RestyleManager)
// Forwarded nsIDocumentObserver method, to handle restyling (and
// passing the notification to the frame).
nsresult ContentStateChanged(nsIContent* aContent,
@@ -216,72 +214,16 @@ public:
* For the pseudo-elements, aContent must be the anonymous content
* that we're creating for that pseudo-element, not the real element.
*/
static bool
TryInitiatingTransition(nsPresContext* aPresContext, nsIContent* aContent,
nsStyleContext* aOldStyleContext,
RefPtr<nsStyleContext>* aNewStyleContext /* inout */);
- // AnimationsWithDestroyedFrame is used to stop animations and transitions
- // on elements that have no frame at the end of the restyling process.
- // It only lives during the restyling process.
- class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
- public:
- // Construct a AnimationsWithDestroyedFrame object. The caller must
- // ensure that aRestyleManager lives at least as long as the
- // object. (This is generally easy since the caller is typically a
- // method of RestyleManager.)
- explicit AnimationsWithDestroyedFrame(RestyleManager* aRestyleManager);
-
- // This method takes the content node for the generated content for
- // animation/transition on ::before and ::after, rather than the
- // content node for the real element.
- void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
- MOZ_ASSERT(aContent);
- CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
- if (pseudoType == CSSPseudoElementType::NotPseudo) {
- mContents.AppendElement(aContent);
- } else if (pseudoType == CSSPseudoElementType::before) {
- MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
- mBeforeContents.AppendElement(aContent->GetParent());
- } else if (pseudoType == CSSPseudoElementType::after) {
- MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
- mAfterContents.AppendElement(aContent->GetParent());
- }
- }
-
- void StopAnimationsForElementsWithoutFrames();
-
- private:
- void StopAnimationsWithoutFrame(nsTArray<RefPtr<nsIContent>>& aArray,
- CSSPseudoElementType aPseudoType);
-
- RestyleManager* mRestyleManager;
- AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
-
- // Below three arrays might include elements that have already had their
- // animations or transitions stopped.
- //
- // mBeforeContents and mAfterContents hold the real element rather than
- // the content node for the generated content (which might change during
- // a reframe)
- nsTArray<RefPtr<nsIContent>> mContents;
- nsTArray<RefPtr<nsIContent>> mBeforeContents;
- nsTArray<RefPtr<nsIContent>> mAfterContents;
- };
-
- /**
- * Return the current AnimationsWithDestroyedFrame struct, or null if we're
- * not currently in a restyling operation.
- */
- AnimationsWithDestroyedFrame* GetAnimationsWithDestroyedFrame() {
- return mAnimationsWithDestroyedFrame;
- }
-
private:
void RestyleForEmptyChange(Element* aContainer);
public:
// Handle ContentInserted notifications.
void ContentInserted(nsINode* aContainer, nsIContent* aChild)
{
RestyleForInsertOrChange(aContainer, aChild);
@@ -504,17 +446,16 @@ private:
nsChangeHint mRebuildAllExtraHint;
nsRestyleHint mRebuildAllRestyleHint;
// The total number of animation flushes by this frame constructor.
// Used to keep the layer and animation manager in sync.
uint64_t mAnimationGeneration;
ReframingStyleContexts* mReframingStyleContexts;
- AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame;
RestyleTracker mPendingRestyles;
// Are we currently in the middle of a call to ProcessRestyles?
// This flag is used both as a debugging aid to assert that we are not
// performing nested calls to ProcessPendingRestyles, as well as to ignore
// redundant calls to IncrementAnimationGeneration.
bool mIsProcessingRestyles;
--- a/layout/base/RestyleManagerBase.cpp
+++ b/layout/base/RestyleManagerBase.cpp
@@ -1369,9 +1369,59 @@ RestyleManagerBase::ProcessRestyledFrame
}
#endif
}
aChangeList.Clear();
return NS_OK;
}
+RestyleManagerBase::AnimationsWithDestroyedFrame
+ ::AnimationsWithDestroyedFrame(
+ RestyleManagerBase* aRestyleManager)
+ : mRestyleManager(aRestyleManager)
+ , mRestorePointer(mRestyleManager->mAnimationsWithDestroyedFrame)
+{
+ MOZ_ASSERT(!mRestyleManager->mAnimationsWithDestroyedFrame,
+ "shouldn't construct recursively");
+ mRestyleManager->mAnimationsWithDestroyedFrame = this;
+}
+
+void
+RestyleManagerBase::AnimationsWithDestroyedFrame
+ ::StopAnimationsForElementsWithoutFrames()
+{
+ StopAnimationsWithoutFrame(mContents, CSSPseudoElementType::NotPseudo);
+ StopAnimationsWithoutFrame(mBeforeContents, CSSPseudoElementType::before);
+ StopAnimationsWithoutFrame(mAfterContents, CSSPseudoElementType::after);
+}
+
+void
+RestyleManagerBase::AnimationsWithDestroyedFrame
+ ::StopAnimationsWithoutFrame(
+ nsTArray<RefPtr<nsIContent>>& aArray,
+ CSSPseudoElementType aPseudoType)
+{
+ nsAnimationManager* animationManager =
+ mRestyleManager->PresContext()->AnimationManager();
+ nsTransitionManager* transitionManager =
+ mRestyleManager->PresContext()->TransitionManager();
+ for (nsIContent* content : aArray) {
+ if (content->GetPrimaryFrame()) {
+ continue;
+ }
+ dom::Element* element = content->AsElement();
+
+ animationManager->StopAnimationsForElement(element, aPseudoType);
+ transitionManager->StopTransitionsForElement(element, aPseudoType);
+
+ // All other animations should keep running but not running on the
+ // *compositor* at this point.
+ EffectSet* effectSet = EffectSet::GetEffectSet(element, aPseudoType);
+ if (effectSet) {
+ for (KeyframeEffectReadOnly* effect : *effectSet) {
+ effect->ResetIsRunningOnCompositor();
+ }
+ }
+ }
+}
+
} // namespace mozilla
--- a/layout/base/RestyleManagerBase.h
+++ b/layout/base/RestyleManagerBase.h
@@ -78,17 +78,80 @@ public:
// ProcessRestyledFrames call in a view update batch and a script blocker.
// This function does not call ProcessAttachedQueue() on the binding manager.
// If the caller wants that to happen synchronously, it needs to handle that
// itself.
nsresult ProcessRestyledFrames(nsStyleChangeList& aChangeList);
bool IsInStyleRefresh() const { return mInStyleRefresh; }
+ // AnimationsWithDestroyedFrame is used to stop animations and transitions
+ // on elements that have no frame at the end of the restyling process.
+ // It only lives during the restyling process.
+ class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
+ public:
+ // Construct a AnimationsWithDestroyedFrame object. The caller must
+ // ensure that aRestyleManager lives at least as long as the
+ // object. (This is generally easy since the caller is typically a
+ // method of RestyleManager.)
+ explicit AnimationsWithDestroyedFrame(RestyleManagerBase* aRestyleManager);
+
+ // This method takes the content node for the generated content for
+ // animation/transition on ::before and ::after, rather than the
+ // content node for the real element.
+ void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
+ MOZ_ASSERT(aContent);
+ CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
+ if (pseudoType == CSSPseudoElementType::NotPseudo) {
+ mContents.AppendElement(aContent);
+ } else if (pseudoType == CSSPseudoElementType::before) {
+ MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
+ nsGkAtoms::mozgeneratedcontentbefore);
+ mBeforeContents.AppendElement(aContent->GetParent());
+ } else if (pseudoType == CSSPseudoElementType::after) {
+ MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
+ nsGkAtoms::mozgeneratedcontentafter);
+ mAfterContents.AppendElement(aContent->GetParent());
+ }
+ }
+
+ void StopAnimationsForElementsWithoutFrames();
+
+ private:
+ void StopAnimationsWithoutFrame(nsTArray<RefPtr<nsIContent>>& aArray,
+ CSSPseudoElementType aPseudoType);
+
+ RestyleManagerBase* mRestyleManager;
+ AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
+
+ // Below three arrays might include elements that have already had their
+ // animations or transitions stopped.
+ //
+ // mBeforeContents and mAfterContents hold the real element rather than
+ // the content node for the generated content (which might change during
+ // a reframe)
+ nsTArray<RefPtr<nsIContent>> mContents;
+ nsTArray<RefPtr<nsIContent>> mBeforeContents;
+ nsTArray<RefPtr<nsIContent>> mAfterContents;
+ };
+
+ /**
+ * Return the current AnimationsWithDestroyedFrame struct, or null if we're
+ * not currently in a restyling operation.
+ */
+ AnimationsWithDestroyedFrame* GetAnimationsWithDestroyedFrame() {
+ return mAnimationsWithDestroyedFrame;
+ }
+
protected:
+ ~RestyleManagerBase() {
+ MOZ_ASSERT(!mAnimationsWithDestroyedFrame,
+ "leaving dangling pointers from AnimationsWithDestroyedFrame");
+ }
+
void ContentStateChangedInternal(Element* aElement,
EventStates aStateMask,
nsChangeHint* aOutChangeHint,
nsRestyleHint* aOutRestyleHint);
bool IsDisconnected() { return mPresContext == nullptr; }
void IncrementHoverGeneration() {
@@ -159,13 +222,15 @@ protected:
* the same. When it is used in other contexts (i.e., where the next
* continuation would already have the new style context), the current
* style context should be passed.
*/
static nsIFrame*
GetNextContinuationWithSameStyle(nsIFrame* aFrame,
nsStyleContext* aOldStyleContext,
bool* aHaveMoreContinuations = nullptr);
+
+ AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame = nullptr;
};
} // namespace mozilla
#endif
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -696,18 +696,19 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
}
}
if (HasCSSAnimations() || HasCSSTransitions() ||
EffectSet::GetEffectSet(this)) {
// If no new frame for this element is created by the end of the
// restyling process, stop animations and transitions for this frame
if (presContext->RestyleManager()->IsGecko()) {
- RestyleManager::AnimationsWithDestroyedFrame* adf =
- presContext->RestyleManager()->AsGecko()->GetAnimationsWithDestroyedFrame();
+ RestyleManagerBase::AnimationsWithDestroyedFrame* adf =
+ presContext->RestyleManager()->AsGecko()
+ ->GetAnimationsWithDestroyedFrame();
// AnimationsWithDestroyedFrame only lives during the restyling process.
if (adf) {
adf->Put(mContent, mStyleContext);
}
} else {
NS_ERROR("stylo: ServoRestyleManager does not support animations yet");
}
}