@@ -8,11 +8,13 @@ const easing = @import("../anim/easing.zig");
88const font_mod = @import ("../font.zig" );
99const FontVariant = font_mod .Variant ;
1010const session_state = @import ("../session/state.zig" );
11+ const view_state = @import ("../ui/session_view_state.zig" );
1112const primitives = @import ("../gfx/primitives.zig" );
1213
1314const log = std .log .scoped (.render );
1415
1516const SessionState = session_state .SessionState ;
17+ const SessionViewState = view_state .SessionViewState ;
1618const Rect = geom .Rect ;
1719const AnimationState = app_state .AnimationState ;
1820
@@ -71,6 +73,7 @@ pub fn render(
7173 renderer : * c.SDL_Renderer ,
7274 render_cache : * RenderCache ,
7375 sessions : []SessionState ,
76+ views : []const SessionViewState ,
7477 cell_width_pixels : c_int ,
7578 cell_height_pixels : c_int ,
7679 grid_cols : usize ,
@@ -87,6 +90,7 @@ pub fn render(
8790) RenderError ! void {
8891 _ = c .SDL_SetRenderDrawColor (renderer , theme .background .r , theme .background .g , theme .background .b , 255 );
8992 _ = c .SDL_RenderClear (renderer );
93+ std .debug .assert (sessions .len == views .len );
9094
9195 // Use the larger dimension for grid scale to ensure proper scaling
9296 // Multiply by grid_font_scale to allow proportionally larger font in grid view
@@ -108,13 +112,13 @@ pub fn render(
108112 };
109113
110114 const entry = render_cache .entry (i );
111- try renderGridSessionCached (renderer , session , entry , cell_rect , grid_scale , i == anim_state .focused_session , true , font , term_cols , term_rows , current_time , theme );
115+ try renderGridSessionCached (renderer , session , & views [ i ], entry , cell_rect , grid_scale , i == anim_state .focused_session , true , font , term_cols , term_rows , current_time , theme );
112116 }
113117 },
114118 .Full = > {
115119 const full_rect = Rect { .x = 0 , .y = 0 , .w = window_width , .h = window_height };
116120 const entry = render_cache .entry (anim_state .focused_session );
117- try renderSession (renderer , & sessions [anim_state .focused_session ], entry , full_rect , 1.0 , true , false , font , term_cols , term_rows , current_time , false , theme );
121+ try renderSession (renderer , & sessions [anim_state .focused_session ], & views [ anim_state . focused_session ], entry , full_rect , 1.0 , true , false , font , term_cols , term_rows , current_time , false , theme );
118122 },
119123 .PanningLeft , .PanningRight = > {
120124 const elapsed = current_time - anim_state .start_time ;
@@ -126,15 +130,15 @@ pub fn render(
126130
127131 const prev_rect = Rect { .x = pan_offset , .y = 0 , .w = window_width , .h = window_height };
128132 const prev_entry = render_cache .entry (anim_state .previous_session );
129- try renderSession (renderer , & sessions [anim_state .previous_session ], prev_entry , prev_rect , 1.0 , false , false , font , term_cols , term_rows , current_time , false , theme );
133+ try renderSession (renderer , & sessions [anim_state .previous_session ], & views [ anim_state . previous_session ], prev_entry , prev_rect , 1.0 , false , false , font , term_cols , term_rows , current_time , false , theme );
130134
131135 const new_offset = if (anim_state .mode == .PanningLeft )
132136 window_width - offset
133137 else
134138 - window_width + offset ;
135139 const new_rect = Rect { .x = new_offset , .y = 0 , .w = window_width , .h = window_height };
136140 const new_entry = render_cache .entry (anim_state .focused_session );
137- try renderSession (renderer , & sessions [anim_state .focused_session ], new_entry , new_rect , 1.0 , true , false , font , term_cols , term_rows , current_time , false , theme );
141+ try renderSession (renderer , & sessions [anim_state .focused_session ], & views [ anim_state . focused_session ], new_entry , new_rect , 1.0 , true , false , font , term_cols , term_rows , current_time , false , theme );
138142 },
139143 .PanningUp , .PanningDown = > {
140144 const elapsed = current_time - anim_state .start_time ;
@@ -146,15 +150,15 @@ pub fn render(
146150
147151 const prev_rect = Rect { .x = 0 , .y = pan_offset , .w = window_width , .h = window_height };
148152 const prev_entry = render_cache .entry (anim_state .previous_session );
149- try renderSession (renderer , & sessions [anim_state .previous_session ], prev_entry , prev_rect , 1.0 , false , false , font , term_cols , term_rows , current_time , false , theme );
153+ try renderSession (renderer , & sessions [anim_state .previous_session ], & views [ anim_state . previous_session ], prev_entry , prev_rect , 1.0 , false , false , font , term_cols , term_rows , current_time , false , theme );
150154
151155 const new_offset = if (anim_state .mode == .PanningUp )
152156 window_height - offset
153157 else
154158 - window_height + offset ;
155159 const new_rect = Rect { .x = 0 , .y = new_offset , .w = window_width , .h = window_height };
156160 const new_entry = render_cache .entry (anim_state .focused_session );
157- try renderSession (renderer , & sessions [anim_state .focused_session ], new_entry , new_rect , 1.0 , true , false , font , term_cols , term_rows , current_time , false , theme );
161+ try renderSession (renderer , & sessions [anim_state .focused_session ], & views [ anim_state . focused_session ], new_entry , new_rect , 1.0 , true , false , font , term_cols , term_rows , current_time , false , theme );
158162 },
159163 .Expanding , .Collapsing = > {
160164 const animating_rect = anim_state .getCurrentRect (current_time );
@@ -179,20 +183,21 @@ pub fn render(
179183 };
180184
181185 const entry = render_cache .entry (i );
182- try renderGridSessionCached (renderer , session , entry , cell_rect , grid_scale , false , true , font , term_cols , term_rows , current_time , theme );
186+ try renderGridSessionCached (renderer , session , & views [ i ], entry , cell_rect , grid_scale , false , true , font , term_cols , term_rows , current_time , theme );
183187 }
184188 }
185189
186190 const apply_effects = anim_scale < 0.999 ;
187191 const entry = render_cache .entry (anim_state .focused_session );
188- try renderSession (renderer , & sessions [anim_state .focused_session ], entry , animating_rect , anim_scale , true , apply_effects , font , term_cols , term_rows , current_time , false , theme );
192+ try renderSession (renderer , & sessions [anim_state .focused_session ], & views [ anim_state . focused_session ], entry , animating_rect , anim_scale , true , apply_effects , font , term_cols , term_rows , current_time , false , theme );
189193 },
190194 }
191195}
192196
193197fn renderSession (
194198 renderer : * c.SDL_Renderer ,
195199 session : * SessionState ,
200+ view : * const SessionViewState ,
196201 cache_entry : * RenderCache.Entry ,
197202 rect : Rect ,
198203 scale : f32 ,
@@ -205,14 +210,15 @@ fn renderSession(
205210 is_grid_view : bool ,
206211 theme : * const colors.Theme ,
207212) RenderError ! void {
208- try renderSessionContent (renderer , session , rect , scale , is_focused , font , term_cols , term_rows , theme );
209- renderSessionOverlays (renderer , session , rect , is_focused , apply_effects , current_time_ms , is_grid_view , theme );
213+ try renderSessionContent (renderer , session , view , rect , scale , is_focused , font , term_cols , term_rows , theme );
214+ renderSessionOverlays (renderer , view , rect , is_focused , apply_effects , current_time_ms , is_grid_view , theme );
210215 cache_entry .presented_epoch = session .render_epoch ;
211216}
212217
213218fn renderSessionContent (
214219 renderer : * c.SDL_Renderer ,
215220 session : * SessionState ,
221+ view : * const SessionViewState ,
216222 rect : Rect ,
217223 scale : f32 ,
218224 is_focused : bool ,
@@ -247,7 +253,7 @@ fn renderSessionContent(
247253 const cursor = screen .cursor ;
248254 const cursor_col : usize = cursor .x ;
249255 const cursor_row : usize = cursor .y ;
250- const should_render_cursor = ! session .is_viewing_scrollback and is_focused and ! session .dead and cursor_visible ;
256+ const should_render_cursor = ! view .is_viewing_scrollback and is_focused and ! session .dead and cursor_visible ;
251257 const pages = screen .pages ;
252258
253259 const base_cell_width = font .cell_width ;
@@ -288,7 +294,7 @@ fn renderSessionContent(
288294
289295 var col : usize = 0 ;
290296 while (col < visible_cols ) : (col += 1 ) {
291- const list_cell = pages .getCell (if (session .is_viewing_scrollback )
297+ const list_cell = pages .getCell (if (view .is_viewing_scrollback )
292298 .{ .viewport = .{ .x = @intCast (col ), .y = @intCast (row ) } }
293299 else
294300 .{ .active = .{ .x = @intCast (col ), .y = @intCast (row ) } }) orelse continue ;
@@ -343,7 +349,7 @@ fn renderSessionContent(
343349 }
344350
345351 if (active_selection ) | sel | {
346- const point_tag = if (session .is_viewing_scrollback )
352+ const point_tag = if (view .is_viewing_scrollback )
347353 ghostty_vt.point.Point { .viewport = .{ .x = @intCast (col ), .y = @intCast (row ) } }
348354 else
349355 ghostty_vt.point.Point { .active = .{ .x = @intCast (col ), .y = @intCast (row ) } };
@@ -362,9 +368,9 @@ fn renderSessionContent(
362368 }
363369 }
364370
365- if (session .hovered_link_start ) | link_start | {
366- if (session .hovered_link_end ) | link_end | {
367- const point_for_link = if (session .is_viewing_scrollback )
371+ if (view .hovered_link_start ) | link_start | {
372+ if (view .hovered_link_end ) | link_end | {
373+ const point_for_link = if (view .is_viewing_scrollback )
368374 ghostty_vt.point.Point { .viewport = .{ .x = @intCast (col ), .y = @intCast (row ) } }
369375 else
370376 ghostty_vt.point.Point { .active = .{ .x = @intCast (col ), .y = @intCast (row ) } };
@@ -497,15 +503,15 @@ fn renderSessionContent(
497503
498504fn renderSessionOverlays (
499505 renderer : * c.SDL_Renderer ,
500- session : * SessionState ,
506+ view : * const SessionViewState ,
501507 rect : Rect ,
502508 is_focused : bool ,
503509 apply_effects : bool ,
504510 current_time_ms : i64 ,
505511 is_grid_view : bool ,
506512 theme : * const colors.Theme ,
507513) void {
508- const has_attention = is_grid_view and session .attention ;
514+ const has_attention = is_grid_view and view .attention ;
509515 const border_thickness : c_int = ATTENTION_THICKNESS ;
510516
511517 if (apply_effects ) {
@@ -542,7 +548,7 @@ fn renderSessionOverlays(
542548 }
543549 }
544550
545- if (is_grid_view and session .is_viewing_scrollback ) {
551+ if (is_grid_view and view .is_viewing_scrollback ) {
546552 const yellow = theme .palette [3 ];
547553 _ = c .SDL_SetRenderDrawColor (renderer , yellow .r , yellow .g , yellow .b , 220 );
548554 const indicator_rect = c.SDL_FRect {
@@ -563,7 +569,7 @@ fn renderSessionOverlays(
563569 .b = @intCast (std .math .clamp (@as (i32 , base_green .b ) - 20 , 0 , 255 )),
564570 .a = 255 ,
565571 };
566- const color = switch (session .status ) {
572+ const color = switch (view .status ) {
567573 .awaiting_approval = > blk : {
568574 const phase_ms : f32 = @floatFromInt (@mod (current_time_ms , @as (i64 , 1000 )));
569575 const pulse = 0.5 + 0.5 * std .math .sin (phase_ms / 1000.0 * 2.0 * std .math .pi );
@@ -577,7 +583,7 @@ fn renderSessionOverlays(
577583 };
578584 primitives .drawThickBorder (renderer , rect , ATTENTION_THICKNESS , color );
579585
580- const tint_color = switch (session .status ) {
586+ const tint_color = switch (view .status ) {
581587 .awaiting_approval = > c.SDL_Color { .r = yellow .r , .g = yellow .g , .b = yellow .b , .a = 25 },
582588 .done = > blk : {
583589 break :blk c.SDL_Color { .r = done_green .r , .g = done_green .g , .b = done_green .b , .a = 35 };
@@ -625,6 +631,7 @@ fn ensureCacheTexture(renderer: *c.SDL_Renderer, cache_entry: *RenderCache.Entry
625631fn renderGridSessionCached (
626632 renderer : * c.SDL_Renderer ,
627633 session : * SessionState ,
634+ view : * const SessionViewState ,
628635 cache_entry : * RenderCache.Entry ,
629636 rect : Rect ,
630637 scale : f32 ,
@@ -647,7 +654,7 @@ fn renderGridSessionCached(
647654 _ = c .SDL_SetRenderDrawColor (renderer , theme .background .r , theme .background .g , theme .background .b , 255 );
648655 _ = c .SDL_RenderClear (renderer );
649656 const local_rect = Rect { .x = 0 , .y = 0 , .w = rect .w , .h = rect .h };
650- try renderSessionContent (renderer , session , local_rect , scale , is_focused , font , term_cols , term_rows , theme );
657+ try renderSessionContent (renderer , session , view , local_rect , scale , is_focused , font , term_cols , term_rows , theme );
651658 cache_entry .cache_epoch = session .render_epoch ;
652659 _ = c .SDL_SetRenderTarget (renderer , null );
653660 }
@@ -659,13 +666,13 @@ fn renderGridSessionCached(
659666 .h = @floatFromInt (rect .h ),
660667 };
661668 _ = c .SDL_RenderTexture (renderer , tex , null , & dest_rect );
662- renderSessionOverlays (renderer , session , rect , is_focused , apply_effects , current_time_ms , true , theme );
669+ renderSessionOverlays (renderer , view , rect , is_focused , apply_effects , current_time_ms , true , theme );
663670 cache_entry .presented_epoch = session .render_epoch ;
664671 return ;
665672 }
666673 }
667674
668- try renderSession (renderer , session , cache_entry , rect , scale , is_focused , apply_effects , font , term_cols , term_rows , current_time_ms , true , theme );
675+ try renderSession (renderer , session , view , cache_entry , rect , scale , is_focused , apply_effects , font , term_cols , term_rows , current_time_ms , true , theme );
669676}
670677
671678fn applyTvOverlay (renderer : * c.SDL_Renderer , rect : Rect , is_focused : bool , theme : * const colors.Theme ) void {
0 commit comments