From 15cf28815e7b3778af48d122bd368b0f627fe275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 20 Oct 2022 14:30:25 +0000 Subject: [PATCH] style: Invalidate viewport units on container-queries properly By re-selector-matching the element (thus re-evaluating the container query condition). Depends on D159852 Differential Revision: https://phabricator.services.mozilla.com/D159853 --- components/style/data.rs | 39 ++++++++++++------- .../style/invalidation/viewport_units.rs | 17 ++++++-- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/components/style/data.rs b/components/style/data.rs index 2fa0b39c24d..c546f0828f3 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -162,6 +162,19 @@ pub struct ElementStyles { // There's one of these per rendered elements so it better be small. size_of_test!(ElementStyles, 16); +/// Information on how this element uses viewport units. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum ViewportUnitUsage { + /// No viewport units are used. + None = 0, + /// There are viewport units used from regular style rules (which means we + /// should re-cascade). + FromDeclaration, + /// There are viewport units used from container queries (which means we + /// need to re-selector-match). + FromQuery, +} + impl ElementStyles { /// Returns the primary style. pub fn get_primary(&self) -> Option<&Arc> { @@ -179,29 +192,27 @@ impl ElementStyles { } /// Whether this element uses viewport units. - pub fn uses_viewport_units(&self) -> bool { + pub fn viewport_unit_usage(&self) -> ViewportUnitUsage { use crate::computed_value_flags::ComputedValueFlags; - if self - .primary() - .flags - .intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) - { - return true; + fn usage_from_flags(flags: ComputedValueFlags) -> ViewportUnitUsage { + if flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS_ON_CONTAINER_QUERIES) { + return ViewportUnitUsage::FromQuery; + } + if flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) { + return ViewportUnitUsage::FromDeclaration; + } + ViewportUnitUsage::None } + let mut usage = usage_from_flags(self.primary().flags); for pseudo_style in self.pseudos.as_array() { if let Some(ref pseudo_style) = pseudo_style { - if pseudo_style - .flags - .intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) - { - return true; - } + usage = std::cmp::max(usage, usage_from_flags(pseudo_style.flags)); } } - false + usage } #[cfg(feature = "gecko")] diff --git a/components/style/invalidation/viewport_units.rs b/components/style/invalidation/viewport_units.rs index acf8b095f9f..75a3aad24ba 100644 --- a/components/style/invalidation/viewport_units.rs +++ b/components/style/invalidation/viewport_units.rs @@ -4,6 +4,7 @@ //! Invalidates style of all elements that depend on viewport units. +use crate::data::ViewportUnitUsage; use crate::dom::{TElement, TNode}; use crate::invalidation::element::restyle_hints::RestyleHint; @@ -32,10 +33,20 @@ where return false; } - let uses_viewport_units = data.styles.uses_viewport_units(); + let usage = data.styles.viewport_unit_usage(); + let uses_viewport_units = usage != ViewportUnitUsage::None; if uses_viewport_units { - debug!("invalidate_recursively: {:?} uses viewport units", element); - data.hint.insert(RestyleHint::RECASCADE_SELF); + debug!("invalidate_recursively: {:?} uses viewport units {:?}", element, usage); + } + + match usage { + ViewportUnitUsage::None => {}, + ViewportUnitUsage::FromQuery => { + data.hint.insert(RestyleHint::RESTYLE_SELF); + }, + ViewportUnitUsage::FromDeclaration => { + data.hint.insert(RestyleHint::RECASCADE_SELF); + } } let mut any_children_invalid = false;