Bug 537139: Prevent SMIL animation from triggering CSS transitions. r=dbaron
authorDaniel Holbert <dholbert@cs.stanford.edu>
Mon, 01 Mar 2010 11:31:45 -0800
changeset 38816 095c11c68ea86cd74ae7100c2db13b7ff653b0a3
parent 38815 9c1f93a599ce855092e1604fc3bee942a60e9500
child 38817 c3de74d507fb83a8b20487ea4194c4a007cff1d4
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs537139
milestone1.9.3a3pre
Bug 537139: Prevent SMIL animation from triggering CSS transitions. r=dbaron
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/nsHTMLCSSStyleSheet.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -11141,39 +11141,44 @@ nsCSSFrameConstructor::ProcessPendingRes
 #ifdef DEBUG
   mPresShell->VerifyStyleTree();
 #endif
 }
 
 void
 nsCSSFrameConstructor::ProcessPendingRestyles()
 {
-  NS_PRECONDITION(mDocument, "No document?  Pshaw!\n");
+  NS_PRECONDITION(mDocument, "No document?  Pshaw!");
   NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
                   "Missing a script blocker!");
 
   // Process non-animation restyles...
+  nsPresContext *presContext = mPresShell->GetPresContext();
+  NS_ABORT_IF_FALSE(!presContext->IsProcessingRestyles(),
+                    "Nesting calls to ProcessPendingRestyles?");
+  presContext->SetProcessingRestyles(PR_TRUE);
+
   ProcessPendingRestyleTable(mPendingRestyles);
 
   NS_POSTCONDITION(mPendingRestyles.Count() == 0,
                    "We should have processed mPendingRestyles to completion");
 
   // ...and then process animation restyles.  This needs to happen
   // second because we need to start animations that resulted from the
   // first set of restyles (e.g., CSS transitions with negative
   // transition-delay), and because we need to immediately
   // restyle-with-animation any just-restyled elements that are
   // mid-transition (since processing the non-animation restyle ignores
   // the running transition so it can check for a new change on the same
   // property, and then posts an immediate animation style change).
-  nsPresContext *presContext = mPresShell->GetPresContext();
   presContext->SetProcessingAnimationStyleChange(PR_TRUE);
   ProcessPendingRestyleTable(mPendingAnimationRestyles);
   presContext->SetProcessingAnimationStyleChange(PR_FALSE);
 
+  presContext->SetProcessingRestyles(PR_FALSE);
   mInStyleRefresh = PR_FALSE;
 
   NS_POSTCONDITION(mPendingAnimationRestyles.Count() == 0,
                    "We should have processed mPendingAnimationRestyles to "
                    "completion");
   NS_POSTCONDITION(mPendingRestyles.Count() == 0,
                    "We should not have posted new non-animation restyles while "
                    "processing animation restyles");
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -199,19 +199,17 @@ nsPresContext::nsPresContext(nsIDocument
     mDefaultMonospaceFont("monospace", NS_FONT_STYLE_NORMAL,
                           NS_FONT_VARIANT_NORMAL, NS_FONT_WEIGHT_NORMAL,
                           NS_FONT_STRETCH_NORMAL, 0, 0),
     mDefaultCursiveFont("cursive", NS_FONT_STYLE_NORMAL,
                         NS_FONT_VARIANT_NORMAL, NS_FONT_WEIGHT_NORMAL,
                         NS_FONT_STRETCH_NORMAL, 0, 0),
     mDefaultFantasyFont("fantasy", NS_FONT_STYLE_NORMAL,
                         NS_FONT_VARIANT_NORMAL, NS_FONT_WEIGHT_NORMAL,
-                        NS_FONT_STRETCH_NORMAL, 0, 0),
-    mCanPaginatedScroll(PR_FALSE),
-    mIsRootPaginatedDocument(PR_FALSE), mSupressResizeReflow(PR_FALSE)
+                        NS_FONT_STRETCH_NORMAL, 0, 0)
 {
   // NOTE! nsPresContext::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
   mDoScaledTwips = PR_TRUE;
 
   SetBackgroundImageDraw(PR_TRUE);		// always draw the background
   SetBackgroundColorDraw(PR_TRUE);
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -847,16 +847,26 @@ public:
   PRBool IsDOMPaintEventPending() {
     return !mInvalidateRequests.mRequests.IsEmpty();
   }
 
   void ClearMozAfterPaintEvents() {
     mInvalidateRequests.mRequests.Clear();
   }
 
+  PRBool IsProcessingRestyles() const {
+    return mProcessingRestyles;
+  }
+
+  void SetProcessingRestyles(PRBool aProcessing) {
+    NS_ASSERTION(aProcessing != PRBool(mProcessingRestyles),
+                 "should never nest");
+    mProcessingRestyles = aProcessing;
+  }
+
   PRBool IsProcessingAnimationStyleChange() const {
     return mProcessingAnimationStyleChange;
   }
 
   void SetProcessingAnimationStyleChange(PRBool aProcessing) {
     NS_ASSERTION(aProcessing != PRBool(mProcessingAnimationStyleChange),
                  "should never nest");
     mProcessingAnimationStyleChange = aProcessing;
@@ -1101,16 +1111,17 @@ protected:
   unsigned              mPostedFlushUserFontSet : 1;
 
   // resize reflow is supressed when the only change has been to zoom
   // the document rather than to change the document's dimensions
   unsigned              mSupressResizeReflow : 1;
 
   unsigned              mIsVisual : 1;
 
+  unsigned              mProcessingRestyles : 1;
   unsigned              mProcessingAnimationStyleChange : 1;
 
 #ifdef DEBUG
   PRBool                mInitialized;
 #endif
 
 
 protected:
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -82,18 +82,28 @@ nsHTMLCSSStyleSheet::RulesMatching(Eleme
   if (rule) {
     rule->RuleMatched();
     aData->mRuleWalker->Forward(rule);
   }
 
 #ifdef MOZ_SMIL
   rule = content->GetSMILOverrideStyleRule();
   if (rule) {
-    rule->RuleMatched();
-    aData->mRuleWalker->Forward(rule);
+    if (aData->mPresContext->IsProcessingRestyles() &&
+        !aData->mPresContext->IsProcessingAnimationStyleChange()) {
+      // Non-animation restyle -- don't process SMIL override style, because we
+      // don't want SMIL animation to trigger new CSS transitions. Instead,
+      // request an Animation restyle, so we still get noticed.
+      aData->mPresContext->PresShell()->RestyleForAnimation(aData->mContent);
+    } else {
+      // Animation restyle (or non-restyle traversal of rules)
+      // Now we can walk SMIL overrride style, without triggering transitions.
+      rule->RuleMatched();
+      aData->mRuleWalker->Forward(rule);
+    }
   }
 #endif // MOZ_SMIL
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLCSSStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)