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/render_signal.rs | |
| 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/render_signal.rs')
| -rw-r--r-- | src/render_signal.rs | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/src/render_signal.rs b/src/render_signal.rs index 2f6d9cb8..f4b4391d 100644 --- a/src/render_signal.rs +++ b/src/render_signal.rs @@ -37,14 +37,41 @@ impl RenderSignal { self.pending.store(true, Ordering::Release); } - /// Returns true when this request transitions the signal from idle to pending. + /// Returns true when the signal becomes pending or a new PTY source joins it. + /// + /// A new source may be visible even when the existing pending sources are + /// hidden, so the consumer must re-evaluate the coalesced request. pub(crate) fn request_pty(&self, pane_id: PaneId) -> bool { let mut request = self .request .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - request.pty_sources.insert(pane_id); - !self.pending.swap(true, Ordering::AcqRel) + let source_added = request.pty_sources.insert(pane_id); + let became_pending = !self.pending.swap(true, Ordering::AcqRel); + became_pending || source_added + } + + pub(crate) fn has_generic_or_terminal_title(&self) -> bool { + let request = self + .request + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner); + request.generic || !request.terminal_title_sources.is_empty() + } + + /// Checks pending PTY origins without allocating a source snapshot. + /// Keep the predicate narrow because producers share this lock. + pub(crate) fn has_pty_source_matching( + &self, + mut predicate: impl FnMut(PaneId) -> bool, + ) -> bool { + self.request + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner) + .pty_sources + .iter() + .copied() + .any(&mut predicate) } /// Coalesces terminal-title changes separately from ordinary PTY damage so @@ -54,8 +81,9 @@ impl RenderSignal { .request .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - request.terminal_title_sources.insert(pane_id); - !self.pending.swap(true, Ordering::AcqRel) + let source_added = request.terminal_title_sources.insert(pane_id); + let became_pending = !self.pending.swap(true, Ordering::AcqRel); + became_pending || source_added } pub(crate) fn pending_terminal_title_sources(&self) -> HashSet<PaneId> { @@ -88,7 +116,7 @@ mod tests { assert!(signal.request_pty(first)); assert!(!signal.request_pty(first)); - assert!(!signal.request_pty(second)); + assert!(signal.request_pty(second)); let request = signal.take(); assert!(!request.generic); @@ -98,6 +126,16 @@ mod tests { } #[test] + fn terminal_title_source_wakes_pending_pty_work() { + let signal = RenderSignal::new(); + let pane_id = PaneId::from_raw(10); + + assert!(signal.request_pty(pane_id)); + assert!(signal.request_terminal_title(pane_id)); + assert!(!signal.request_terminal_title(pane_id)); + } + + #[test] fn coalesces_terminal_title_sources_without_making_them_pty_damage() { let signal = RenderSignal::new(); let pane_id = PaneId::from_raw(10); @@ -120,7 +158,7 @@ mod tests { let pane_id = PaneId::from_raw(10); signal.request_generic(); - assert!(!signal.request_pty(pane_id)); + assert!(signal.request_pty(pane_id)); let request = signal.take(); assert!(request.generic); |
