@@ -74,8 +74,6 @@ pub struct InlineApp {
7474 // === Scrollback Rendering ===
7575 /// Track scrollback line count per task for incremental rendering
7676 task_scrollback_lines : HashMap < String , usize > ,
77- /// Track last rendered scrollback lines per task for buffered rendering
78- task_last_rendered_scrollback : HashMap < String , usize > ,
7977 /// Counter for buffering scrollback renders (render every 20th iteration)
8078 scrollback_render_counter : u32 ,
8179 /// Total lines inserted above TUI (for cleanup on exit)
@@ -126,7 +124,7 @@ impl InlineApp {
126124 countdown_popup : CountdownPopup :: new ( ) ,
127125 is_interactive : false ,
128126 task_scrollback_lines : HashMap :: new ( ) ,
129- task_last_rendered_scrollback : HashMap :: new ( ) ,
127+
130128 scrollback_render_counter : 0 ,
131129 total_inserted_lines : 0 ,
132130 status_message : None ,
@@ -156,7 +154,7 @@ impl InlineApp {
156154 // Reset all scrollback tracking when mode switching
157155 // PTYs will be resized in init(), which changes scrollback calculations
158156 task_scrollback_lines : HashMap :: new ( ) ,
159- task_last_rendered_scrollback : HashMap :: new ( ) ,
157+
160158 // Start at 19 so the first render (increment to 20) will trigger scrollback rendering
161159 // This ensures existing PTY content from full-screen mode is immediately displayed
162160 scrollback_render_counter : 19 ,
@@ -239,11 +237,10 @@ impl InlineApp {
239237 rows
240238 ) ;
241239
242- // Clone the PTY instance, resize it, and replace the Arc
243- let mut pty_clone = pty_arc. as_ref ( ) . clone ( ) ;
244- if pty_clone. resize ( rows, cols) . is_ok ( ) {
245- state. register_pty_instance ( task_id. to_string ( ) , Arc :: new ( pty_clone) ) ;
246- }
240+ // Async resize moves the expensive reparse off the event loop.
241+ // Scrollback rendering is skipped until the resize completes
242+ // (detected via is_resize_pending).
243+ pty_arc. resize_async ( rows, cols) ;
247244 }
248245
249246 Some ( ( ) )
@@ -615,8 +612,6 @@ impl TuiApp for InlineApp {
615612 fn on_pty_registered ( & mut self , task_id : & str ) {
616613 // Initialize scrollback tracking for inline mode
617614 self . task_scrollback_lines . insert ( task_id. to_string ( ) , 0 ) ;
618- self . task_last_rendered_scrollback
619- . insert ( task_id. to_string ( ) , 0 ) ;
620615 }
621616
622617 /// Override to resize interactive PTYs to inline dimensions
@@ -758,31 +753,22 @@ impl InlineApp {
758753 let pty = pty. clone ( ) ;
759754 drop ( state) ;
760755
761- // Get last rendered scrollback line count for this task
762- let last_rendered_lines = self
763- . task_last_rendered_scrollback
764- . get ( current_task)
765- . copied ( )
766- . unwrap_or ( 0 ) ;
756+ const MAX_LINES_PER_RENDER : usize = 250 ;
767757
768- // Get buffered scrollback content since last render
769- let buffered_scrollback_lines =
770- pty . get_buffered_scrollback_content_for_inline ( last_rendered_lines ) ;
771-
772- // Update tracking for next buffered render
773- let current_scrollback_lines = pty. get_scrollback_line_count ( ) ;
758+ // Get buffered scrollback content produced by the background thread.
759+ // The background thread tracks its own cursor into the scrollback
760+ // region and appends new lines to pending_lines. We drain up to
761+ // MAX_LINES_PER_RENDER per frame — the rest stay in pending_lines.
762+ let ( buffered_scrollback_lines , current_scrollback_lines ) =
763+ pty. get_buffered_scrollback_content_for_inline ( MAX_LINES_PER_RENDER ) ;
774764
775765 self . task_scrollback_lines
776766 . insert ( current_task. clone ( ) , current_scrollback_lines) ;
777767
778768 // Render buffered scrollback above TUI using terminal.insert_before
779- // Render in batches to avoid overwhelming the terminal
780769 if !buffered_scrollback_lines. is_empty ( ) {
781- const MAX_LINES_PER_RENDER : usize = 250 ;
782-
783- // Calculate how many lines to render this cycle
784- let lines_to_render = buffered_scrollback_lines. len ( ) . min ( MAX_LINES_PER_RENDER ) ;
785- let batch = & buffered_scrollback_lines[ 0 ..lines_to_render] ;
770+ let lines_to_render = buffered_scrollback_lines. len ( ) ;
771+ let batch = & buffered_scrollback_lines[ ..] ;
786772
787773 use crate :: native:: tui:: theme:: THEME ;
788774 use ratatui:: style:: Style ;
@@ -809,17 +795,10 @@ impl InlineApp {
809795 // Track total lines inserted for cleanup on exit
810796 self . total_inserted_lines += height as u32 ;
811797
812- // Update last rendered count to reflect what we actually rendered
813- // This is incremental - we only advance by the batch size
814- let new_last_rendered = last_rendered_lines + lines_to_render;
815- self . task_last_rendered_scrollback
816- . insert ( current_task. clone ( ) , new_last_rendered) ;
817-
818798 tracing:: trace!(
819- "render_scrollback_above_tui: Updated last_rendered from {} to {} (remaining: {})" ,
820- last_rendered_lines,
821- new_last_rendered,
822- current_scrollback_lines - new_last_rendered
799+ "render_scrollback_above_tui: Rendered {} lines (total scrollback: {})" ,
800+ lines_to_render,
801+ current_scrollback_lines
823802 ) ;
824803 } else {
825804 tracing:: error!(
@@ -1375,7 +1354,6 @@ mod tests {
13751354
13761355 // Verify scrollback tracking initialized
13771356 assert_eq ! ( app. task_scrollback_lines. get( "app1" ) , Some ( & 0 ) ) ;
1378- assert_eq ! ( app. task_last_rendered_scrollback. get( "app1" ) , Some ( & 0 ) ) ;
13791357
13801358 // Verify PTY registered in state
13811359 let state_ref = app. get_state ( ) ;
0 commit comments