1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use crate::cell_renderer::Cell;
use crate::selection::Selection;
use std::sync::Arc;
/// State related to render caching and dirty tracking
pub struct RenderCache {
pub(crate) cells: Option<Arc<Vec<Cell>>>, // Cached cells from last render (dirty tracking; Arc avoids double-clone on cache hit)
pub(crate) generation: u64, // Last terminal generation number (for dirty tracking)
pub(crate) scroll_offset: usize, // Last scroll offset (for cache invalidation)
pub(crate) cursor_pos: Option<(usize, usize)>, // Last cursor position (for cache invalidation)
pub(crate) selection: Option<Selection>, // Last selection state (for cache invalidation)
pub(crate) grid_dims: (usize, usize), // Last known terminal grid dimensions (cols, rows)
pub(crate) terminal_title: String, // Last known terminal title (for change detection)
pub(crate) scrollback_len: usize, // Last known scrollback length
pub(crate) pane_cells: Option<Arc<Vec<Cell>>>, // Cached cells for pane rendering (reuse across frames)
pub(crate) pane_cells_generation: u64, // Generation of cached pane_cells (0 = stale/unset)
pub(crate) pane_cells_scroll_offset: usize, // Scroll offset used when pane_cells was generated
pub(crate) pane_cells_selection: Option<Selection>, // Selection used when pane_cells was generated
pub(crate) pane_cells_grid_dims: (usize, usize), // Grid dimensions used when pane_cells was generated
pub(crate) pane_scrollback_len: usize, // Cached scrollback_len for pane rendering
}
impl RenderCache {
pub(crate) fn new() -> Self {
Self {
cells: None,
generation: 0,
scroll_offset: 0,
cursor_pos: None,
selection: None,
grid_dims: (0, 0),
terminal_title: String::new(),
scrollback_len: 0,
pane_cells: None,
pane_cells_generation: 0,
pane_cells_scroll_offset: 0,
pane_cells_selection: None,
pane_cells_grid_dims: (0, 0),
pane_scrollback_len: 0,
}
}
/// Force the next `gather_pane_render_data` call to regather cells for this
/// pane instead of reusing the cross-frame cache.
///
/// Needed for frontend-driven mutations that change rendered cell content
/// without going through the PTY reader thread (which is the only place
/// `update_generation` is bumped) — e.g. theme changes or `clear_scrollback()`.
pub(crate) fn invalidate_pane_cells(&mut self) {
self.pane_cells = None;
self.pane_cells_generation = 0;
}
}
impl Default for RenderCache {
fn default() -> Self {
Self::new()
}
}