aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2025-04-18 13:10:35 +0200
committerMartin Robinson <mrobinson@igalia.com>2025-04-18 15:38:16 +0200
commit78847cd64a6633ee9ef9646524cf5a1fce1aa041 (patch)
treef9d9aa79932e178c49d2f0b72d05424817965233
parenta16e7639608b45972521395191a2725ad9a10b1d (diff)
downloadservo-78847cd64a6633ee9ef9646524cf5a1fce1aa041.tar.gz
servo-78847cd64a6633ee9ef9646524cf5a1fce1aa041.zip
layout: Add a new `FragmentTree` pass to calculate containing block rectangles
When doing any kind of query, up until now, containing block rectangles were calculated by walking the `FragmentTree` until the node being queried was found. In order to make possible answering queries without walking the `FragmentTree`, `Fragment`s need to cache their cumulative containing block rectangles. This change adds a new `FragmentTree` pass (during construction) that takes care of calculating and caching these values. The new cached value is used during resolved style queries and also scrolling area queries (with the idea that all queries will eventually use them). In addition, extra `FragmentTree` walks used for cancelling animations for elements no longer in the `FragmentTree` are integrated into this new traversal. Co-authored-by: Oriol Brufau <obrufau@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
-rw-r--r--components/layout_2020/flow/root.rs11
-rw-r--r--components/layout_2020/fragment_tree/box_fragment.rs25
-rw-r--r--components/layout_2020/fragment_tree/fragment.rs31
-rw-r--r--components/layout_2020/fragment_tree/fragment_tree.rs77
-rw-r--r--components/layout_2020/query.rs190
-rw-r--r--components/layout_thread_2020/lib.rs68
-rw-r--r--components/script/dom/window.rs5
-rw-r--r--components/shared/script_layout/lib.rs2
8 files changed, 204 insertions, 205 deletions
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index f02703f58d2..0b50a8c809b 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -426,13 +426,14 @@ impl BoxTree {
acc.union(&child_overflow)
});
- FragmentTree {
+ FragmentTree::new(
+ layout_context,
root_fragments,
scrollable_overflow,
- initial_containing_block: physical_containing_block,
- canvas_background: self.canvas_background.clone(),
- viewport_scroll_sensitivity: self.viewport_scroll_sensitivity,
- }
+ physical_containing_block,
+ self.canvas_background.clone(),
+ self.viewport_scroll_sensitivity,
+ )
}
}
diff --git a/components/layout_2020/fragment_tree/box_fragment.rs b/components/layout_2020/fragment_tree/box_fragment.rs
index d0c96b3ea03..32e8ae72464 100644
--- a/components/layout_2020/fragment_tree/box_fragment.rs
+++ b/components/layout_2020/fragment_tree/box_fragment.rs
@@ -59,6 +59,10 @@ pub(crate) struct BoxFragment {
/// does not include padding, border, or margin -- it only includes content.
pub content_rect: PhysicalRect<Au>,
+ /// This [`BoxFragment`]'s containing block rectangle in coordinates relative to
+ /// the initial containing block, but not taking into account any transforms.
+ pub cumulative_containing_block_rect: PhysicalRect<Au>,
+
pub padding: PhysicalSides<Au>,
pub border: PhysicalSides<Au>,
pub margin: PhysicalSides<Au>,
@@ -114,6 +118,7 @@ impl BoxFragment {
style,
children,
content_rect,
+ cumulative_containing_block_rect: Default::default(),
padding,
border,
margin,
@@ -189,6 +194,8 @@ impl BoxFragment {
self
}
+ /// Get the scrollable overflow for this [`BoxFragment`] relative to its
+ /// containing block.
pub fn scrollable_overflow(&self) -> PhysicalRect<Au> {
let physical_padding_rect = self.padding_rect();
let content_origin = self.content_rect.origin.to_vector();
@@ -199,6 +206,10 @@ impl BoxFragment {
)
}
+ pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> {
+ rect.translate(self.cumulative_containing_block_rect.origin.to_vector())
+ }
+
pub(crate) fn padding_rect(&self) -> PhysicalRect<Au> {
self.content_rect.outer_rect(self.padding)
}
@@ -272,10 +283,7 @@ impl BoxFragment {
overflow
}
- pub(crate) fn calculate_resolved_insets_if_positioned(
- &self,
- containing_block: &PhysicalRect<Au>,
- ) -> PhysicalSides<AuOrAuto> {
+ pub(crate) fn calculate_resolved_insets_if_positioned(&self) -> PhysicalSides<AuOrAuto> {
let position = self.style.get_box().position;
debug_assert_ne!(
position,
@@ -303,7 +311,10 @@ impl BoxFragment {
// used value. Otherwise the resolved value is the computed value."
// https://drafts.csswg.org/cssom/#resolved-values
let insets = self.style.physical_box_offsets();
- let (cb_width, cb_height) = (containing_block.width(), containing_block.height());
+ let (cb_width, cb_height) = (
+ self.cumulative_containing_block_rect.width(),
+ self.cumulative_containing_block_rect.height(),
+ );
if position == ComputedPosition::Relative {
let get_resolved_axis = |start: &LengthPercentageOrAuto,
end: &LengthPercentageOrAuto,
@@ -388,4 +399,8 @@ impl BoxFragment {
_ => CollapsedBlockMargins::zero(),
}
}
+
+ pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
+ self.cumulative_containing_block_rect = *containing_block;
+ }
}
diff --git a/components/layout_2020/fragment_tree/fragment.rs b/components/layout_2020/fragment_tree/fragment.rs
index f8ba80369ed..f86b026ff24 100644
--- a/components/layout_2020/fragment_tree/fragment.rs
+++ b/components/layout_2020/fragment_tree/fragment.rs
@@ -103,6 +103,7 @@ impl Fragment {
Fragment::Float(fragment) => fragment.borrow().base.clone(),
})
}
+
pub(crate) fn mutate_content_rect(&mut self, callback: impl FnOnce(&mut PhysicalRect<Au>)) {
match self {
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
@@ -115,6 +116,26 @@ impl Fragment {
}
}
+ pub(crate) fn set_containing_block(&self, containing_block: &PhysicalRect<Au>) {
+ match self {
+ Fragment::Box(box_fragment) => box_fragment
+ .borrow_mut()
+ .set_containing_block(containing_block),
+ Fragment::Float(float_fragment) => float_fragment
+ .borrow_mut()
+ .set_containing_block(containing_block),
+ Fragment::Positioning(_) => {},
+ Fragment::AbsoluteOrFixedPositioned(hoisted_shared_fragment) => {
+ if let Some(ref fragment) = hoisted_shared_fragment.borrow().fragment {
+ fragment.set_containing_block(containing_block);
+ }
+ },
+ Fragment::Text(_) => {},
+ Fragment::Image(_) => {},
+ Fragment::IFrame(_) => {},
+ }
+ }
+
pub fn tag(&self) -> Option<Tag> {
self.base().and_then(|base| base.tag)
}
@@ -137,12 +158,12 @@ impl Fragment {
}
}
- pub fn scrolling_area(&self, containing_block: &PhysicalRect<Au>) -> PhysicalRect<Au> {
+ pub fn scrolling_area(&self) -> PhysicalRect<Au> {
match self {
- Fragment::Box(fragment) | Fragment::Float(fragment) => fragment
- .borrow()
- .scrollable_overflow()
- .translate(containing_block.origin.to_vector()),
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ let fragment = fragment.borrow();
+ fragment.offset_by_containing_block(&fragment.scrollable_overflow())
+ },
_ => self.scrollable_overflow(),
}
}
diff --git a/components/layout_2020/fragment_tree/fragment_tree.rs b/components/layout_2020/fragment_tree/fragment_tree.rs
index 32542ccd155..51e4e66bd60 100644
--- a/components/layout_2020/fragment_tree/fragment_tree.rs
+++ b/components/layout_2020/fragment_tree/fragment_tree.rs
@@ -12,6 +12,7 @@ use style::dom::OpaqueNode;
use webrender_api::units;
use super::{ContainingBlockManager, Fragment, Tag};
+use crate::context::LayoutContext;
use crate::display_list::StackingContext;
use crate::flow::CanvasBackground;
use crate::geom::{PhysicalPoint, PhysicalRect};
@@ -42,6 +43,58 @@ pub struct FragmentTree {
}
impl FragmentTree {
+ pub(crate) fn new(
+ layout_context: &LayoutContext,
+ root_fragments: Vec<Fragment>,
+ scrollable_overflow: PhysicalRect<Au>,
+ initial_containing_block: PhysicalRect<Au>,
+ canvas_background: CanvasBackground,
+ viewport_scroll_sensitivity: AxesScrollSensitivity,
+ ) -> Self {
+ let fragment_tree = Self {
+ root_fragments,
+ scrollable_overflow,
+ initial_containing_block,
+ canvas_background,
+ viewport_scroll_sensitivity,
+ };
+
+ // As part of building the fragment tree, we want to stop animating elements and
+ // pseudo-elements that used to be animating or had animating images attached to
+ // them. Create a set of all elements that used to be animating.
+ let mut animations = layout_context.style_context.animations.sets.write();
+ let mut invalid_animating_nodes: FxHashSet<_> = animations.keys().cloned().collect();
+ let mut image_animations = layout_context.node_image_animation_map.write().to_owned();
+ let mut invalid_image_animating_nodes: FxHashSet<_> = image_animations
+ .keys()
+ .cloned()
+ .map(|node| AnimationSetKey::new(node, None))
+ .collect();
+
+ fragment_tree.find(|fragment, _level, containing_block| {
+ if let Some(tag) = fragment.tag() {
+ invalid_animating_nodes.remove(&AnimationSetKey::new(tag.node, tag.pseudo));
+ invalid_image_animating_nodes.remove(&AnimationSetKey::new(tag.node, tag.pseudo));
+ }
+
+ fragment.set_containing_block(containing_block);
+ None::<()>
+ });
+
+ // Cancel animations for any elements and pseudo-elements that are no longer found
+ // in the fragment tree.
+ for node in &invalid_animating_nodes {
+ if let Some(state) = animations.get_mut(node) {
+ state.cancel_all_animations();
+ }
+ }
+ for node in &invalid_image_animating_nodes {
+ image_animations.remove(&node.node);
+ }
+
+ fragment_tree
+ }
+
pub(crate) fn build_display_list(
&self,
builder: &mut crate::display_list::DisplayListBuilder,
@@ -84,14 +137,6 @@ impl FragmentTree {
.find_map(|child| child.find(&info, 0, &mut process_func))
}
- pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<AnimationSetKey>) {
- self.find(|fragment, _, _| {
- let tag = fragment.tag()?;
- set.remove(&AnimationSetKey::new(tag.node, tag.pseudo));
- None::<()>
- });
- }
-
/// Get the vector of rectangles that surrounds the fragments of the node with the given address.
/// This function answers the `getClientRects()` query and the union of the rectangles answers
/// the `getBoundingClientRect()` query.
@@ -171,22 +216,8 @@ impl FragmentTree {
pub fn get_scrolling_area_for_viewport(&self) -> PhysicalRect<Au> {
let mut scroll_area = self.initial_containing_block;
for fragment in self.root_fragments.iter() {
- scroll_area = fragment
- .scrolling_area(&self.initial_containing_block)
- .union(&scroll_area);
+ scroll_area = fragment.scrolling_area().union(&scroll_area);
}
scroll_area
}
-
- pub fn get_scrolling_area_for_node(&self, requested_node: OpaqueNode) -> PhysicalRect<Au> {
- let tag_to_find = Tag::new(requested_node);
- let scroll_area = self.find(|fragment, _, containing_block| {
- if fragment.tag() == Some(tag_to_find) {
- Some(fragment.scrolling_area(containing_block))
- } else {
- None
- }
- });
- scroll_area.unwrap_or_else(PhysicalRect::<Au>::zero)
- }
}
diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs
index 08b264deea9..3409f7c1923 100644
--- a/components/layout_2020/query.rs
+++ b/components/layout_2020/query.rs
@@ -83,14 +83,21 @@ pub fn process_node_geometry_request(
}
/// <https://drafts.csswg.org/cssom-view/#scrolling-area>
-pub fn process_node_scroll_area_request(
- requested_node: Option<OpaqueNode>,
+pub fn process_node_scroll_area_request<'dom>(
+ requested_node: Option<impl LayoutNode<'dom> + 'dom>,
fragment_tree: Option<Arc<FragmentTree>>,
) -> Rect<i32> {
- let rect = match (fragment_tree, requested_node) {
- (Some(tree), Some(node)) => tree.get_scrolling_area_for_node(node),
- (Some(tree), None) => tree.get_scrolling_area_for_viewport(),
- _ => return Rect::zero(),
+ let Some(tree) = fragment_tree else {
+ return Rect::zero();
+ };
+
+ let rect = match requested_node {
+ Some(node) => node
+ .fragments_for_pseudo(None)
+ .first()
+ .map(Fragment::scrolling_area)
+ .unwrap_or_default(),
+ None => tree.get_scrolling_area_for_viewport(),
};
Rect::new(
@@ -109,7 +116,6 @@ pub fn process_resolved_style_request<'dom>(
node: impl LayoutNode<'dom> + 'dom,
pseudo: &Option<PseudoElement>,
property: &PropertyId,
- fragment_tree: Option<Arc<FragmentTree>>,
) -> String {
if !node.as_element().unwrap().has_data() {
return process_resolved_style_request_for_unstyled_node(context, node, pseudo, property);
@@ -161,8 +167,6 @@ pub fn process_resolved_style_request<'dom>(
_ => style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id)),
};
- let tag_to_find = Tag::new_pseudo(node.opaque(), *pseudo);
-
// https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle
// Here we are trying to conform to the specification that says that getComputedStyle
// should return the used values in certain circumstances. For size and positional
@@ -191,107 +195,87 @@ pub fn process_resolved_style_request<'dom>(
return computed_style(None);
}
- let resolve_for_fragment =
- |fragment: &Fragment, containing_block: Option<&PhysicalRect<Au>>| {
- let (content_rect, margins, padding, specific_layout_info) = match fragment {
- Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
- let box_fragment = box_fragment.borrow();
- if style.get_box().position != Position::Static {
- let resolved_insets = || {
- box_fragment
- .calculate_resolved_insets_if_positioned(containing_block.unwrap())
- };
- match longhand_id {
- LonghandId::Top => return resolved_insets().top.to_css_string(),
- LonghandId::Right => {
- return resolved_insets().right.to_css_string();
- },
- LonghandId::Bottom => {
- return resolved_insets().bottom.to_css_string();
- },
- LonghandId::Left => {
- return resolved_insets().left.to_css_string();
- },
- _ => {},
- }
- }
- let content_rect = box_fragment.content_rect;
- let margins = box_fragment.margin;
- let padding = box_fragment.padding;
- let specific_layout_info = box_fragment.specific_layout_info.clone();
- (content_rect, margins, padding, specific_layout_info)
- },
- Fragment::Positioning(positioning_fragment) => {
- let content_rect = positioning_fragment.borrow().rect;
- (
- content_rect,
- SideOffsets2D::zero(),
- SideOffsets2D::zero(),
- None,
- )
- },
- _ => return computed_style(Some(fragment)),
- };
-
- // https://drafts.csswg.org/css-grid/#resolved-track-list
- // > The grid-template-rows and grid-template-columns properties are
- // > resolved value special case properties.
- //
- // > When an element generates a grid container box...
- if display.inside() == DisplayInside::Grid {
- if let Some(SpecificLayoutInfo::Grid(info)) = specific_layout_info {
- if let Some(value) = resolve_grid_template(&info, style, longhand_id) {
- return value;
+ let resolve_for_fragment = |fragment: &Fragment| {
+ let (content_rect, margins, padding, specific_layout_info) = match fragment {
+ Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
+ let box_fragment = box_fragment.borrow();
+ if style.get_box().position != Position::Static {
+ let resolved_insets = || box_fragment.calculate_resolved_insets_if_positioned();
+ match longhand_id {
+ LonghandId::Top => return resolved_insets().top.to_css_string(),
+ LonghandId::Right => {
+ return resolved_insets().right.to_css_string();
+ },
+ LonghandId::Bottom => {
+ return resolved_insets().bottom.to_css_string();
+ },
+ LonghandId::Left => {
+ return resolved_insets().left.to_css_string();
+ },
+ _ => {},
}
}
- }
+ let content_rect = box_fragment.content_rect;
+ let margins = box_fragment.margin;
+ let padding = box_fragment.padding;
+ let specific_layout_info = box_fragment.specific_layout_info.clone();
+ (content_rect, margins, padding, specific_layout_info)
+ },
+ Fragment::Positioning(positioning_fragment) => {
+ let content_rect = positioning_fragment.borrow().rect;
+ (
+ content_rect,
+ SideOffsets2D::zero(),
+ SideOffsets2D::zero(),
+ None,
+ )
+ },
+ _ => return computed_style(Some(fragment)),
+ };
- // https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height
- // > If the property applies to the element or pseudo-element and the resolved value of the
- // > display property is not none or contents, then the resolved value is the used value.
- // > Otherwise the resolved value is the computed value.
- //
- // However, all browsers ignore that for margin and padding properties, and resolve to a length
- // even if the property doesn't apply: https://github.com/w3c/csswg-drafts/issues/10391
- match longhand_id {
- LonghandId::Width if resolved_size_should_be_used_value(fragment) => {
- content_rect.size.width
- },
- LonghandId::Height if resolved_size_should_be_used_value(fragment) => {
- content_rect.size.height
- },
- LonghandId::MarginBottom => margins.bottom,
- LonghandId::MarginTop => margins.top,
- LonghandId::MarginLeft => margins.left,
- LonghandId::MarginRight => margins.right,
- LonghandId::PaddingBottom => padding.bottom,
- LonghandId::PaddingTop => padding.top,
- LonghandId::PaddingLeft => padding.left,
- LonghandId::PaddingRight => padding.right,
- _ => return computed_style(Some(fragment)),
+ // https://drafts.csswg.org/css-grid/#resolved-track-list
+ // > The grid-template-rows and grid-template-columns properties are
+ // > resolved value special case properties.
+ //
+ // > When an element generates a grid container box...
+ if display.inside() == DisplayInside::Grid {
+ if let Some(SpecificLayoutInfo::Grid(info)) = specific_layout_info {
+ if let Some(value) = resolve_grid_template(&info, style, longhand_id) {
+ return value;
+ }
}
- .to_css_string()
- };
+ }
- if !matches!(
- longhand_id,
- LonghandId::Top | LonghandId::Bottom | LonghandId::Left | LonghandId::Right
- ) {
- if let Some(fragment) = node.fragments_for_pseudo(*pseudo).first() {
- return resolve_for_fragment(fragment, None);
+ // https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height
+ // > If the property applies to the element or pseudo-element and the resolved value of the
+ // > display property is not none or contents, then the resolved value is the used value.
+ // > Otherwise the resolved value is the computed value.
+ //
+ // However, all browsers ignore that for margin and padding properties, and resolve to a length
+ // even if the property doesn't apply: https://github.com/w3c/csswg-drafts/issues/10391
+ match longhand_id {
+ LonghandId::Width if resolved_size_should_be_used_value(fragment) => {
+ content_rect.size.width
+ },
+ LonghandId::Height if resolved_size_should_be_used_value(fragment) => {
+ content_rect.size.height
+ },
+ LonghandId::MarginBottom => margins.bottom,
+ LonghandId::MarginTop => margins.top,
+ LonghandId::MarginLeft => margins.left,
+ LonghandId::MarginRight => margins.right,
+ LonghandId::PaddingBottom => padding.bottom,
+ LonghandId::PaddingTop => padding.top,
+ LonghandId::PaddingLeft => padding.left,
+ LonghandId::PaddingRight => padding.right,
+ _ => return computed_style(Some(fragment)),
}
- }
+ .to_css_string()
+ };
- fragment_tree
- .and_then(|fragment_tree| {
- fragment_tree.find(|fragment, _, containing_block| {
- if Some(tag_to_find) == fragment.tag() {
- Some(resolve_for_fragment(fragment, Some(containing_block)))
- } else {
- None
- }
- })
- })
+ node.fragments_for_pseudo(*pseudo)
+ .first()
+ .map(resolve_for_fragment)
.unwrap_or_else(|| computed_style(None))
}
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 86db80bf999..59d047e70cd 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -26,7 +26,7 @@ use euclid::{Point2D, Scale, Size2D, Vector2D};
use fnv::FnvHashMap;
use fonts::{FontContext, FontContextWebFontMethods};
use fonts_traits::StylesheetWebFontLoadFinishedCallback;
-use fxhash::{FxHashMap, FxHashSet};
+use fxhash::FxHashMap;
use ipc_channel::ipc::IpcSender;
use layout::context::LayoutContext;
use layout::display_list::{DisplayList, WebRenderImageInfo};
@@ -49,15 +49,15 @@ use profile_traits::{path, time_profile};
use rayon::ThreadPool;
use script::layout_dom::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode};
use script_layout_interface::{
- ImageAnimationState, Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType,
- OffsetParentResponse, ReflowGoal, ReflowRequest, ReflowResult, TrustedNodeAddress,
+ Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType, OffsetParentResponse, ReflowGoal,
+ ReflowRequest, ReflowResult, TrustedNodeAddress,
};
use script_traits::{DrawAPaintImageResult, PaintWorkletError, Painter, ScriptThreadMessage};
use servo_arc::Arc as ServoArc;
use servo_config::opts::{self, DebugOptions};
use servo_config::pref;
use servo_url::ServoUrl;
-use style::animation::{AnimationSetKey, DocumentAnimationSet};
+use style::animation::DocumentAnimationSet;
use style::context::{
QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext,
};
@@ -328,14 +328,7 @@ impl Layout for LayoutThread {
TraversalFlags::empty(),
);
- let fragment_tree = self.fragment_tree.borrow().clone();
- process_resolved_style_request(
- &shared_style_context,
- node,
- &pseudo,
- &property_id,
- fragment_tree,
- )
+ process_resolved_style_request(&shared_style_context, node, &pseudo, &property_id)
}
#[cfg_attr(
@@ -378,7 +371,8 @@ impl Layout for LayoutThread {
feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
)]
- fn query_scrolling_area(&self, node: Option<OpaqueNode>) -> UntypedRect<i32> {
+ fn query_scrolling_area(&self, node: Option<TrustedNodeAddress>) -> UntypedRect<i32> {
+ let node = node.map(|node| unsafe { ServoLayoutNode::new(&node) });
process_node_scroll_area_request(node, self.fragment_tree.borrow().clone())
}
@@ -767,18 +761,6 @@ impl LayoutThread {
run_layout()
});
- Self::cancel_animations_for_nodes_not_in_fragment_tree(
- &recalc_style_traversal.context().style_context.animations,
- &fragment_tree,
- );
- Self::cancel_image_animation_for_nodes_not_in_fragment_tree(
- recalc_style_traversal
- .context()
- .node_image_animation_map
- .clone(),
- &fragment_tree,
- );
-
*self.fragment_tree.borrow_mut() = Some(fragment_tree);
if self.debug.dump_style_tree {
@@ -899,42 +881,6 @@ impl LayoutThread {
})
}
- /// Cancel animations for any nodes which have been removed from fragment tree.
- /// TODO(mrobinson): We should look into a way of doing this during flow tree construction.
- /// This also doesn't yet handles nodes that have been reparented.
- fn cancel_animations_for_nodes_not_in_fragment_tree(
- animations: &DocumentAnimationSet,
- root: &FragmentTree,
- ) {
- // Assume all nodes have been removed until proven otherwise.
- let mut animations = animations.sets.write();
- let mut invalid_nodes = animations.keys().cloned().collect();
- root.remove_nodes_in_fragment_tree_from_set(&mut invalid_nodes);
-
- // Cancel animations for any nodes that are no longer in the fragment tree.
- for node in &invalid_nodes {
- if let Some(state) = animations.get_mut(node) {
- state.cancel_all_animations();
- }
- }
- }
-
- fn cancel_image_animation_for_nodes_not_in_fragment_tree(
- image_animation_set: Arc<RwLock<FxHashMap<OpaqueNode, ImageAnimationState>>>,
- root: &FragmentTree,
- ) {
- let mut image_animations = image_animation_set.write().to_owned();
- let mut invalid_nodes: FxHashSet<AnimationSetKey> = image_animations
- .keys()
- .cloned()
- .map(|node| AnimationSetKey::new(node, None))
- .collect();
- root.remove_nodes_in_fragment_tree_from_set(&mut invalid_nodes);
- for node in &invalid_nodes {
- image_animations.remove(&node.node);
- }
- }
-
fn viewport_did_change(&mut self, viewport_details: ViewportDetails) -> bool {
let new_pixel_ratio = viewport_details.hidpi_scale_factor.get();
let new_viewport_size = Size2D::new(
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index ce3b5ff6e8c..6ba22591641 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -2282,11 +2282,12 @@ impl Window {
node: Option<&Node>,
can_gc: CanGc,
) -> UntypedRect<i32> {
- let opaque = node.map(|node| node.to_opaque());
if !self.layout_reflow(QueryMsg::ScrollingAreaQuery, can_gc) {
return Rect::zero();
}
- self.layout.borrow().query_scrolling_area(opaque)
+ self.layout
+ .borrow()
+ .query_scrolling_area(node.map(Node::to_trusted_node_address))
}
pub(crate) fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32, LayoutPixel> {
diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs
index 9b052642c32..69e577e139d 100644
--- a/components/shared/script_layout/lib.rs
+++ b/components/shared/script_layout/lib.rs
@@ -265,7 +265,7 @@ pub trait Layout {
animations: DocumentAnimationSet,
animation_timeline_value: f64,
) -> Option<ServoArc<Font>>;
- fn query_scrolling_area(&self, node: Option<OpaqueNode>) -> Rect<i32>;
+ fn query_scrolling_area(&self, node: Option<TrustedNodeAddress>) -> Rect<i32>;
fn query_text_indext(&self, node: OpaqueNode, point: Point2D<f32>) -> Option<usize>;
}