зеркало из https://github.com/mozilla/pjs.git
Stop transitions when -moz-transition-property changes to a value that no longer includes the transitioning property. (Bug 525530) r=bzbarsky
This commit is contained in:
Родитель
6f0f6ea0ea
Коммит
b4797974ce
|
@ -1918,15 +1918,16 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Our current behavior for handling changes to transition
|
// Note: Our current behavior for handling changes to the
|
||||||
|
// transition-duration, transition-delay, and transition-timing-function
|
||||||
// properties is to do nothing. In other words, the transition
|
// properties is to do nothing. In other words, the transition
|
||||||
// property that matters is what it is when the transition begins, and
|
// property that matters is what it is when the transition begins, and
|
||||||
// we don't stop a transition later because the transition property
|
// we don't stop a transition later because the transition property
|
||||||
// changed.
|
// changed.
|
||||||
// FIXME (Bug 522599): Need to test for this and write it in the
|
// We do handle changes to transition-property, but we don't need to
|
||||||
// spec, if it's compatible with other browsers. Test for behavior at
|
// bother with anything here, since the transition manager is notified
|
||||||
// http://dbaron.org/css/test/2009/transitions/dynamic-transition-change
|
// of any style context change anyway.
|
||||||
|
|
||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,12 +358,20 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement,
|
||||||
aNewStyleContext->HasPseudoElementData(),
|
aNewStyleContext->HasPseudoElementData(),
|
||||||
"pseudo type mismatch");
|
"pseudo type mismatch");
|
||||||
|
|
||||||
|
// NOTE: Things in this function (and ConsiderStartingTransition)
|
||||||
|
// should never call PeekStyleData because we don't preserve gotten
|
||||||
|
// structs across reframes.
|
||||||
|
|
||||||
// Return sooner (before the startedAny check below) for the most
|
// Return sooner (before the startedAny check below) for the most
|
||||||
// common case: no transitions specified.
|
// common case: no transitions specified.
|
||||||
const nsStyleDisplay *disp = aNewStyleContext->GetStyleDisplay();
|
const nsStyleDisplay *disp = aNewStyleContext->GetStyleDisplay();
|
||||||
|
const nsStyleDisplay *oldDisp = aOldStyleContext->GetStyleDisplay();
|
||||||
if (disp->mTransitionPropertyCount == 1 &&
|
if (disp->mTransitionPropertyCount == 1 &&
|
||||||
|
oldDisp->mTransitionPropertyCount == 1 &&
|
||||||
disp->mTransitions[0].GetDelay() == 0.0f &&
|
disp->mTransitions[0].GetDelay() == 0.0f &&
|
||||||
disp->mTransitions[0].GetDuration() == 0.0f) {
|
disp->mTransitions[0].GetDuration() == 0.0f &&
|
||||||
|
oldDisp->mTransitions[0].GetProperty() ==
|
||||||
|
disp->mTransitions[0].GetProperty()) {
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,16 +400,17 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement,
|
||||||
// ones (tracked using |whichStarted|).
|
// ones (tracked using |whichStarted|).
|
||||||
PRBool startedAny = PR_FALSE;
|
PRBool startedAny = PR_FALSE;
|
||||||
nsCSSPropertySet whichStarted;
|
nsCSSPropertySet whichStarted;
|
||||||
ElementTransitions *et = nsnull;
|
ElementTransitions *et =
|
||||||
|
GetElementTransitions(aElement, pseudoType, PR_FALSE);
|
||||||
for (PRUint32 i = disp->mTransitionPropertyCount; i-- != 0; ) {
|
for (PRUint32 i = disp->mTransitionPropertyCount; i-- != 0; ) {
|
||||||
const nsTransition& t = disp->mTransitions[i];
|
const nsTransition& t = disp->mTransitions[i];
|
||||||
// Check delay and duration first, since they default to zero, and
|
// Check delay and duration first, since they default to zero, and
|
||||||
// when they're both zero, we can ignore the transition.
|
// when they're both zero, we can ignore the transition.
|
||||||
if (t.GetDelay() != 0.0f || t.GetDuration() != 0.0f) {
|
if (t.GetDelay() != 0.0f || t.GetDuration() != 0.0f) {
|
||||||
et = GetElementTransitions(aElement, pseudoType, PR_FALSE);
|
|
||||||
|
|
||||||
// We might have something to transition. See if any of the
|
// We might have something to transition. See if any of the
|
||||||
// properties in question changed and are animatable.
|
// properties in question changed and are animatable.
|
||||||
|
// FIXME: Would be good to find a way to share code between this
|
||||||
|
// interpretation of transition-property and the one below.
|
||||||
nsCSSProperty property = t.GetProperty();
|
nsCSSProperty property = t.GetProperty();
|
||||||
if (property == eCSSPropertyExtra_no_properties ||
|
if (property == eCSSPropertyExtra_no_properties ||
|
||||||
property == eCSSProperty_UNKNOWN) {
|
property == eCSSProperty_UNKNOWN) {
|
||||||
|
@ -428,6 +437,51 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop any transitions for properties that are no longer in
|
||||||
|
// 'transition-property'.
|
||||||
|
if (et && disp->mTransitions[0].GetProperty() !=
|
||||||
|
eCSSPropertyExtra_all_properties) {
|
||||||
|
nsCSSPropertySet allTransitionProperties;
|
||||||
|
for (PRUint32 i = disp->mTransitionPropertyCount; i-- != 0; ) {
|
||||||
|
const nsTransition& t = disp->mTransitions[i];
|
||||||
|
// FIXME: Would be good to find a way to share code between this
|
||||||
|
// interpretation of transition-property and the one above.
|
||||||
|
nsCSSProperty property = t.GetProperty();
|
||||||
|
if (property == eCSSPropertyExtra_no_properties ||
|
||||||
|
property == eCSSProperty_UNKNOWN) {
|
||||||
|
// Nothing to do, but need to exclude this from cases below.
|
||||||
|
} else if (property == eCSSPropertyExtra_all_properties) {
|
||||||
|
for (nsCSSProperty p = nsCSSProperty(0);
|
||||||
|
p < eCSSProperty_COUNT_no_shorthands;
|
||||||
|
p = nsCSSProperty(p + 1)) {
|
||||||
|
allTransitionProperties.AddProperty(p);
|
||||||
|
}
|
||||||
|
} else if (nsCSSProps::IsShorthand(property)) {
|
||||||
|
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, property) {
|
||||||
|
allTransitionProperties.AddProperty(*subprop);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allTransitionProperties.AddProperty(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<ElementPropertyTransition> &pts = et->mPropertyTransitions;
|
||||||
|
PRUint32 i = pts.Length();
|
||||||
|
NS_ABORT_IF_FALSE(i != 0, "empty transitions list?");
|
||||||
|
do {
|
||||||
|
--i;
|
||||||
|
ElementPropertyTransition &pt = pts[i];
|
||||||
|
if (!allTransitionProperties.HasProperty(pt.mProperty)) {
|
||||||
|
pts.RemoveElementAt(i);
|
||||||
|
}
|
||||||
|
} while (i != 0);
|
||||||
|
|
||||||
|
if (pts.IsEmpty()) {
|
||||||
|
et->Destroy();
|
||||||
|
et = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!startedAny) {
|
if (!startedAny) {
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
@ -542,7 +596,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
|
||||||
// |aElementTransitions| is now a dangling pointer!
|
// |aElementTransitions| is now a dangling pointer!
|
||||||
aElementTransitions = nsnull;
|
aElementTransitions = nsnull;
|
||||||
}
|
}
|
||||||
presContext->PresShell()->RestyleForAnimation(aElement);
|
// WalkTransitionRule already called RestyleForAnimation.
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -564,9 +618,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
|
||||||
// If we got a style change that changed the value to the endpoint
|
// If we got a style change that changed the value to the endpoint
|
||||||
// of the currently running transition, we don't want to interrupt
|
// of the currently running transition, we don't want to interrupt
|
||||||
// its timing function.
|
// its timing function.
|
||||||
// But don't forget to restyle with animation so we show the
|
// WalkTransitionRule already called RestyleForAnimation.
|
||||||
// current transition.
|
|
||||||
presContext->PresShell()->RestyleForAnimation(aElement);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,15 +764,7 @@ nsresult
|
||||||
nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
|
nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
|
||||||
nsCSSPseudoElements::Type aPseudoType)
|
nsCSSPseudoElements::Type aPseudoType)
|
||||||
{
|
{
|
||||||
if (!aData->mPresContext->IsProcessingAnimationStyleChange()) {
|
if (!aData->mContent) {
|
||||||
// If we're processing a normal style change rather than one from
|
|
||||||
// animation, don't add the transition rule. This allows us to
|
|
||||||
// compute the new style value rather than having the transition
|
|
||||||
// override it, so that we can start transitioning differently.
|
|
||||||
|
|
||||||
// In most cases, we need to immediately restyle with animation
|
|
||||||
// after doing this. However, ConsiderStartingTransition takes care
|
|
||||||
// of that for us.
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,6 +774,20 @@ nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!aData->mPresContext->IsProcessingAnimationStyleChange()) {
|
||||||
|
// If we're processing a normal style change rather than one from
|
||||||
|
// animation, don't add the transition rule. This allows us to
|
||||||
|
// compute the new style value rather than having the transition
|
||||||
|
// override it, so that we can start transitioning differently.
|
||||||
|
|
||||||
|
// We need to immediately restyle with animation
|
||||||
|
// after doing this.
|
||||||
|
if (et) {
|
||||||
|
mPresContext->PresShell()->RestyleForAnimation(aData->mContent);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (!et->EnsureStyleRuleFor(
|
if (!et->EnsureStyleRuleFor(
|
||||||
aData->mPresContext->RefreshDriver()->MostRecentRefresh())) {
|
aData->mPresContext->RefreshDriver()->MostRecentRefresh())) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
|
@ -140,6 +140,7 @@ _TEST_FILES = test_acid3_test46.html \
|
||||||
test_transitions_computed_value_combinations.html \
|
test_transitions_computed_value_combinations.html \
|
||||||
test_transitions.html \
|
test_transitions.html \
|
||||||
test_transitions_per_property.html \
|
test_transitions_per_property.html \
|
||||||
|
test_transitions_dynamic_changes.html \
|
||||||
test_units_angle.html \
|
test_units_angle.html \
|
||||||
test_units_frequency.html \
|
test_units_frequency.html \
|
||||||
test_units_length.html \
|
test_units_length.html \
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=525530
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 525530</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=525530">Mozilla Bug 525530</a>
|
||||||
|
<p id="display" style="text-indent: 100px"></p>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 525530 **/
|
||||||
|
|
||||||
|
var p = document.getElementById("display");
|
||||||
|
var cs = getComputedStyle(p, "");
|
||||||
|
|
||||||
|
p.style.MozTransitionProperty = "all";
|
||||||
|
p.style.MozTransitionDuration = "4s";
|
||||||
|
p.style.MozTransitionDelay = "-2s";
|
||||||
|
p.style.MozTransitionTimingFunction = "linear";
|
||||||
|
|
||||||
|
is(cs.textIndent, "100px", "initial value");
|
||||||
|
|
||||||
|
p.style.textIndent = "0";
|
||||||
|
is(cs.textIndent, "50px", "transition is halfway");
|
||||||
|
p.style.MozTransitionDuration = "0s";
|
||||||
|
is(cs.textIndent, "50px", "changing duration doesn't change transitioning");
|
||||||
|
p.style.MozTransitionDelay = "0s";
|
||||||
|
is(cs.textIndent, "50px", "changing delay doesn't change transitioning");
|
||||||
|
p.style.MozTransitionProperty = "text-indent";
|
||||||
|
is(cs.textIndent, "50px",
|
||||||
|
"irrelevant change to transition property doesn't change transitioning");
|
||||||
|
p.style.MozTransitionProperty = "font";
|
||||||
|
is(cs.textIndent, "0px",
|
||||||
|
"relevant change to transition property does change transitioning");
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
Загрузка…
Ссылка в новой задаче