diff --git a/components/style/context.rs b/components/style/context.rs index b173aad03eb..337afd65ceb 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -419,6 +419,11 @@ bitflags! { const EFFECT_PROPERTIES = structs::UpdateAnimationsTasks_EffectProperties; /// Update animation cacade results for animations running on the compositor. const CASCADE_RESULTS = structs::UpdateAnimationsTasks_CascadeResults; + /// Display property was changed from none. + /// Script animations keep alive on display:none elements, so we need to trigger + /// the second animation restyles for the script animations in the case where + /// the display property was changed from 'none' to others. + const DISPLAY_CHANGED_FROM_NONE = structs::UpdateAnimationsTasks_DisplayChangedFromNone; } } diff --git a/components/style/gecko/generated/structs.rs b/components/style/gecko/generated/structs.rs index 6187943584f..38e0d1f9d1b 100644 --- a/components/style/gecko/generated/structs.rs +++ b/components/style/gecko/generated/structs.rs @@ -5642,6 +5642,7 @@ pub mod root { pub const UpdateAnimationsTasks_CSSTransitions: root::mozilla::UpdateAnimationsTasks = 2; pub const UpdateAnimationsTasks_EffectProperties: root::mozilla::UpdateAnimationsTasks = 4; pub const UpdateAnimationsTasks_CascadeResults: root::mozilla::UpdateAnimationsTasks = 8; + pub const UpdateAnimationsTasks_DisplayChangedFromNone: root::mozilla::UpdateAnimationsTasks = 16; pub type UpdateAnimationsTasks = u8; pub const ParsingMode_Default: root::mozilla::ParsingMode = 0; pub const ParsingMode_AllowUnitlessLength: root::mozilla::ParsingMode = 1; diff --git a/components/style/matching.rs b/components/style/matching.rs index 89b60c9905a..594717cc52a 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -176,14 +176,7 @@ trait PrivateMatchMethods: TElement { return; } - let display_changed_from_none = old_values.map_or(false, |old| { - let old_display_style = old.get_box().clone_display(); - let new_display_style = new_values.get_box().clone_display(); - old_display_style == Display::None && - new_display_style != Display::None - }); - - if display_changed_from_none { + if new_values.is_display_property_changed_from_none(old_values) { // When display value is changed from none to other, we need to // traverse descendant elements in a subsequent normal // traversal (we can't traverse them in this animation-only restyle @@ -266,6 +259,9 @@ trait PrivateMatchMethods: TElement { if important_rules_changed { tasks.insert(UpdateAnimationsTasks::CASCADE_RESULTS); } + if new_values.is_display_property_changed_from_none(old_values.as_ref().map(|s| &**s)) { + tasks.insert(UpdateAnimationsTasks::DISPLAY_CHANGED_FROM_NONE); + } } if !tasks.is_empty() { diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 11b8ac5210a..aea141323ce 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -144,6 +144,22 @@ impl ComputedValues { return our_type == CSSPseudoElementType_InheritingAnonBox || our_type == CSSPseudoElementType::NonInheritingAnonBox; } + + /// Returns true if the display property is changed from 'none' to others. + pub fn is_display_property_changed_from_none( + &self, + old_values: Option<<&ComputedValues> + ) -> bool { + use properties::longhands::display::computed_value::T as Display; + + old_values.map_or(false, |old| { + let old_display_style = old.get_box().clone_display(); + let new_display_style = self.get_box().clone_display(); + old_display_style == Display::None && + new_display_style != Display::None + }) + } + } impl Drop for ComputedValues {