fix(tui): avoid resume input leaks

This commit is contained in:
Felipe Coury
2026-06-06 19:15:01 -03:00
parent c51e4fb052
commit 2218b17dc0
2 changed files with 15 additions and 12 deletions
+2 -2
View File
@@ -882,7 +882,7 @@ impl Tui {
#[cfg(unix)]
let mut prepared_resume = self
.suspend_context
.prepare_resume_action(&mut self.terminal, &mut self.alt_saved_viewport);
.prepare_resume_action(&mut self.alt_saved_viewport);
// Precompute any viewport updates that need a cursor-position query before entering
// the synchronized update, to avoid racing with the event reader.
@@ -1018,7 +1018,7 @@ impl Tui {
#[cfg(unix)]
let mut prepared_resume = self
.suspend_context
.prepare_resume_action(&mut self.terminal, &mut self.alt_saved_viewport);
.prepare_resume_action(&mut self.alt_saved_viewport);
ensure_virtual_terminal_processing()?;
+13 -10
View File
@@ -13,7 +13,6 @@ use crossterm::event::KeyCode;
use crossterm::terminal::EnterAlternateScreen;
use crossterm::terminal::LeaveAlternateScreen;
use ratatui::crossterm::execute;
use ratatui::layout::Position;
use ratatui::layout::Rect;
use crate::key_hint;
@@ -81,23 +80,22 @@ impl SuspendContext {
/// resumes; returns `None` when there was no pending suspend intent.
pub(crate) fn prepare_resume_action(
&self,
terminal: &mut Terminal,
alt_saved_viewport: &mut Option<Rect>,
) -> Option<PreparedResumeAction> {
let action = self.take_resume_action()?;
match action {
ResumeAction::RealignInline => {
let cursor_pos = terminal
.get_cursor_position()
.unwrap_or(terminal.last_known_cursor_pos);
let viewport = Rect::new(0, cursor_pos.y, 0, 0);
let viewport = Rect::new(
/*x*/ 0,
self.cursor_y(),
/*width*/ 0,
/*height*/ 0,
);
Some(PreparedResumeAction::RealignViewport(viewport))
}
ResumeAction::RestoreAlt => {
if let Ok(Position { y, .. }) = terminal.get_cursor_position()
&& let Some(saved) = alt_saved_viewport.as_mut()
{
saved.y = y;
if let Some(saved) = alt_saved_viewport.as_mut() {
saved.y = self.cursor_y();
}
Some(PreparedResumeAction::RestoreAltScreen)
}
@@ -112,6 +110,10 @@ impl SuspendContext {
self.suspend_cursor_y.store(value, Ordering::Relaxed);
}
fn cursor_y(&self) -> u16 {
self.suspend_cursor_y.load(Ordering::Relaxed)
}
/// Record a pending resume action to apply after SIGTSTP returns control.
fn set_resume_action(&self, value: ResumeAction) {
*self
@@ -182,5 +184,6 @@ fn suspend_process() -> Result<()> {
// After the process resumes, reapply terminal modes so drawing can continue.
super::terminal_stderr::resume()?;
super::set_modes()?;
super::flush_terminal_input_buffer();
Ok(())
}