Skip to main content

par_term_render/renderer/shaders/
shared.rs

1//! Shader methods that coordinate across both background and cursor shaders.
2//!
3//! These operations apply uniformly to whichever renderers are currently active:
4//! mouse input forwarding, key press timing, cursor state, progress bar state,
5//! cursor shader config updates, and animation pause/resume.
6
7use super::super::Renderer;
8
9impl Renderer {
10    /// Update mouse position for custom shader (iMouse uniform)
11    pub fn set_shader_mouse_position(&mut self, x: f32, y: f32) {
12        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
13            custom_shader.set_mouse_position(x, y);
14        }
15    }
16
17    /// Update mouse button state for custom shader (iMouse uniform)
18    pub fn set_shader_mouse_button(&mut self, pressed: bool, x: f32, y: f32) {
19        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
20            custom_shader.set_mouse_button(pressed, x, y);
21        }
22    }
23
24    /// Record a key-press timestamp on both shader renderers (iTime-derived uniforms)
25    pub fn update_key_press_time(&mut self) {
26        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
27            custom_shader.update_key_press();
28        }
29        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
30            cursor_shader.update_key_press();
31        }
32    }
33
34    /// Update cursor state for both shader renderers (Ghostty-compatible cursor uniforms).
35    ///
36    /// Enables cursor trail effects and other cursor-based animations in both
37    /// background and cursor shaders.
38    pub fn update_shader_cursor(
39        &mut self,
40        col: usize,
41        row: usize,
42        opacity: f32,
43        color: [f32; 4],
44        style: par_term_emu_core_rust::cursor::CursorStyle,
45    ) {
46        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
47            custom_shader.update_cursor(col, row, opacity, color, style);
48        }
49        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
50            cursor_shader.update_cursor(col, row, opacity, color, style);
51        }
52    }
53
54    /// Clear cursor uniforms for shaders when the terminal cursor is hidden or unavailable.
55    pub fn clear_shader_cursor(&mut self) {
56        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
57            custom_shader.clear_cursor();
58        }
59        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
60            cursor_shader.clear_cursor();
61        }
62    }
63
64    /// Update progress bar state for both shader renderers (iProgress uniform).
65    ///
66    /// # Arguments
67    /// * `state` - Progress state (0=hidden, 1=normal, 2=error, 3=indeterminate, 4=warning)
68    /// * `percent` - Progress percentage as 0.0–1.0
69    /// * `is_active` - 1.0 if any progress bar is active, 0.0 otherwise
70    /// * `active_count` - Total count of active bars (simple + named)
71    pub fn update_shader_progress(
72        &mut self,
73        state: f32,
74        percent: f32,
75        is_active: f32,
76        active_count: f32,
77    ) {
78        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
79            custom_shader.update_progress(state, percent, is_active, active_count);
80        }
81        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
82            cursor_shader.update_progress(state, percent, is_active, active_count);
83        }
84    }
85
86    /// Update command lifecycle state for shader effects (iCommand uniform).
87    pub fn update_shader_command_status(&mut self, state: f32, exit_code: f32, running: f32) {
88        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
89            custom_shader.update_command_status(state, exit_code, running);
90        }
91        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
92            cursor_shader.update_command_status(state, exit_code, running);
93        }
94    }
95
96    /// Update focused pane bounds for shader effects (iFocusedPane uniform).
97    pub fn update_shader_focused_pane(
98        &mut self,
99        focused_viewport: Option<&crate::cell_renderer::PaneViewport>,
100    ) {
101        let pane = focused_viewport
102            .map(|viewport| {
103                [
104                    viewport.x,
105                    self.size.height as f32 - (viewport.y + viewport.height),
106                    viewport.width,
107                    viewport.height,
108                ]
109            })
110            .unwrap_or([0.0, 0.0, self.size.width as f32, self.size.height as f32]);
111
112        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
113            custom_shader.update_focused_pane(pane[0], pane[1], pane[2], pane[3]);
114        }
115        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
116            cursor_shader.update_focused_pane(pane[0], pane[1], pane[2], pane[3]);
117        }
118    }
119
120    /// Update scrollback context for shader effects (iScroll uniform).
121    pub fn update_shader_scrollback(
122        &mut self,
123        offset: f32,
124        visible_lines: f32,
125        scrollback_lines: f32,
126    ) {
127        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
128            custom_shader.update_scrollback(offset, visible_lines, scrollback_lines);
129        }
130        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
131            cursor_shader.update_scrollback(offset, visible_lines, scrollback_lines);
132        }
133    }
134
135    /// Update cursor shader configuration on both renderer instances.
136    ///
137    /// Glow radius is in logical pixels and will be scaled to physical pixels internally.
138    pub fn update_cursor_shader_config(
139        &mut self,
140        color: [u8; 3],
141        trail_duration: f32,
142        glow_radius: f32,
143        glow_intensity: f32,
144    ) {
145        let physical_glow_radius = glow_radius * self.cell_renderer.scale_factor;
146        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
147            custom_shader.update_cursor_shader_config(
148                color,
149                trail_duration,
150                physical_glow_radius,
151                glow_intensity,
152            );
153        }
154        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
155            cursor_shader.update_cursor_shader_config(
156                color,
157                trail_duration,
158                physical_glow_radius,
159                glow_intensity,
160            );
161        }
162    }
163
164    /// Pause shader animations on all active renderers (e.g., when window loses focus).
165    pub fn pause_shader_animations(&mut self) {
166        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
167            custom_shader.set_animation_enabled(false);
168        }
169        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
170            cursor_shader.set_animation_enabled(false);
171        }
172        log::info!("[SHADER] Shader animations paused");
173    }
174
175    /// Resume shader animations on all active renderers (e.g., when window regains focus).
176    ///
177    /// Only resumes if the user's config has animation enabled for that shader.
178    pub fn resume_shader_animations(
179        &mut self,
180        custom_shader_animation: bool,
181        cursor_shader_animation: bool,
182    ) {
183        if let Some(ref mut custom_shader) = self.custom_shader_renderer {
184            custom_shader.set_animation_enabled(custom_shader_animation);
185        }
186        if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
187            cursor_shader.set_animation_enabled(cursor_shader_animation);
188        }
189        self.dirty = true;
190        log::info!(
191            "[SHADER] Shader animations resumed (custom: {}, cursor: {})",
192            custom_shader_animation,
193            cursor_shader_animation
194        );
195    }
196}