tree: split container tasks
This commit is contained in:
parent
16c402825f
commit
7d9ee6e696
2 changed files with 161 additions and 148 deletions
|
|
@ -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
157
src/tree/container/tasks.rs
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue