From 2218b17dc056c5846ef6e094d60634485b85c8f4 Mon Sep 17 00:00:00 2001 From: Felipe Coury Date: Sat, 6 Jun 2026 19:15:01 -0300 Subject: [PATCH] fix(tui): avoid resume input leaks --- codex-rs/tui/src/tui.rs | 4 ++-- codex-rs/tui/src/tui/job_control.rs | 23 +++++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/codex-rs/tui/src/tui.rs b/codex-rs/tui/src/tui.rs index ed3a214193..99ba3cfbeb 100644 --- a/codex-rs/tui/src/tui.rs +++ b/codex-rs/tui/src/tui.rs @@ -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()?; diff --git a/codex-rs/tui/src/tui/job_control.rs b/codex-rs/tui/src/tui/job_control.rs index 11f52b1287..1669615ccc 100644 --- a/codex-rs/tui/src/tui/job_control.rs +++ b/codex-rs/tui/src/tui/job_control.rs @@ -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, ) -> Option { 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(()) }