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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! Viewport and sizing helpers for the render pipeline.
//!
//! This module provides helpers that operate on renderer/viewport state
//! rather than on terminal content:
//! - `resolve_cursor_shader_hide`: resolves whether the cursor shader should
//! hide the default cursor, consulting per-shader overrides, metadata
//! defaults, and global config.
//! - `gather_viewport_sizing`: extracts the renderer's grid size and physical
//! pixel dimensions needed at the start of every gather pass.
use crate::app::window_state::WindowState;
use winit::dpi::PhysicalSize;
impl WindowState {
/// Extract renderer grid dimensions and physical size.
///
/// Returns `None` when no renderer is attached (rendering must be skipped).
/// Returns `(renderer_size, visible_lines, grid_cols)` otherwise.
pub(super) fn gather_viewport_sizing(&self) -> Option<(PhysicalSize<u32>, usize, usize)> {
let renderer = self.renderer.as_ref()?;
let (cols, rows) = renderer.grid_size();
Some((renderer.size(), rows, cols))
}
/// Resolve whether the cursor shader should hide the default terminal cursor.
///
/// Precedence: per-shader config override → shader metadata defaults → global config.
/// Returns `true` when the cursor should be hidden for the current shader.
///
/// Requires `&mut self` because `cursor_shader_metadata_cache` is a lazy-loading
/// cache whose `.get()` method may read from disk on first access.
pub(super) fn resolve_cursor_shader_hide(&mut self, is_alt_screen: bool) -> bool {
// Clone the shader name to an owned String so that the shared borrow on
// `self.config` is released before the mutable borrow on
// `self.shader_state.shader.cursor_shader_metadata_cache` in the closures below.
let cfg = self.config.load();
let cursor_shader_name: Option<String> = cfg.shader.cursor_shader.clone();
// hides_cursor: per-shader config override -> metadata defaults -> global config
let hides_cursor_from_config = cursor_shader_name
.as_deref()
.and_then(|name| cfg.shader_overrides.cursor_shader_configs.get(name))
.and_then(|c| c.hides_cursor);
let resolved_hides_cursor = hides_cursor_from_config
.or_else(|| {
cursor_shader_name
.as_deref()
.and_then(|name| self.shader_state.cursor_shader_metadata_cache.get(name))
.and_then(|meta| meta.defaults.hides_cursor)
})
.unwrap_or(cfg.shader.cursor_shader_hides_cursor);
// disable_in_alt_screen: per-shader override -> metadata defaults -> global config
let disable_in_alt_screen_from_config = cursor_shader_name
.as_deref()
.and_then(|name| cfg.shader_overrides.cursor_shader_configs.get(name))
.and_then(|c| c.disable_in_alt_screen);
let resolved_disable_in_alt_screen = disable_in_alt_screen_from_config
.or_else(|| {
cursor_shader_name
.as_deref()
.and_then(|name| self.shader_state.cursor_shader_metadata_cache.get(name))
.and_then(|meta| meta.defaults.disable_in_alt_screen)
})
.unwrap_or(cfg.shader.cursor_shader_disable_in_alt_screen);
cfg.shader.cursor_shader_enabled
&& resolved_hides_cursor
&& !(resolved_disable_in_alt_screen && is_alt_screen)
}
}