1
0
Fork 0
forked from wry/wry

tree: split container tasks

This commit is contained in:
kossLAN 2026-05-29 19:50:08 -04:00
parent 16c402825f
commit 7d9ee6e696
No known key found for this signature in database
2 changed files with 161 additions and 148 deletions

View file

@ -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<State>) {
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<State>) {
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<State>) {
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<Self>,
) -> (
Rc<crate::utils::asyncevent::AsyncEvent>,
Vec<Rc<RefCell<Option<TextTexture>>>>,
) {
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<RefCell<Option<TextTexture>>>]) {
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()

157
src/tree/container/tasks.rs Normal file
View file

@ -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<State>) {
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<State>) {
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<State>) {
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<Self>,
) -> (
Rc<crate::utils::asyncevent::AsyncEvent>,
Vec<Rc<RefCell<Option<TextTexture>>>>,
) {
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<RefCell<Option<TextTexture>>>]) {
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();
}
}