Bug 1057129 patch 1 - Make AddStyleUpdatesTo handle pseudo-elements. r=birtles
authorL. David Baron <dbaron@dbaron.org>
Sun, 24 Aug 2014 21:48:22 -0700
changeset 201270 c0948312ced7c5e4c4f618bde4d627912cf7f1aa
parent 201269 56c3cb543b9092af71a1e771ed1ddb958957717c
child 201271 2bf015380818ecdae9254922461ff99defd6d7b5
push id48141
push userdbaron@mozilla.com
push dateMon, 25 Aug 2014 04:48:50 +0000
treeherdermozilla-inbound@916f273f3ad1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1057129, 960465
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1057129 patch 1 - Make AddStyleUpdatesTo handle pseudo-elements. r=birtles This (like patch 2) posts restyles directly to the pseudo-element content nodes, which is a new thing. This isn't needed right now since AddStyleUpdatesTo is currently only used when updating main-thread-suppressed animations running on the compositor. However, it will be needed once we depend on AddStyleUpdatesTo for bug 960465. And it will have an effect now since AddStyleUpdatesTo actually adds all animations rather than only the ones that are suppressed from running on the main thread.
layout/style/AnimationCommon.cpp
layout/style/AnimationCommon.h
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -171,27 +171,22 @@ void
 CommonAnimationManager::AddStyleUpdatesTo(RestyleTracker& aTracker)
 {
   PRCList* next = PR_LIST_HEAD(&mElementCollections);
   while (next != &mElementCollections) {
     AnimationPlayerCollection* collection =
       static_cast<AnimationPlayerCollection*>(next);
     next = PR_NEXT_LINK(next);
 
-    if (!collection->IsForElement()) {
-      // We don't support compositor-driven animation of :before/:after
-      // transitions or animations, so at least skip those.
-      // FIXME: We'll need to handle this before using this for the
-      // transitions redesign.
-      continue;
+    dom::Element* elementToRestyle = collection->GetElementToRestyle();
+    if (elementToRestyle) {
+      nsRestyleHint rshint = collection->IsForTransitions()
+        ? eRestyle_CSSTransitions : eRestyle_CSSAnimations;
+      aTracker.AddPendingRestyle(elementToRestyle, rshint, nsChangeHint(0));
     }
-
-    nsRestyleHint rshint = collection->IsForTransitions()
-      ? eRestyle_CSSTransitions : eRestyle_CSSAnimations;
-    aTracker.AddPendingRestyle(collection->mElement, rshint, nsChangeHint(0));
   }
 }
 
 /* static */ bool
 CommonAnimationManager::ExtractComputedValueForTransition(
                           nsCSSProperty aProperty,
                           nsStyleContext* aStyleContext,
                           StyleAnimationValue& aComputedValue)
@@ -408,16 +403,42 @@ AnimationPlayerCollection::HasAnimationO
     if (anim && anim->HasAnimationOfProperty(aProperty) &&
         !anim->IsFinishedTransition()) {
       return true;
     }
   }
   return false;
 }
 
+mozilla::dom::Element*
+AnimationPlayerCollection::GetElementToRestyle() const
+{
+  if (IsForElement()) {
+    return mElement;
+  }
+
+  nsIFrame* primaryFrame = mElement->GetPrimaryFrame();
+  if (!primaryFrame) {
+    return nullptr;
+  }
+  nsIFrame* pseudoFrame;
+  if (IsForBeforePseudo()) {
+    pseudoFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame);
+  } else if (IsForAfterPseudo()) {
+    pseudoFrame = nsLayoutUtils::GetAfterFrame(primaryFrame);
+  } else {
+    MOZ_ASSERT(false, "unknown mElementProperty");
+    return nullptr;
+  }
+  if (!pseudoFrame) {
+    return nullptr;
+  }
+  return pseudoFrame->GetContent()->AsElement();
+}
+
 /* static */ void
 AnimationPlayerCollection::LogAsyncAnimationFailure(nsCString& aMessage,
                                                      const nsIContent* aContent)
 {
   if (aContent) {
     aMessage.AppendLiteral(" [");
     aMessage.Append(nsAtomCString(aContent->Tag()));
 
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -225,40 +225,51 @@ struct AnimationPlayerCollection : publi
   bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const;
   bool HasAnimationOfProperty(nsCSSProperty aProperty) const;
 
   bool IsForElement() const { // rather than for a pseudo-element
     return mElementProperty == nsGkAtoms::animationsProperty ||
            mElementProperty == nsGkAtoms::transitionsProperty;
   }
 
+  bool IsForBeforePseudo() const {
+    return mElementProperty == nsGkAtoms::animationsOfBeforeProperty ||
+           mElementProperty == nsGkAtoms::transitionsOfBeforeProperty;
+  }
+
+  bool IsForAfterPseudo() const {
+    return mElementProperty == nsGkAtoms::animationsOfAfterProperty ||
+           mElementProperty == nsGkAtoms::transitionsOfAfterProperty;
+  }
+
   bool IsForTransitions() const {
     return mElementProperty == nsGkAtoms::transitionsProperty ||
            mElementProperty == nsGkAtoms::transitionsOfBeforeProperty ||
            mElementProperty == nsGkAtoms::transitionsOfAfterProperty;
   }
 
   bool IsForAnimations() const {
     return mElementProperty == nsGkAtoms::animationsProperty ||
            mElementProperty == nsGkAtoms::animationsOfBeforeProperty ||
            mElementProperty == nsGkAtoms::animationsOfAfterProperty;
   }
 
   nsString PseudoElement()
   {
     if (IsForElement()) {
       return EmptyString();
-    } else if (mElementProperty == nsGkAtoms::animationsOfBeforeProperty ||
-               mElementProperty == nsGkAtoms::transitionsOfBeforeProperty) {
+    } else if (IsForBeforePseudo()) {
       return NS_LITERAL_STRING("::before");
     } else {
       return NS_LITERAL_STRING("::after");
     }
   }
 
+  mozilla::dom::Element* GetElementToRestyle() const;
+
   void PostRestyleForAnimation(nsPresContext *aPresContext) {
     nsRestyleHint styleHint = IsForElement() ? eRestyle_Self : eRestyle_Subtree;
     aPresContext->PresShell()->RestyleForAnimation(mElement, styleHint);
   }
 
   static void LogAsyncAnimationFailure(nsCString& aMessage,
                                        const nsIContent* aContent = nullptr);