From 7d9ee6e69614a08363b9faac992fde03725fe541 Mon Sep 17 00:00:00 2001 From: kossLAN Date: Fri, 29 May 2026 19:50:08 -0400 Subject: [PATCH] tree: split container tasks --- src/tree/container.rs | 152 +--------------------------------- src/tree/container/tasks.rs | 157 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 148 deletions(-) create mode 100644 src/tree/container/tasks.rs diff --git a/src/tree/container.rs b/src/tree/container.rs index b8de7b25..72d6eef7 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1,3 +1,7 @@ +mod tasks; + +pub use tasks::{container_layout, container_render_positions, container_tab_render_textures}; + use { crate::{ backend::ButtonState, @@ -11,9 +15,7 @@ use { }, rect::Rect, renderer::Renderer, - scale::Scale, state::State, - text::TextTexture, tree::{ ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, OutputNode, TddType, TileDragDestination, @@ -25,12 +27,10 @@ use { }, utils::{ clonecell::CloneCell, - errorfmt::ErrorFmt, event_listener::LazyEventSource, hash_map_ext::HashMapExt, linkedlist::{LinkedList, LinkedNode, NodeRef}, numcell::NumCell, - on_drop_event::OnDropEvent, rc_eq::rc_eq, threshold_counter::ThresholdCounter, }, @@ -1769,150 +1769,6 @@ enum SeatOpKind { Resize { dist_left: i32, dist_right: i32 }, } -pub async fn container_layout(state: Rc) { - loop { - let first = state.pending_container_layout.pop().await; - let mut containers = vec![first]; - while let Some(container) = state.pending_container_layout.try_pop() { - containers.push(container); - } - let mut animated = vec![]; - let mut immediate = vec![]; - for container in containers { - if !container.layout_scheduled.get() { - continue; - } - let animate = container.animate_next_layout.replace(false) - && !state.suppress_animations_for_next_layout.get(); - if animate { - animated.push(container); - } else { - immediate.push(container); - } - } - if !animated.is_empty() { - let prev_active = state.layout_animations_active.replace(true); - state.begin_layout_animation_batch(); - for container in animated { - container.perform_layout(); - } - state.finish_layout_animation_batch(); - state.layout_animations_active.set(prev_active); - } - if !immediate.is_empty() { - let prev_active = state.layout_animations_active.replace(false); - for container in immediate { - container.perform_layout(); - } - state.layout_animations_active.set(prev_active); - } - state.suppress_animations_for_next_layout.set(false); - } -} - -pub async fn container_render_positions(state: Rc) { - loop { - let container = state.pending_container_render_positions.pop().await; - if container.compute_render_positions_scheduled.get() { - container.compute_render_positions(); - } - } -} - -pub async fn container_tab_render_textures(state: Rc) { - loop { - let container = state.pending_container_tab_render_textures.pop().await; - container.update_tab_textures_scheduled.set(false); - let (event, textures) = container.update_tab_textures_phase1(); - event.triggered().await; - container.update_tab_textures_phase2(&textures); - } -} - -impl ContainerNode { - fn update_tab_textures_phase1( - self: &Rc, - ) -> ( - Rc, - Vec>>>, - ) { - let on_completed = Rc::new(OnDropEvent::default()); - let (entries, bar_height, render_scale) = { - let tab_bar = self.tab_bar.borrow(); - let Some(tb) = tab_bar.as_ref() else { - return (on_completed.event(), vec![]); - }; - let entries: Vec<_> = tb - .entries - .iter() - .map(|e| { - ( - e.title.clone(), - TabBar::entry_colors(&self.state, e), - e.title_texture.clone(), - e.width.get(), - ) - }) - .collect(); - (entries, tb.height, tb.render_scale) - }; - let Some(ctx) = self.state.render_ctx.get() else { - log::warn!("tab text phase1: no render context"); - return (on_completed.event(), vec![]); - }; - let font = self.state.theme.title_font(); - let scale = if render_scale != Scale::from_int(1) { - Some(render_scale.to_f64()) - } else { - None - }; - let mut texture_height = bar_height; - if let Some(s) = scale { - texture_height = (bar_height as f64 * s).round() as _; - } - let mut texture_refs = Vec::new(); - let text_padding = self.state.theme.sizes.tab_bar_text_padding.get(); - let border_width = self.state.theme.sizes.tab_bar_border_width.get(); - for (title, (_, _, text_color), title_texture, tab_width) in &entries { - let max_width = (*tab_width - 2 * (text_padding + border_width)).max(0); - let max_width = if let Some(s) = scale { - (max_width as f64 * s).round() as i32 - } else { - max_width - }; - if max_width <= 0 { - continue; - } - let mut tex_ref = title_texture.borrow_mut(); - let tex = tex_ref.get_or_insert_with(|| TextTexture::new(&self.state, &ctx)); - tex.schedule_render_fitting_or_ellipsized( - on_completed.clone(), - Some(texture_height), - max_width, - &font, - title, - *text_color, - false, - scale, - ); - texture_refs.push(title_texture.clone()); - } - (on_completed.event(), texture_refs) - } - - fn update_tab_textures_phase2(&self, textures: &[Rc>>]) { - for title_texture in textures { - let tex_ref = title_texture.borrow(); - if let Some(tex) = tex_ref.as_ref() { - if let Err(e) = tex.flip() { - log::warn!("Could not render tab text: {}", ErrorFmt(e)); - } - } - } - self.damage(); - } -} - impl Node for ContainerNode { fn node_id(&self) -> NodeId { self.id.into() diff --git a/src/tree/container/tasks.rs b/src/tree/container/tasks.rs new file mode 100644 index 00000000..4c90413e --- /dev/null +++ b/src/tree/container/tasks.rs @@ -0,0 +1,157 @@ +use { + crate::{ + scale::Scale, + state::State, + text::TextTexture, + tree::tab_bar::TabBar, + utils::{errorfmt::ErrorFmt, on_drop_event::OnDropEvent}, + }, + std::{cell::RefCell, rc::Rc}, +}; + +use super::ContainerNode; + +pub async fn container_layout(state: Rc) { + loop { + let first = state.pending_container_layout.pop().await; + let mut containers = vec![first]; + while let Some(container) = state.pending_container_layout.try_pop() { + containers.push(container); + } + let mut animated = vec![]; + let mut immediate = vec![]; + for container in containers { + if !container.layout_scheduled.get() { + continue; + } + let animate = container.animate_next_layout.replace(false) + && !state.suppress_animations_for_next_layout.get(); + if animate { + animated.push(container); + } else { + immediate.push(container); + } + } + if !animated.is_empty() { + let prev_active = state.layout_animations_active.replace(true); + state.begin_layout_animation_batch(); + for container in animated { + container.perform_layout(); + } + state.finish_layout_animation_batch(); + state.layout_animations_active.set(prev_active); + } + if !immediate.is_empty() { + let prev_active = state.layout_animations_active.replace(false); + for container in immediate { + container.perform_layout(); + } + state.layout_animations_active.set(prev_active); + } + state.suppress_animations_for_next_layout.set(false); + } +} + +pub async fn container_render_positions(state: Rc) { + loop { + let container = state.pending_container_render_positions.pop().await; + if container.compute_render_positions_scheduled.get() { + container.compute_render_positions(); + } + } +} + +pub async fn container_tab_render_textures(state: Rc) { + loop { + let container = state.pending_container_tab_render_textures.pop().await; + container.update_tab_textures_scheduled.set(false); + let (event, textures) = container.update_tab_textures_phase1(); + event.triggered().await; + container.update_tab_textures_phase2(&textures); + } +} + +impl ContainerNode { + fn update_tab_textures_phase1( + self: &Rc, + ) -> ( + Rc, + Vec>>>, + ) { + let on_completed = Rc::new(OnDropEvent::default()); + let (entries, bar_height, render_scale) = { + let tab_bar = self.tab_bar.borrow(); + let Some(tb) = tab_bar.as_ref() else { + return (on_completed.event(), vec![]); + }; + let entries: Vec<_> = tb + .entries + .iter() + .map(|e| { + ( + e.title.clone(), + TabBar::entry_colors(&self.state, e), + e.title_texture.clone(), + e.width.get(), + ) + }) + .collect(); + (entries, tb.height, tb.render_scale) + }; + let Some(ctx) = self.state.render_ctx.get() else { + log::warn!("tab text phase1: no render context"); + return (on_completed.event(), vec![]); + }; + let font = self.state.theme.title_font(); + let scale = if render_scale != Scale::from_int(1) { + Some(render_scale.to_f64()) + } else { + None + }; + let mut texture_height = bar_height; + if let Some(s) = scale { + texture_height = (bar_height as f64 * s).round() as _; + } + let mut texture_refs = Vec::new(); + let text_padding = self.state.theme.sizes.tab_bar_text_padding.get(); + let border_width = self.state.theme.sizes.tab_bar_border_width.get(); + for (title, (_, _, text_color), title_texture, tab_width) in &entries { + let max_width = (*tab_width - 2 * (text_padding + border_width)).max(0); + let max_width = if let Some(s) = scale { + (max_width as f64 * s).round() as i32 + } else { + max_width + }; + if max_width <= 0 { + continue; + } + let mut tex_ref = title_texture.borrow_mut(); + let tex = tex_ref.get_or_insert_with(|| TextTexture::new(&self.state, &ctx)); + tex.schedule_render_fitting_or_ellipsized( + on_completed.clone(), + Some(texture_height), + max_width, + &font, + title, + *text_color, + false, + scale, + ); + texture_refs.push(title_texture.clone()); + } + (on_completed.event(), texture_refs) + } + + fn update_tab_textures_phase2(&self, textures: &[Rc>>]) { + for title_texture in textures { + let tex_ref = title_texture.borrow(); + if let Some(tex) = tex_ref.as_ref() { + if let Err(e) = tex.flip() { + log::warn!("Could not render tab text: {}", ErrorFmt(e)); + } + } + } + self.damage(); + } +} +