1mod constraint;
2mod node;
3
4use std::{any::TypeId, num::NonZero, sync::Arc, time::Instant};
5
6use parking_lot::RwLock;
7use rayon::prelude::*;
8use tracing::{debug, warn};
9
10use crate::{
11 Clipboard, ComputeResourceManager, Px, PxRect,
12 cursor::CursorEvent,
13 px::{PxPosition, PxSize},
14 renderer::Command,
15};
16
17pub use constraint::{Constraint, DimensionValue};
18pub use node::{
19 ComponentNode, ComponentNodeMetaData, ComponentNodeMetaDatas, ComponentNodeTree, ComputedData,
20 ImeRequest, InputHandlerFn, InputHandlerInput, MeasureFn, MeasureInput, MeasurementError,
21 WindowRequests, measure_node, measure_nodes, place_node,
22};
23
24pub struct ComputeParams<'a> {
26 pub screen_size: PxSize,
27 pub cursor_position: Option<PxPosition>,
28 pub cursor_events: Vec<CursorEvent>,
29 pub keyboard_events: Vec<winit::event::KeyEvent>,
30 pub ime_events: Vec<winit::event::Ime>,
31 pub modifiers: winit::keyboard::ModifiersState,
32 pub compute_resource_manager: Arc<RwLock<ComputeResourceManager>>,
33 pub gpu: &'a wgpu::Device,
34 pub clipboard: &'a mut Clipboard,
35}
36
37pub struct ComponentTree {
39 tree: indextree::Arena<ComponentNode>,
41 metadatas: ComponentNodeMetaDatas,
43 node_queue: Vec<indextree::NodeId>,
45}
46
47impl Default for ComponentTree {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl ComponentTree {
54 pub fn new() -> Self {
56 let tree = indextree::Arena::new();
57 let node_queue = Vec::new();
58 let metadatas = ComponentNodeMetaDatas::new();
59 Self {
60 tree,
61 node_queue,
62 metadatas,
63 }
64 }
65
66 pub fn clear(&mut self) {
68 self.tree.clear();
69 self.metadatas.clear();
70 self.node_queue.clear();
71 }
72
73 pub fn get(&self, node_id: indextree::NodeId) -> Option<&ComponentNode> {
75 self.tree.get(node_id).map(|n| n.get())
76 }
77
78 pub fn get_mut(&mut self, node_id: indextree::NodeId) -> Option<&mut ComponentNode> {
80 self.tree.get_mut(node_id).map(|n| n.get_mut())
81 }
82
83 pub fn current_node(&self) -> Option<&ComponentNode> {
85 self.node_queue
86 .last()
87 .and_then(|node_id| self.get(*node_id))
88 }
89
90 pub fn current_node_mut(&mut self) -> Option<&mut ComponentNode> {
92 let node_id = self.node_queue.last()?;
93 self.get_mut(*node_id)
94 }
95
96 pub fn add_node(&mut self, node_component: ComponentNode) {
100 let new_node_id = self.tree.new_node(node_component);
101 if let Some(current_node_id) = self.node_queue.last_mut() {
102 current_node_id.append(new_node_id, &mut self.tree);
103 }
104 let metadata = ComponentNodeMetaData::none();
105 self.metadatas.insert(new_node_id, metadata);
106 self.node_queue.push(new_node_id);
107 }
108
109 pub fn pop_node(&mut self) {
111 self.node_queue.pop();
112 }
113
114 pub(crate) fn tree(&self) -> &indextree::Arena<ComponentNode> {
118 &self.tree
119 }
120
121 pub(crate) fn metadatas(&self) -> &ComponentNodeMetaDatas {
125 &self.metadatas
126 }
127
128 #[tracing::instrument(level = "debug", skip(self, params))]
138 pub fn compute(
139 &mut self,
140 params: ComputeParams<'_>,
141 ) -> (Vec<(Command, TypeId, PxSize, PxPosition)>, WindowRequests) {
142 let ComputeParams {
143 screen_size,
144 mut cursor_position,
145 mut cursor_events,
146 mut keyboard_events,
147 mut ime_events,
148 modifiers,
149 compute_resource_manager,
150 gpu,
151 clipboard,
152 } = params;
153 let Some(root_node) = self.tree.get_node_id_at(NonZero::new(1).unwrap()) else {
154 return (vec![], WindowRequests::default());
155 };
156 let screen_constraint = Constraint::new(
157 DimensionValue::Fixed(screen_size.width),
158 DimensionValue::Fixed(screen_size.height),
159 );
160
161 let measure_timer = Instant::now();
162 debug!("Start measuring the component tree...");
163
164 match measure_node(
167 root_node,
168 &screen_constraint,
169 &self.tree,
170 &self.metadatas,
171 compute_resource_manager,
172 gpu,
173 ) {
174 Ok(_root_computed_data) => {
175 debug!("Component tree measured in {:?}", measure_timer.elapsed());
176 }
177 Err(e) => {
178 panic!(
179 "Root node ({root_node:?}) measurement failed: {e:?}. Aborting draw command computation."
180 );
181 }
182 }
183
184 let compute_draw_timer = Instant::now();
185 debug!("Start computing draw commands...");
186 let commands = compute_draw_commands_parallel(
189 root_node,
190 &self.tree,
191 &self.metadatas,
192 screen_size.width.0,
193 screen_size.height.0,
194 );
195 debug!(
196 "Draw commands computed in {:?}, total commands: {}",
197 compute_draw_timer.elapsed(),
198 commands.len()
199 );
200
201 let input_handler_timer = Instant::now();
202 let mut window_requests = WindowRequests::default();
203 debug!("Start executing input handlers...");
204
205 for node_id in root_node
206 .reverse_traverse(&self.tree)
207 .filter_map(|edge| match edge {
208 indextree::NodeEdge::Start(id) => Some(id),
209 indextree::NodeEdge::End(_) => None,
210 })
211 {
212 let Some(input_handler) = self
213 .tree
214 .get(node_id)
215 .and_then(|n| n.get().input_handler_fn.as_ref())
216 else {
217 continue;
218 };
219
220 let metadata = self.metadatas.get(&node_id).unwrap();
221 let abs_pos = metadata.abs_position.unwrap();
222 let event_clip_rect = metadata.event_clip_rect;
223 let node_computed_data = metadata.computed_data;
224 drop(metadata); let mut cursor_position_ref = &mut cursor_position;
227 let mut dummy_cursor_position = None;
228 let mut cursor_events_ref = &mut cursor_events;
229 let mut empty_dummy_cursor_events = Vec::new();
230 if let (Some(cursor_pos), Some(clip_rect)) = (*cursor_position_ref, event_clip_rect) {
231 if !clip_rect.contains(cursor_pos) {
233 cursor_position_ref = &mut dummy_cursor_position;
235 cursor_events_ref = &mut empty_dummy_cursor_events;
236 }
237 }
238 let current_cursor_position = cursor_position_ref.map(|pos| pos - abs_pos);
239
240 if let Some(node_computed_data) = node_computed_data {
241 let input = InputHandlerInput {
242 computed_data: node_computed_data,
243 cursor_position_rel: current_cursor_position,
244 cursor_position_abs: cursor_position_ref,
245 cursor_events: cursor_events_ref,
246 keyboard_events: &mut keyboard_events,
247 ime_events: &mut ime_events,
248 key_modifiers: modifiers,
249 requests: &mut window_requests,
250 clipboard,
251 current_node_id: node_id,
252 metadatas: &self.metadatas,
253 };
254 input_handler(input);
255 if let Some(ref mut ime_request) = window_requests.ime_request
257 && ime_request.position.is_none()
258 {
259 ime_request.position = Some(abs_pos);
260 }
261 } else {
262 warn!(
263 "Computed data not found for node {:?} during input handler execution.",
264 node_id
265 );
266 }
267 }
268
269 debug!(
270 "Input Handlers executed in {:?}",
271 input_handler_timer.elapsed()
272 );
273 (commands, window_requests)
274 }
275}
276
277#[tracing::instrument(level = "trace", skip(tree, metadatas))]
286fn compute_draw_commands_parallel(
287 node_id: indextree::NodeId,
288 tree: &ComponentNodeTree,
289 metadatas: &ComponentNodeMetaDatas,
290 screen_width: i32,
291 screen_height: i32,
292) -> Vec<(Command, TypeId, PxSize, PxPosition)> {
293 compute_draw_commands_inner_parallel(
294 PxPosition::ZERO,
295 true,
296 node_id,
297 tree,
298 metadatas,
299 screen_width,
300 screen_height,
301 None,
302 )
303}
304
305#[tracing::instrument(level = "trace", skip(tree, metadatas))]
306fn compute_draw_commands_inner_parallel(
307 start_pos: PxPosition,
308 is_root: bool,
309 node_id: indextree::NodeId,
310 tree: &ComponentNodeTree,
311 metadatas: &ComponentNodeMetaDatas,
312 screen_width: i32,
313 screen_height: i32,
314 clip_rect: Option<PxRect>,
315) -> Vec<(Command, TypeId, PxSize, PxPosition)> {
316 let mut local_commands = Vec::new();
317
318 let mut metadata = metadatas.get_mut(&node_id).unwrap();
320 let rel_pos = match metadata.rel_position {
321 Some(pos) => pos,
322 None if is_root => PxPosition::ZERO,
323 _ => return local_commands, };
325 let self_pos = start_pos + rel_pos;
326 metadata.abs_position = Some(self_pos);
327
328 let size = metadata
329 .computed_data
330 .map(|d| PxSize {
331 width: d.width,
332 height: d.height,
333 })
334 .unwrap_or_default();
335
336 let node_rect = PxRect {
337 x: self_pos.x,
338 y: self_pos.y,
339 width: size.width,
340 height: size.height,
341 };
342
343 let mut clip_rect = clip_rect;
344 if let Some(clip_rect) = clip_rect {
345 metadata.event_clip_rect = Some(clip_rect);
346 }
347
348 let clips_children = metadata.clips_children;
349 if clips_children {
351 let new_clip_rect = if let Some(existing_clip) = clip_rect {
352 existing_clip
353 .intersection(&node_rect)
354 .unwrap_or(PxRect::ZERO)
355 } else {
356 node_rect
357 };
358
359 clip_rect = Some(new_clip_rect);
360
361 local_commands.push((
362 Command::ClipPush(new_clip_rect),
363 TypeId::of::<Command>(),
364 size,
365 self_pos,
366 ));
367 }
368
369 let screen_rect = PxRect {
371 x: Px(0),
372 y: Px(0),
373 width: Px(screen_width),
374 height: Px(screen_height),
375 };
376
377 if size.width.0 > 0 && size.height.0 > 0 && !node_rect.is_orthogonal(&screen_rect) {
379 for (cmd, type_id) in metadata.commands.drain(..) {
380 local_commands.push((cmd, type_id, size, self_pos));
381 }
382 }
383
384 drop(metadata); let children: Vec<_> = node_id.children(tree).collect();
388 let child_results: Vec<Vec<_>> = children
389 .into_par_iter()
390 .map(|child| {
391 let parent_abs_pos = metadatas.get(&node_id).unwrap().abs_position.unwrap();
393 compute_draw_commands_inner_parallel(
394 parent_abs_pos, false,
396 child,
397 tree,
398 metadatas,
399 screen_width,
400 screen_height,
401 clip_rect,
402 )
403 })
404 .collect();
405
406 for child_cmds in child_results {
407 local_commands.extend(child_cmds);
408 }
409
410 if clips_children {
412 local_commands.push((Command::ClipPop, TypeId::of::<Command>(), size, self_pos));
413 }
414
415 local_commands
416}