aboutsummaryrefslogtreecommitdiff
path: root/src/render_signal.rs
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-08-18 04:37:11 +0300
committerGitHub <noreply@github.com>2026-08-18 04:37:11 +0300
commit2d24950ad9a02096921bc764e2e3dcd8900c3366 (patch)
treeb6884a29425922dfed083bb7108415ae56725a45 /src/render_signal.rs
parentd497ee14dd3f2b5325a16d0de779ed6bd62178ee (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.rs52
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);