зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1278136
- Part 5: Create a stacking context for opacity/transform animations even if it's in delay phase and even if the property is overridden by !important rules. r=birtles
This patch introduces a new functions named HasEffectiveAnimationOfProperty. This function checks that a given CSS property is overridden by !important rules. On the other hand, now KeyframeEffetReadOnly::HasAnimationOfProperty() does just check that the effect has a given CSS property. This is used to create a stacking context because we should create a stacking context for opacity or transform animations even if the property is overridden by !important rules. MozReview-Commit-ID: AG1Y0IgoB3U
This commit is contained in:
Родитель
5443b7cdf5
Коммит
d7f92dae54
|
@ -148,7 +148,7 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!effect->HasAnimationOfProperty(aProperty)) {
|
if (!effect->HasEffectiveAnimationOfProperty(aProperty)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,8 @@ KeyframeEffectReadOnly::SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnimationProperty*
|
const AnimationProperty*
|
||||||
KeyframeEffectReadOnly::GetAnimationOfProperty(nsCSSPropertyID aProperty) const
|
KeyframeEffectReadOnly::GetEffectiveAnimationOfProperty(
|
||||||
|
nsCSSPropertyID aProperty) const
|
||||||
{
|
{
|
||||||
if (!IsInEffect()) {
|
if (!IsInEffect()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -219,6 +220,17 @@ KeyframeEffectReadOnly::GetAnimationOfProperty(nsCSSPropertyID aProperty) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
KeyframeEffectReadOnly::HasAnimationOfProperty(nsCSSPropertyID aProperty) const
|
||||||
|
{
|
||||||
|
for (const AnimationProperty& property : mProperties) {
|
||||||
|
if (property.mProperty == aProperty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool
|
bool
|
||||||
SpecifiedKeyframeArraysAreEqual(const nsTArray<Keyframe>& aA,
|
SpecifiedKeyframeArraysAreEqual(const nsTArray<Keyframe>& aA,
|
||||||
|
@ -926,10 +938,12 @@ KeyframeEffectReadOnly::CanThrottle() const
|
||||||
// already running on compositor.
|
// already running on compositor.
|
||||||
for (const LayerAnimationInfo::Record& record :
|
for (const LayerAnimationInfo::Record& record :
|
||||||
LayerAnimationInfo::sRecords) {
|
LayerAnimationInfo::sRecords) {
|
||||||
// Skip properties that are overridden in the cascade.
|
// Skip properties that are overridden by !important rules.
|
||||||
// (GetAnimationOfProperty, as called by HasAnimationOfProperty,
|
// (GetEffectiveAnimationOfProperty, as called by
|
||||||
// only returns an animation if it currently wins in the cascade.)
|
// HasEffectiveAnimationOfProperty, only returns a property which is
|
||||||
if (!HasAnimationOfProperty(record.mProperty)) {
|
// neither overridden by !important rules nor overridden by other
|
||||||
|
// animation.)
|
||||||
|
if (!HasEffectiveAnimationOfProperty(record.mProperty)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,12 +235,25 @@ public:
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
|
void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
|
||||||
nsStyleContext* aStyleContext);
|
nsStyleContext* aStyleContext);
|
||||||
const AnimationProperty*
|
|
||||||
GetAnimationOfProperty(nsCSSPropertyID aProperty) const;
|
// Returns true if the effect includes |aProperty| regardless of whether the
|
||||||
bool HasAnimationOfProperty(nsCSSPropertyID aProperty) const
|
// property is overridden by !important rule.
|
||||||
|
bool HasAnimationOfProperty(nsCSSPropertyID aProperty) const;
|
||||||
|
|
||||||
|
// GetEffectiveAnimationOfProperty returns AnimationProperty corresponding
|
||||||
|
// to a given CSS property if the effect includes the property and the
|
||||||
|
// property is not overridden by !important rules.
|
||||||
|
// Also EffectiveAnimationOfProperty returns true under the same condition.
|
||||||
|
//
|
||||||
|
// NOTE: We don't currently check for !important rules for properties that
|
||||||
|
// can't run on the compositor.
|
||||||
|
bool HasEffectiveAnimationOfProperty(nsCSSPropertyID aProperty) const
|
||||||
{
|
{
|
||||||
return GetAnimationOfProperty(aProperty) != nullptr;
|
return GetEffectiveAnimationOfProperty(aProperty) != nullptr;
|
||||||
}
|
}
|
||||||
|
const AnimationProperty* GetEffectiveAnimationOfProperty(
|
||||||
|
nsCSSPropertyID aProperty) const;
|
||||||
|
|
||||||
const InfallibleTArray<AnimationProperty>& Properties() const
|
const InfallibleTArray<AnimationProperty>& Properties() const
|
||||||
{
|
{
|
||||||
return mProperties;
|
return mProperties;
|
||||||
|
|
|
@ -1569,8 +1569,7 @@ ElementRestyler::AddLayerChangesForAnimation()
|
||||||
// setKeyframes or changing target element from other target which prevents
|
// setKeyframes or changing target element from other target which prevents
|
||||||
// running on the compositor, etc.
|
// running on the compositor, etc.
|
||||||
if (!layer &&
|
if (!layer &&
|
||||||
nsLayoutUtils::HasRelevantAnimationOfProperty(mFrame,
|
nsLayoutUtils::HasEffectiveAnimation(mFrame, layerInfo.mProperty)) {
|
||||||
layerInfo.mProperty)) {
|
|
||||||
hint |= layerInfo.mChangeHint;
|
hint |= layerInfo.mChangeHint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,21 +487,21 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSPropertyID aProperty,
|
||||||
MOZ_ASSERT(keyframeEffect,
|
MOZ_ASSERT(keyframeEffect,
|
||||||
"A playing animation should have a keyframe effect");
|
"A playing animation should have a keyframe effect");
|
||||||
const AnimationProperty* property =
|
const AnimationProperty* property =
|
||||||
keyframeEffect->GetAnimationOfProperty(aProperty);
|
keyframeEffect->GetEffectiveAnimationOfProperty(aProperty);
|
||||||
if (!property) {
|
if (!property) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that if the property is overridden by !important rules,
|
// Note that if the property is overridden by !important rules,
|
||||||
// GetAnimationOfProperty returns null instead.
|
// GetEffectiveAnimationOfProperty returns null instead.
|
||||||
// This is what we want, since if we have animations overridden by
|
// This is what we want, since if we have animations overridden by
|
||||||
// !important rules, we don't want to send them to the compositor.
|
// !important rules, we don't want to send them to the compositor.
|
||||||
MOZ_ASSERT(anim->CascadeLevel() !=
|
MOZ_ASSERT(anim->CascadeLevel() !=
|
||||||
EffectCompositor::CascadeLevel::Animations ||
|
EffectCompositor::CascadeLevel::Animations ||
|
||||||
!effects->PropertiesWithImportantRules()
|
!effects->PropertiesWithImportantRules()
|
||||||
.HasProperty(aProperty),
|
.HasProperty(aProperty),
|
||||||
"GetAnimationOfProperty already tested the property is not "
|
"GetEffectiveAnimationOfProperty already tested the property "
|
||||||
"overridden by !important rules");
|
"is not overridden by !important rules");
|
||||||
|
|
||||||
// Don't add animations that are pending if their timeline does not
|
// Don't add animations that are pending if their timeline does not
|
||||||
// track wallclock time. This is because any pending animations on layers
|
// track wallclock time. This is because any pending animations on layers
|
||||||
|
|
|
@ -483,7 +483,7 @@ nsLayoutUtils::HasActiveAnimationOfProperty(const nsIFrame* aFrame,
|
||||||
[&aProperty](KeyframeEffectReadOnly& aEffect)
|
[&aProperty](KeyframeEffectReadOnly& aEffect)
|
||||||
{
|
{
|
||||||
return aEffect.IsCurrent() && aEffect.IsInEffect() &&
|
return aEffect.IsCurrent() && aEffect.IsInEffect() &&
|
||||||
aEffect.HasAnimationOfProperty(aProperty);
|
aEffect.HasEffectiveAnimationOfProperty(aProperty);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -502,8 +502,8 @@ nsLayoutUtils::HasCurrentTransitions(const nsIFrame* aFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsLayoutUtils::HasRelevantAnimationOfProperty(const nsIFrame* aFrame,
|
nsLayoutUtils::HasAnimationOfProperty(const nsIFrame* aFrame,
|
||||||
nsCSSPropertyID aProperty)
|
nsCSSPropertyID aProperty)
|
||||||
{
|
{
|
||||||
return HasMatchingAnimations(aFrame,
|
return HasMatchingAnimations(aFrame,
|
||||||
[&aProperty](KeyframeEffectReadOnly& aEffect)
|
[&aProperty](KeyframeEffectReadOnly& aEffect)
|
||||||
|
@ -514,6 +514,19 @@ nsLayoutUtils::HasRelevantAnimationOfProperty(const nsIFrame* aFrame,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsLayoutUtils::HasEffectiveAnimation(const nsIFrame* aFrame,
|
||||||
|
nsCSSPropertyID aProperty)
|
||||||
|
{
|
||||||
|
return HasMatchingAnimations(aFrame,
|
||||||
|
[&aProperty](KeyframeEffectReadOnly& aEffect)
|
||||||
|
{
|
||||||
|
return (aEffect.IsInEffect() || aEffect.IsCurrent()) &&
|
||||||
|
aEffect.HasEffectiveAnimationOfProperty(aProperty);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static float
|
static float
|
||||||
GetSuitableScale(float aMaxScale, float aMinScale,
|
GetSuitableScale(float aMaxScale, float aMinScale,
|
||||||
nscoord aVisibleDimension, nscoord aDisplayDimension)
|
nscoord aVisibleDimension, nscoord aDisplayDimension)
|
||||||
|
|
|
@ -2244,12 +2244,18 @@ public:
|
||||||
static bool HasCurrentTransitions(const nsIFrame* aFrame);
|
static bool HasCurrentTransitions(const nsIFrame* aFrame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the frame has current or in-effect (i.e. in before phase,
|
* Returns true if |aFrame| has an animation of |aProperty| regardless of
|
||||||
* running or filling) animations or transitions for the
|
* whether the property is overridden by !important rule.
|
||||||
* property.
|
|
||||||
*/
|
*/
|
||||||
static bool HasRelevantAnimationOfProperty(const nsIFrame* aFrame,
|
static bool HasAnimationOfProperty(const nsIFrame* aFrame,
|
||||||
nsCSSPropertyID aProperty);
|
nsCSSPropertyID aProperty);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if |aFrame| has an animation of |aProperty| which is
|
||||||
|
* not overridden by !important rules.
|
||||||
|
*/
|
||||||
|
static bool HasEffectiveAnimation(const nsIFrame* aFrame,
|
||||||
|
nsCSSPropertyID aProperty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if off-main-thread animations are enabled.
|
* Checks if off-main-thread animations are enabled.
|
||||||
|
|
|
@ -554,8 +554,7 @@ nsFrame::Init(nsIContent* aContent,
|
||||||
}
|
}
|
||||||
const nsStyleDisplay *disp = StyleDisplay();
|
const nsStyleDisplay *disp = StyleDisplay();
|
||||||
if (disp->HasTransform(this) ||
|
if (disp->HasTransform(this) ||
|
||||||
nsLayoutUtils::HasRelevantAnimationOfProperty(this,
|
nsLayoutUtils::HasAnimationOfProperty(this, eCSSProperty_transform)) {
|
||||||
eCSSProperty_transform)) {
|
|
||||||
// The frame gets reconstructed if we toggle the -moz-transform
|
// The frame gets reconstructed if we toggle the -moz-transform
|
||||||
// property, so we can set this bit here and then ignore it.
|
// property, so we can set this bit here and then ignore it.
|
||||||
mState |= NS_FRAME_MAY_BE_TRANSFORMED;
|
mState |= NS_FRAME_MAY_BE_TRANSFORMED;
|
||||||
|
@ -1140,8 +1139,8 @@ nsIFrame::IsTransformed() const
|
||||||
(StyleDisplay()->HasTransform(this) ||
|
(StyleDisplay()->HasTransform(this) ||
|
||||||
IsSVGTransformed() ||
|
IsSVGTransformed() ||
|
||||||
(mContent &&
|
(mContent &&
|
||||||
nsLayoutUtils::HasRelevantAnimationOfProperty(
|
nsLayoutUtils::HasAnimationOfProperty(this,
|
||||||
this, eCSSProperty_transform) &&
|
eCSSProperty_transform) &&
|
||||||
IsFrameOfType(eSupportsCSSTransforms) &&
|
IsFrameOfType(eSupportsCSSTransforms) &&
|
||||||
mContent->GetPrimaryFrame() == this)));
|
mContent->GetPrimaryFrame() == this)));
|
||||||
}
|
}
|
||||||
|
@ -1153,8 +1152,7 @@ nsIFrame::HasOpacityInternal(float aThreshold) const
|
||||||
return StyleEffects()->mOpacity < aThreshold ||
|
return StyleEffects()->mOpacity < aThreshold ||
|
||||||
(StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) ||
|
(StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) ||
|
||||||
(mContent &&
|
(mContent &&
|
||||||
nsLayoutUtils::HasRelevantAnimationOfProperty(
|
nsLayoutUtils::HasAnimationOfProperty(this, eCSSProperty_opacity) &&
|
||||||
this, eCSSProperty_opacity) &&
|
|
||||||
mContent->GetPrimaryFrame() == this);
|
mContent->GetPrimaryFrame() == this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2115,8 +2113,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
bool opacityItemForEventsAndPluginsOnly = false;
|
bool opacityItemForEventsAndPluginsOnly = false;
|
||||||
if (effects->mOpacity == 0.0 && aBuilder->IsForPainting() &&
|
if (effects->mOpacity == 0.0 && aBuilder->IsForPainting() &&
|
||||||
!(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
|
!(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
|
||||||
!nsLayoutUtils::HasActiveAnimationOfProperty(this,
|
!nsLayoutUtils::HasAnimationOfProperty(this, eCSSProperty_opacity)) {
|
||||||
eCSSProperty_opacity)) {
|
|
||||||
if (needEventRegions ||
|
if (needEventRegions ||
|
||||||
aBuilder->WillComputePluginGeometry()) {
|
aBuilder->WillComputePluginGeometry()) {
|
||||||
opacityItemForEventsAndPluginsOnly = true;
|
opacityItemForEventsAndPluginsOnly = true;
|
||||||
|
|
|
@ -14,8 +14,8 @@ test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-co
|
||||||
test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-transform-none-animation.html stacking-context-animation-ref.html
|
test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-transform-none-animation.html stacking-context-animation-ref.html
|
||||||
== no-stacking-context-opacity-removing-animation-in-delay.html no-stacking-context-animation-ref.html
|
== no-stacking-context-opacity-removing-animation-in-delay.html no-stacking-context-animation-ref.html
|
||||||
== no-stacking-context-transform-removing-animation-in-delay.html no-stacking-context-animation-ref.html
|
== no-stacking-context-transform-removing-animation-in-delay.html no-stacking-context-animation-ref.html
|
||||||
fails == stacking-context-lose-opacity-1.html stacking-context-animation-ref.html
|
== stacking-context-lose-opacity-1.html stacking-context-animation-ref.html
|
||||||
fails == stacking-context-lose-transform-none.html stacking-context-animation-ref.html
|
== stacking-context-lose-transform-none.html stacking-context-animation-ref.html
|
||||||
== stacking-context-opacity-win-in-delay.html stacking-context-animation-ref.html
|
== stacking-context-opacity-win-in-delay.html stacking-context-animation-ref.html
|
||||||
== stacking-context-opacity-win-in-delay-on-main-thread.html stacking-context-animation-ref.html
|
== stacking-context-opacity-win-in-delay-on-main-thread.html stacking-context-animation-ref.html
|
||||||
== stacking-context-opacity-wins-over-transition.html stacking-context-animation-ref.html
|
== stacking-context-opacity-wins-over-transition.html stacking-context-animation-ref.html
|
||||||
|
@ -33,10 +33,10 @@ fails == stacking-context-lose-transform-none.html stacking-context-animation-re
|
||||||
== stacking-context-transform-none-animation-with-preserve-3d.html stacking-context-animation-ref.html
|
== stacking-context-transform-none-animation-with-preserve-3d.html stacking-context-animation-ref.html
|
||||||
== stacking-context-transform-none-with-fill-backwards.html stacking-context-animation-ref.html
|
== stacking-context-transform-none-with-fill-backwards.html stacking-context-animation-ref.html
|
||||||
== stacking-context-transform-none-with-fill-forwards.html stacking-context-animation-ref.html
|
== stacking-context-transform-none-with-fill-forwards.html stacking-context-animation-ref.html
|
||||||
fails == stacking-context-opacity-1-in-delay.html stacking-context-animation-ref.html # bug 1278136 and bug 1279403
|
== stacking-context-opacity-1-in-delay.html stacking-context-animation-ref.html
|
||||||
fails == stacking-context-opacity-removing-important-in-delay.html stacking-context-animation-ref.html
|
== stacking-context-opacity-removing-important-in-delay.html stacking-context-animation-ref.html
|
||||||
fails == stacking-context-transform-none-in-delay.html stacking-context-animation-ref.html # bug 1278136 and bug 1279403
|
== stacking-context-transform-none-in-delay.html stacking-context-animation-ref.html
|
||||||
fails == stacking-context-transform-removing-important-in-delay.html stacking-context-animation-ref.html
|
== stacking-context-transform-removing-important-in-delay.html stacking-context-animation-ref.html
|
||||||
== background-position-in-delay.html background-position-ref.html
|
== background-position-in-delay.html background-position-ref.html
|
||||||
== background-position-after-finish.html background-position-ref.html
|
== background-position-after-finish.html background-position-ref.html
|
||||||
fails == background-position-running.html background-position-ref.html # This test fails the reftest-opaque-layer check since animating background-position currently creates an active layer, and reftest-opaque-layer only handles items assigned to PaintedLayers.
|
fails == background-position-running.html background-position-ref.html # This test fails the reftest-opaque-layer check since animating background-position currently creates an active layer, and reftest-opaque-layer only handles items assigned to PaintedLayers.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
== transitions-inline-already-wrapped-2.html transitions-inline-ref.html
|
== transitions-inline-already-wrapped-2.html transitions-inline-ref.html
|
||||||
== transitions-inline-rewrap-1.html transitions-inline-ref.html
|
== transitions-inline-rewrap-1.html transitions-inline-ref.html
|
||||||
== transitions-inline-rewrap-2.html transitions-inline-ref.html
|
== transitions-inline-rewrap-2.html transitions-inline-ref.html
|
||||||
fails == stacking-context-opacity-lose-to-animation.html stacking-context-transition-ref.html
|
== stacking-context-opacity-lose-to-animation.html stacking-context-transition-ref.html
|
||||||
fails == stacking-context-transform-lose-to-animation.html stacking-context-transition-ref.html
|
== stacking-context-transform-lose-to-animation.html stacking-context-transition-ref.html
|
||||||
== stacking-context-opacity-wins-over-important-style.html stacking-context-transition-ref.html
|
== stacking-context-opacity-wins-over-important-style.html stacking-context-transition-ref.html
|
||||||
== stacking-context-transform-wins-over-important-style.html stacking-context-transition-ref.html
|
== stacking-context-transform-wins-over-important-style.html stacking-context-transition-ref.html
|
||||||
|
|
Загрузка…
Ссылка в новой задаче