Bug 1315874 part 2 - Skip creating CSS-Transition when SMIL restyling. r?dbaron
Currently composing smil attribute will call nsSMILCSSProperty::GetBaseValue().
In this procecss, we will call updating style with eStyle_StyleAttribute and eStyle_StyleAttribute_Animations hints.[1]
So RestyleManager will create transition since we didn't notify to the TransitionManager this updating style is for animations.
Usually we will notify this after composing smil attribute. [2][3]
[1] https://dxr.mozilla.org/mozilla-central/rev/8103c612b79c2587ea4ca1b0a9f9f82db4b185b8/dom/base/Element.cpp#1987
[2] https://dxr.mozilla.org/mozilla-central/rev/5ce3882eec21be3a70e4afc050959ca2f76bfa76/dom/smil/nsSMILAnimationController.cpp#448-454
[3] https://dxr.mozilla.org/mozilla-central/rev/5ce3882eec21be3a70e4afc050959ca2f76bfa76/layout/base/RestyleManager.cpp#910-919
In this patch, nsSMILCSSProperty will notify to the TransitionManager that this updating style is for animations when updating style.
MozReview-Commit-ID: 1sUnr2j8Jyu
--- a/dom/smil/nsSMILCSSProperty.cpp
+++ b/dom/smil/nsSMILCSSProperty.cpp
@@ -11,16 +11,17 @@
#include "mozilla/dom/Element.h"
#include "mozilla/Move.h"
#include "nsSMILCSSValueType.h"
#include "nsSMILValue.h"
#include "nsComputedDOMStyle.h"
#include "nsCSSProps.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
+#include "nsContentUtils.h"
using namespace mozilla::dom;
// Helper function
static bool
GetCSSComputedValue(Element* aElem,
nsCSSPropertyID aPropID,
nsAString& aResult)
@@ -97,34 +98,42 @@ nsSMILCSSProperty::GetBaseValue() const
// (Don't bother clearing override style if it's already empty)
if (!cachedOverrideStyleVal.IsEmpty()) {
overrideDecl->SetPropertyValue(mPropID, EmptyString());
}
}
// (2) Get Computed Style
nsAutoString computedStyleVal;
+ // In GetCSSComputedValue(), we will update style. So we need to prevent
+ // creating a CSS Transition.
+ SetAnimationOnlyStyleUpdateToTransitionManager();
bool didGetComputedVal = GetCSSComputedValue(mElement, mPropID,
computedStyleVal);
+ UnsetAnimationOnlyStyleUpdateToTransitionManager();
// (3) Put cached override style back (if it's non-empty)
if (overrideDecl && !cachedOverrideStyleVal.IsEmpty()) {
overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
}
// (4) Populate our nsSMILValue from the computed style
if (didGetComputedVal) {
+ // In ValueFromString(), we will upadte style. So we need to prevent
+ // creating a CSS Transition.
+ SetAnimationOnlyStyleUpdateToTransitionManager();
// When we parse animation values we check if they are context-sensitive or
// not so that we don't cache animation values whose meaning may change.
// For base values however this is unnecessary since on each sample the
// compositor will fetch the (computed) base value and compare it against
// the cached (computed) value and detect changes for us.
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
computedStyleVal, baseValue,
nullptr);
+ UnsetAnimationOnlyStyleUpdateToTransitionManager();
}
return baseValue;
}
nsresult
nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
const SVGAnimationElement* aSrcElement,
nsSMILValue& aValue,
@@ -268,8 +277,41 @@ nsSMILCSSProperty::IsPropertyAnimatable(
case eCSSProperty_direction:
case eCSSProperty_unicode_bidi:
return false;
default:
return false;
}
}
+
+void
+nsSMILCSSProperty::SetAnimationOnlyStyleUpdateToTransitionManager() const
+{
+ nsTransitionManager* manager = GetTransitionManager();
+ if (manager) {
+ manager->SetInAnimationOnlyStyleUpdate(true);
+ }
+}
+
+void
+nsSMILCSSProperty::UnsetAnimationOnlyStyleUpdateToTransitionManager() const
+{
+ nsTransitionManager* manager = GetTransitionManager();
+ if (manager) {
+ manager->SetInAnimationOnlyStyleUpdate(false);
+ }
+}
+
+nsTransitionManager*
+nsSMILCSSProperty::GetTransitionManager() const
+{
+ if (!mElement) {
+ return nullptr;
+ }
+
+ nsPresContext* context = nsContentUtils::GetContextForContent(mElement);
+ if (!context) {
+ return nullptr;
+ }
+
+ return context->TransitionManager();
+}
--- a/dom/smil/nsSMILCSSProperty.h
+++ b/dom/smil/nsSMILCSSProperty.h
@@ -9,16 +9,17 @@
#ifndef NS_SMILCSSPROPERTY_H_
#define NS_SMILCSSPROPERTY_H_
#include "mozilla/Attributes.h"
#include "nsISMILAttr.h"
#include "nsIAtom.h"
#include "nsCSSPropertyID.h"
#include "nsCSSValue.h"
+#include "nsTransitionManager.h"
namespace mozilla {
namespace dom {
class Element;
} // namespace dom
} // namespace mozilla
/**
@@ -57,11 +58,21 @@ public:
protected:
nsCSSPropertyID mPropID;
// Using non-refcounted pointer for mElement -- we know mElement will stay
// alive for my lifetime because a nsISMILAttr (like me) only lives as long
// as the Compositing step, and DOM elements don't get a chance to die during
// that time.
mozilla::dom::Element* mElement;
+
+ // Notify that this updating style is for animation(SMIL)
+ // to the TransitionManager.
+ // If we doesn't notify this, TransitionManager will create new Transition
+ // since we notify this after composing smil css attribute.
+ // For detail, see nsSMILCompositor::ComposeAttribute.
+ void SetAnimationOnlyStyleUpdateToTransitionManager() const;
+ void UnsetAnimationOnlyStyleUpdateToTransitionManager() const;
+
+ nsTransitionManager* GetTransitionManager() const;
};
#endif // NS_SMILCSSPROPERTY_H_
--- a/dom/smil/test/test_smilWithTransition.html
+++ b/dom/smil/test/test_smilWithTransition.html
@@ -32,17 +32,17 @@ https://bugzilla.mozilla.org/show_bug.cg
svg.setCurrentTime(1);
ok(getComputedStyle(rect).fill, "rgb(0, 255, 0)",
"The end color should be lime.");
// wait to 2 frame for restyle to the current SMIL.
return waitForAnimationFrames(2);
}).then(function() {
var anim = document.getAnimations()[0];
- todo(!anim, "CSS-Transition shouldn't created by restyling of SMIL.");
+ ok(!anim, "CSS-Transition shouldn't created by restyling of SMIL.");
SimpleTest.finish();
});
}
// Utility methods from testscommon.js
// For detail, see dom/animationte/test/testcommon.js.