layout/fragment_tree/
fragment_tree.rs1use std::cell::Cell;
6
7use app_units::Au;
8use base::print_tree::PrintTree;
9use compositing_traits::display_list::AxesScrollSensitivity;
10use malloc_size_of_derive::MallocSizeOf;
11use rustc_hash::FxHashSet;
12use style::animation::AnimationSetKey;
13use style::computed_values::position::T as Position;
14
15use super::{BoxFragment, ContainingBlockManager, Fragment};
16use crate::ArcRefCell;
17use crate::context::LayoutContext;
18use crate::geom::PhysicalRect;
19
20#[derive(MallocSizeOf)]
21pub struct FragmentTree {
22 pub(crate) root_fragments: Vec<Fragment>,
31
32 scrollable_overflow: Cell<Option<PhysicalRect<Au>>>,
35
36 pub(crate) initial_containing_block: PhysicalRect<Au>,
38
39 pub viewport_scroll_sensitivity: AxesScrollSensitivity,
41}
42
43impl FragmentTree {
44 pub(crate) fn new(
45 layout_context: &LayoutContext,
46 root_fragments: Vec<Fragment>,
47 initial_containing_block: PhysicalRect<Au>,
48 viewport_scroll_sensitivity: AxesScrollSensitivity,
49 ) -> Self {
50 let fragment_tree = Self {
51 root_fragments,
52 scrollable_overflow: Cell::default(),
53 initial_containing_block,
54 viewport_scroll_sensitivity,
55 };
56
57 let mut animations = layout_context.style_context.animations.sets.write();
61 let mut invalid_animating_nodes: FxHashSet<_> = animations.keys().cloned().collect();
62
63 let mut animating_images = layout_context.image_resolver.animating_images.write();
64 let mut invalid_image_animating_nodes: FxHashSet<_> = animating_images
65 .node_to_state_map
66 .keys()
67 .cloned()
68 .map(|node| AnimationSetKey::new(node, None))
69 .collect();
70
71 fragment_tree.find(|fragment, _level, containing_block| {
72 if let Some(tag) = fragment.tag() {
73 invalid_animating_nodes.remove(&AnimationSetKey::new(
75 tag.node,
76 tag.pseudo_element_chain.primary,
77 ));
78 invalid_image_animating_nodes.remove(&AnimationSetKey::new(
79 tag.node,
80 tag.pseudo_element_chain.primary,
81 ));
82 }
83
84 fragment.set_containing_block(containing_block);
85 None::<()>
86 });
87
88 for node in &invalid_animating_nodes {
91 if let Some(state) = animations.get_mut(node) {
92 state.cancel_all_animations();
93 }
94 }
95 for node in &invalid_image_animating_nodes {
96 animating_images.remove(node.node);
97 }
98
99 fragment_tree
100 }
101
102 pub fn print(&self) {
103 let mut print_tree = PrintTree::new("Fragment Tree".to_string());
104 for fragment in &self.root_fragments {
105 fragment.print(&mut print_tree);
106 }
107 }
108
109 pub(crate) fn scrollable_overflow(&self) -> PhysicalRect<Au> {
110 self.scrollable_overflow
111 .get()
112 .expect("Should only call `scrollable_overflow()` after calculating overflow")
113 }
114
115 pub(crate) fn calculate_scrollable_overflow(&self) {
118 let scrollable_overflow = || {
119 let Some(first_root_fragment) = self.root_fragments.first() else {
120 return self.initial_containing_block;
121 };
122
123 let scrollable_overflow = self.root_fragments.iter().fold(
124 self.initial_containing_block,
125 |overflow, fragment| {
126 let overflow_from_fragment =
129 fragment.calculate_scrollable_overflow_for_parent();
130
131 if fragment
137 .retrieve_box_fragment()
138 .is_some_and(|box_fragment| {
139 box_fragment.borrow().style.get_box().position == Position::Fixed
140 })
141 {
142 return overflow;
143 }
144
145 overflow.union(&overflow_from_fragment)
146 },
147 );
148
149 let first_root_fragment = match first_root_fragment {
154 Fragment::Box(fragment) | Fragment::Float(fragment) => fragment.borrow(),
155 _ => return scrollable_overflow,
156 };
157 if !first_root_fragment.is_root_element() {
158 return scrollable_overflow;
159 }
160 first_root_fragment.clip_wholly_unreachable_scrollable_overflow(
161 scrollable_overflow,
162 self.initial_containing_block,
163 )
164 };
165
166 self.scrollable_overflow.set(Some(scrollable_overflow()))
167 }
168
169 pub(crate) fn find<T>(
170 &self,
171 mut process_func: impl FnMut(&Fragment, usize, &PhysicalRect<Au>) -> Option<T>,
172 ) -> Option<T> {
173 let info = ContainingBlockManager {
174 for_non_absolute_descendants: &self.initial_containing_block,
175 for_absolute_descendants: None,
176 for_absolute_and_fixed_descendants: &self.initial_containing_block,
177 };
178 self.root_fragments
179 .iter()
180 .find_map(|child| child.find(&info, 0, &mut process_func))
181 }
182
183 pub(crate) fn body_fragment(&self) -> Option<ArcRefCell<BoxFragment>> {
185 fn find_body(children: &[Fragment]) -> Option<ArcRefCell<BoxFragment>> {
186 children.iter().find_map(|fragment| {
187 match fragment {
188 Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
189 let borrowed_box_fragment = box_fragment.borrow();
190 if borrowed_box_fragment.is_body_element_of_html_element_root() {
191 return Some(box_fragment.clone());
192 }
193
194 if borrowed_box_fragment.is_root_element() ||
201 borrowed_box_fragment.base.is_anonymous()
202 {
203 find_body(&borrowed_box_fragment.children)
204 } else {
205 None
206 }
207 },
208 Fragment::Positioning(positioning_context)
209 if positioning_context.borrow().base.is_anonymous() =>
210 {
211 find_body(&positioning_context.borrow().children)
215 },
216 _ => None,
217 }
218 })
219 }
220
221 find_body(&self.root_fragments)
222 }
223}