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
This commit is contained in:
Emilio Cobos Álvarez 2022-10-20 14:30:25 +00:00 committed by Martin Robinson
parent b8c0a898ad
commit 15cf28815e
2 changed files with 39 additions and 17 deletions

View file

@ -162,6 +162,19 @@ pub struct ElementStyles {
// There's one of these per rendered elements so it better be small. // There's one of these per rendered elements so it better be small.
size_of_test!(ElementStyles, 16); 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 { impl ElementStyles {
/// Returns the primary style. /// Returns the primary style.
pub fn get_primary(&self) -> Option<&Arc<ComputedValues>> { pub fn get_primary(&self) -> Option<&Arc<ComputedValues>> {
@ -179,29 +192,27 @@ impl ElementStyles {
} }
/// Whether this element uses viewport units. /// 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; use crate::computed_value_flags::ComputedValueFlags;
if self fn usage_from_flags(flags: ComputedValueFlags) -> ViewportUnitUsage {
.primary() if flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS_ON_CONTAINER_QUERIES) {
.flags return ViewportUnitUsage::FromQuery;
.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) }
{ if flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) {
return true; return ViewportUnitUsage::FromDeclaration;
}
ViewportUnitUsage::None
} }
let mut usage = usage_from_flags(self.primary().flags);
for pseudo_style in self.pseudos.as_array() { for pseudo_style in self.pseudos.as_array() {
if let Some(ref pseudo_style) = pseudo_style { if let Some(ref pseudo_style) = pseudo_style {
if pseudo_style usage = std::cmp::max(usage, usage_from_flags(pseudo_style.flags));
.flags
.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS)
{
return true;
}
} }
} }
false usage
} }
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]

View file

@ -4,6 +4,7 @@
//! Invalidates style of all elements that depend on viewport units. //! Invalidates style of all elements that depend on viewport units.
use crate::data::ViewportUnitUsage;
use crate::dom::{TElement, TNode}; use crate::dom::{TElement, TNode};
use crate::invalidation::element::restyle_hints::RestyleHint; use crate::invalidation::element::restyle_hints::RestyleHint;
@ -32,10 +33,20 @@ where
return false; 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 { if uses_viewport_units {
debug!("invalidate_recursively: {:?} uses viewport units", element); debug!("invalidate_recursively: {:?} uses viewport units {:?}", element, usage);
data.hint.insert(RestyleHint::RECASCADE_SELF); }
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; let mut any_children_invalid = false;