From fe0a21bdb9184c990521ce287cc00bdafe5d7919 Mon Sep 17 00:00:00 2001 From: zach Date: Wed, 3 Jun 2026 22:10:50 +0200 Subject: [PATCH] cleaned up debug code --- src/main.rs | 98 +++++++++++++++++++++++++++++++++++++++++++++++-- src/renderer.rs | 5 +++ 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 56a7808..0aafeea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -173,6 +173,15 @@ impl Pane { /// Calculate the current dim factor based on animation progress. /// Returns a value between `inactive_dim` (for unfocused) and 1.0 (for focused). + /// Check if the fade animation is still in progress for this pane. + pub fn is_fade_in_progress(&self, fade_duration_ms: u64, was_focused: bool) -> bool { + if fade_duration_ms == 0 { + return false; + } + let elapsed = self.focus_animation_start.elapsed().as_millis() as f32; + elapsed < fade_duration_ms as f32 + } + fn calculate_dim_factor( &mut self, is_focused: bool, @@ -1353,6 +1362,8 @@ struct App { last_render_at: std::time::Instant, /// Whether a fatal render error occurred (e.g., OutOfMemory). render_fatal_error: bool, + /// Whether UI state changed and a full redraw is needed (tab switch, pane focus, etc.). + needs_redraw: bool, } impl App { @@ -1395,6 +1406,7 @@ impl App { last_stats_log: std::time::Instant::now(), last_render_at: std::time::Instant::now(), render_fatal_error: false, + needs_redraw: false, } } @@ -1949,7 +1961,18 @@ impl App { .unwrap_or(false) }); - if !has_dirty_content && self.edge_glows.is_empty() { + // Check if any pane fade animation is in progress + let fade_in_progress = geometries.iter().any(|(pane_id, _)| { + tab.panes + .get(pane_id) + .map(|p| { + let is_active = *pane_id == active_pane_id; + p.is_fade_in_progress(fade_duration_ms, is_active) + }) + .unwrap_or(false) + }); + + if !has_dirty_content && !self.needs_redraw && self.edge_glows.is_empty() && !fade_in_progress { let image_animation_in_progress = tab.panes.values().any(|p| { p.terminal.image_storage.has_animations() }); @@ -2102,8 +2125,22 @@ impl App { pane.terminal.clear_dirty_lines(); } } + // Only clear needs_redraw if no pane fade is still in progress + let any_fade_in_progress = geometries.iter().any(|(pane_id, _)| { + tab.panes + .get(pane_id) + .map(|p| { + let is_active = *pane_id == active_pane_id; + p.is_fade_in_progress(fade_duration_ms, is_active) + }) + .unwrap_or(false) + }); + if !any_fade_in_progress { + self.needs_redraw = false; + } } Err(wgpu::SurfaceError::Lost) => { + log::info!("RENDER LOST: resizing"); renderer.resize(renderer.width, renderer.height); } Err(wgpu::SurfaceError::OutOfMemory) => { @@ -2391,6 +2428,7 @@ impl App { self.start_pane_io_thread_with_info(pane_id, pty_fd, shared_parser); // Recalculate layout self.resize_all_panes(); + self.needs_redraw = true; self.request_redraw(); log::info!( "Split pane (horizontal={}), new pane {}", @@ -2445,6 +2483,10 @@ impl App { false }; + if navigated { + self.needs_redraw = true; + } + if !navigated { // No neighbor in that direction - trigger edge glow animation // Use renderer's helper to calculate proper screen-space glow bounds @@ -2486,19 +2528,30 @@ impl App { if !self.tabs.is_empty() && self.active_tab >= self.tabs.len() { self.active_tab = self.tabs.len() - 1; } + self.needs_redraw = true; + // Force full redraw for the new active tab's content + if let Some(renderer) = &mut self.renderer { + renderer.force_full_redraw(); + } } else { // Recalculate layout after removing pane self.resize_all_panes(); } + self.needs_redraw = true; self.request_redraw(); } fn switch_to_tab(&mut self, idx: usize) { if idx < self.tabs.len() { self.active_tab = idx; + self.needs_redraw = true; // Update grid dimensions for proper centering of the new active tab self.update_active_tab_grid_dimensions(); + // Force full GPU buffer rebuild for the new tab's terminal content + if let Some(renderer) = &mut self.renderer { + renderer.force_full_redraw(); + } self.request_redraw(); } } @@ -2856,7 +2909,23 @@ impl ApplicationHandler for App { const REPAINT_DELAY: Duration = Duration::from_millis(6); let time_since_last_render = self.last_render_at.elapsed(); - let should_render = any_input + // Check if anything actually needs rendering + let any_dirty = self.tabs.iter().any(|tab| { + tab.panes.values().any(|pane| { + let dl = &pane.terminal.dirty_lines; + dl[0] != 0 || dl[1] != 0 || dl[2] != 0 || dl[3] != 0 + }) + }); + let any_animations = self.tabs.iter().any(|tab| { + tab.panes.values().any(|pane| pane.terminal.image_storage.has_animations()) + }); + let need_render = any_dirty + || self.needs_redraw + || !self.edge_glows.is_empty() + || any_animations; + + let should_render = need_render + && any_input && any_not_synchronized && time_since_last_render >= REPAINT_DELAY && self.renderer.is_some(); @@ -2871,7 +2940,8 @@ impl ApplicationHandler for App { if needs_another_frame { self.request_redraw(); } - } else if any_input + } else if need_render + && any_input && any_not_synchronized && self.renderer.is_some() { @@ -3189,6 +3259,24 @@ impl ApplicationHandler for App { self.last_frame_log = std::time::Instant::now(); } + // Skip rendering if nothing needs it (prevents render loop on Wayland) + let any_dirty = self.tabs.iter().any(|tab| { + tab.panes.values().any(|pane| { + let dl = &pane.terminal.dirty_lines; + dl[0] != 0 || dl[1] != 0 || dl[2] != 0 || dl[3] != 0 + }) + }); + let need_render = any_dirty + || self.needs_redraw + || !self.edge_glows.is_empty() + || self.tabs.iter().any(|tab| { + tab.panes.values().any(|pane| pane.terminal.image_storage.has_animations()) + }); + + if !need_render { + return; + } + // Use shared render logic let needs_another_frame = self.do_render(); @@ -3260,6 +3348,10 @@ impl ApplicationHandler for App { // Update grid dimensions if tabs were removed if tabs_removed && !self.tabs.is_empty() { + self.needs_redraw = true; + if let Some(renderer) = &mut self.renderer { + renderer.force_full_redraw(); + } self.update_active_tab_grid_dimensions(); } diff --git a/src/renderer.rs b/src/renderer.rs index 314fb25..e445d50 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -2141,6 +2141,11 @@ impl Renderer { self.pane_resources.retain(|id, _| active_pane_ids.contains(id)); } + /// Force a full GPU cell buffer rebuild on the next call to update_gpu_cells. + pub fn force_full_redraw(&mut self) { + self.cells_dirty = true; + } + /// Update GPU cell buffer from terminal content. /// Like Kitty, this only processes dirty lines to minimize work. ///