diff options
| author | akbash <akbash@herdr.dev> | 2026-08-18 04:37:11 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-18 04:37:11 +0300 |
| commit | 2d24950ad9a02096921bc764e2e3dcd8900c3366 (patch) | |
| tree | b6884a29425922dfed083bb7108415ae56725a45 /src/app | |
| parent | d497ee14dd3f2b5325a16d0de779ed6bd62178ee (diff) | |
fix: isolate hidden pane render cadence (#2892)
refs #2890
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src/app')
| -rw-r--r-- | src/app/mod.rs | 6 | ||||
| -rw-r--r-- | src/app/runtime.rs | 30 |
2 files changed, 35 insertions, 1 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs index 2095b99e..501f39f6 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -149,7 +149,10 @@ pub struct App { /// Parsed `ui.window_title` plus the hostname resolved when it was applied. window_title_template: Option<(crate::config::WindowTitleTemplate, String)>, pub(crate) persist_pane_history: bool, + /// Last render-loop attempt, including a throttled hidden-only PTY skip. pub(crate) last_render_at: Option<Instant>, + /// Last attempt that could update a connected presentation surface. + pub(crate) last_presentation_at: Option<Instant>, pub(crate) input_leases: input::InputLeaseTable, pub render_notify: Arc<Notify>, pub(crate) render_dirty: Arc<crate::render_signal::RenderSignal>, @@ -783,6 +786,7 @@ impl App { selection_highlight_clear_deadline: None, persist_pane_history: config.experimental.pane_history, last_render_at: None, + last_presentation_at: None, input_leases: input::InputLeaseTable::default(), api_rx, event_hub, @@ -1133,7 +1137,7 @@ impl App { self.render_dirty.request_generic(); self.render_notify.notify_one(); } - self.last_render_at = Some(now); + self.record_render_attempt(now, true); needs_render = false; continue; } diff --git a/src/app/runtime.rs b/src/app/runtime.rs index d7023727..8367a223 100644 --- a/src/app/runtime.rs +++ b/src/app/runtime.rs @@ -534,6 +534,22 @@ impl App { } } + pub(crate) fn can_present_now(&self, now: Instant) -> bool { + match self.last_presentation_at { + Some(last_presentation_at) => { + now.duration_since(last_presentation_at) >= MIN_RENDER_INTERVAL + } + None => true, + } + } + + pub(crate) fn record_render_attempt(&mut self, now: Instant, presentation: bool) { + self.last_render_at = Some(now); + if presentation { + self.last_presentation_at = Some(now); + } + } + pub(crate) fn run_auto_update_check(&mut self) { if !background_update_check_enabled(self.no_session, self.update_version_check_enabled) { self.next_auto_update_check = None; @@ -658,6 +674,20 @@ mod tests { use crate::workspace::Workspace; #[test] + fn hidden_render_attempt_keeps_presentation_cadence_available() { + let (mut app, _) = test_app_with_pane(); + let initial_presentation = Instant::now(); + app.record_render_attempt(initial_presentation, true); + + let hidden_attempt = initial_presentation + MIN_RENDER_INTERVAL; + app.record_render_attempt(hidden_attempt, false); + let foreground_echo = hidden_attempt + Duration::from_millis(1); + + assert!(!app.can_render_now(foreground_echo)); + assert!(app.can_present_now(foreground_echo)); + } + + #[test] fn interrupted_detached_process_wait_keeps_child_for_retry() { let interrupted = std::io::Error::new(std::io::ErrorKind::Interrupted, "test interrupt"); |
