par_term_render/renderer/
state.rs1use crate::cell_renderer::Cell;
2use anyhow::Result;
3use par_term_config::SeparatorMark;
4use par_term_config::color_u8_to_f32;
5
6use super::Renderer;
7
8impl Renderer {
12 pub fn is_dirty(&self) -> bool {
14 self.dirty
15 }
16
17 pub fn mark_dirty(&mut self) {
19 self.dirty = true;
20 }
21
22 pub fn render_debug_overlay(&mut self, text: &str) {
24 self.debug_text = Some(text.to_string());
25 self.dirty = true; }
27
28 pub fn reconfigure_surface(&mut self) {
31 self.cell_renderer.reconfigure_surface();
32 self.dirty = true;
33 }
34
35 pub fn is_vsync_mode_supported(&self, mode: par_term_config::VsyncMode) -> bool {
37 self.cell_renderer.is_vsync_mode_supported(mode)
38 }
39
40 pub fn update_vsync_mode(
43 &mut self,
44 mode: par_term_config::VsyncMode,
45 ) -> (par_term_config::VsyncMode, bool) {
46 let result = self.cell_renderer.update_vsync_mode(mode);
47 if result.1 {
48 self.dirty = true;
49 }
50 result
51 }
52
53 pub fn current_vsync_mode(&self) -> par_term_config::VsyncMode {
55 self.cell_renderer.current_vsync_mode()
56 }
57
58 pub fn clear_glyph_cache(&mut self) {
61 self.cell_renderer.clear_glyph_cache();
62 self.dirty = true;
63 }
64
65 pub fn update_font_antialias(&mut self, enabled: bool) -> bool {
68 let changed = self.cell_renderer.update_font_antialias(enabled);
69 if changed {
70 self.dirty = true;
71 }
72 changed
73 }
74
75 pub fn update_font_hinting(&mut self, enabled: bool) -> bool {
78 let changed = self.cell_renderer.update_font_hinting(enabled);
79 if changed {
80 self.dirty = true;
81 }
82 changed
83 }
84
85 pub fn update_font_thin_strokes(&mut self, mode: par_term_config::ThinStrokesMode) -> bool {
88 let changed = self.cell_renderer.update_font_thin_strokes(mode);
89 if changed {
90 self.dirty = true;
91 }
92 changed
93 }
94
95 pub fn update_minimum_contrast(&mut self, value: f32) -> bool {
98 let changed = self.cell_renderer.update_minimum_contrast(value);
99 if changed {
100 self.dirty = true;
101 }
102 changed
103 }
104
105 pub fn scrollbar_contains_point(&self, x: f32, y: f32) -> bool {
111 self.cell_renderer.scrollbar_contains_point(x, y)
112 }
113
114 pub fn scrollbar_thumb_bounds(&self) -> Option<(f32, f32)> {
116 self.cell_renderer.scrollbar_thumb_bounds()
117 }
118
119 pub fn scrollbar_track_contains_x(&self, x: f32) -> bool {
121 self.cell_renderer.scrollbar_track_contains_x(x)
122 }
123
124 pub fn scrollbar_mouse_y_to_scroll_offset(&self, mouse_y: f32) -> Option<usize> {
132 self.cell_renderer
133 .scrollbar_mouse_y_to_scroll_offset(mouse_y)
134 }
135
136 pub fn scrollbar_mark_at_position(
146 &self,
147 mouse_x: f32,
148 mouse_y: f32,
149 tolerance: f32,
150 ) -> Option<&par_term_config::ScrollbackMark> {
151 self.cell_renderer
152 .scrollbar_mark_at_position(mouse_x, mouse_y, tolerance)
153 }
154}
155
156impl Renderer {
157 pub fn update_cells(&mut self, cells: &[Cell]) {
158 if self.cell_renderer.update_cells(cells) {
159 self.dirty = true;
160 }
161 }
162
163 pub fn clear_all_cells(&mut self) {
166 self.cell_renderer.clear_all_cells();
167 self.dirty = true;
168 }
169
170 pub fn update_cursor(
172 &mut self,
173 position: (usize, usize),
174 opacity: f32,
175 style: par_term_emu_core_rust::cursor::CursorStyle,
176 ) {
177 if self.cell_renderer.update_cursor(position, opacity, style) {
178 self.dirty = true;
179 }
180 }
181
182 pub fn clear_cursor(&mut self) {
184 if self.cell_renderer.clear_cursor() {
185 self.dirty = true;
186 }
187 }
188
189 pub fn update_scrollbar(
191 &mut self,
192 scroll_offset: usize,
193 visible_lines: usize,
194 total_lines: usize,
195 marks: &[par_term_config::ScrollbackMark],
196 ) {
197 let new_state = (
198 scroll_offset,
199 visible_lines,
200 total_lines,
201 marks.len(),
202 self.cell_renderer.config.width,
203 self.cell_renderer.config.height,
204 0,
206 0,
207 0,
208 0,
209 );
210 if new_state == self.last_scrollbar_state {
211 return;
212 }
213 self.last_scrollbar_state = new_state;
214 self.cell_renderer
215 .update_scrollbar(scroll_offset, visible_lines, total_lines, marks);
216 self.dirty = true;
217 }
218
219 pub fn set_visual_bell_intensity(&mut self, intensity: f32) {
224 self.cell_renderer.set_visual_bell_intensity(intensity);
225 if intensity > 0.0 {
226 self.dirty = true; }
228 }
229
230 pub fn set_visual_bell_color(&mut self, color: [f32; 3]) {
232 self.cell_renderer.set_visual_bell_color(color);
233 }
234
235 pub fn update_opacity(&mut self, opacity: f32) {
237 self.cell_renderer.update_opacity(opacity);
238
239 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
241 custom_shader.set_opacity(opacity);
242 }
243
244 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
246 cursor_shader.set_opacity(opacity);
247 }
248
249 self.dirty = true;
250 }
251
252 pub fn update_cursor_color(&mut self, color: [u8; 3]) {
254 self.cell_renderer.update_cursor_color(color);
255 self.dirty = true;
256 }
257
258 pub fn update_cursor_text_color(&mut self, color: Option<[u8; 3]>) {
260 self.cell_renderer.update_cursor_text_color(color);
261 self.dirty = true;
262 }
263
264 pub fn set_cursor_hidden_for_shader(&mut self, hidden: bool) {
266 if self.cell_renderer.set_cursor_hidden_for_shader(hidden) {
267 self.dirty = true;
268 }
269 }
270
271 pub fn set_focused(&mut self, focused: bool) {
273 if self.cell_renderer.set_focused(focused) {
274 self.dirty = true;
275 }
276 }
277
278 pub fn update_cursor_guide(&mut self, enabled: bool, color: [u8; 4]) {
280 self.cell_renderer.update_cursor_guide(enabled, color);
281 self.dirty = true;
282 }
283
284 pub fn update_cursor_shadow(
287 &mut self,
288 enabled: bool,
289 color: [u8; 4],
290 offset: [f32; 2],
291 blur: f32,
292 ) {
293 let scale = self.cell_renderer.scale_factor;
294 let physical_offset = [offset[0] * scale, offset[1] * scale];
295 let physical_blur = blur * scale;
296 self.cell_renderer
297 .update_cursor_shadow(enabled, color, physical_offset, physical_blur);
298 self.dirty = true;
299 }
300
301 pub fn update_cursor_boost(&mut self, intensity: f32, color: [u8; 3]) {
303 self.cell_renderer.update_cursor_boost(intensity, color);
304 self.dirty = true;
305 }
306
307 pub fn update_unfocused_cursor_style(&mut self, style: par_term_config::UnfocusedCursorStyle) {
309 self.cell_renderer.update_unfocused_cursor_style(style);
310 self.dirty = true;
311 }
312
313 pub fn update_command_separator(
316 &mut self,
317 enabled: bool,
318 logical_thickness: f32,
319 opacity: f32,
320 exit_color: bool,
321 color: [u8; 3],
322 ) {
323 let physical_thickness = logical_thickness * self.cell_renderer.scale_factor;
324 self.cell_renderer.update_command_separator(
325 enabled,
326 physical_thickness,
327 opacity,
328 exit_color,
329 color,
330 );
331 self.dirty = true;
332 }
333
334 pub fn set_separator_marks(&mut self, marks: Vec<SeparatorMark>) {
336 if self.cell_renderer.set_separator_marks(marks) {
337 self.dirty = true;
338 }
339 }
340
341 pub fn set_gutter_indicators(&mut self, indicators: Vec<(usize, [f32; 4])>) {
343 self.cell_renderer.set_gutter_indicators(indicators);
344 self.dirty = true;
345 }
346
347 pub fn set_transparency_affects_only_default_background(&mut self, value: bool) {
350 self.cell_renderer
351 .set_transparency_affects_only_default_background(value);
352 self.dirty = true;
353 }
354
355 pub fn set_keep_text_opaque(&mut self, value: bool) {
358 self.cell_renderer.set_keep_text_opaque(value);
359
360 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
362 custom_shader.set_keep_text_opaque(value);
363 }
364
365 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
367 cursor_shader.set_keep_text_opaque(value);
368 }
369
370 self.dirty = true;
371 }
372
373 pub fn set_link_underline_style(&mut self, style: par_term_config::LinkUnderlineStyle) {
374 self.cell_renderer.set_link_underline_style(style);
375 self.dirty = true;
376 }
377
378 pub fn set_cursor_shader_disabled_for_alt_screen(&mut self, disabled: bool) {
383 if self.cursor_shader_disabled_for_alt_screen != disabled {
384 log::debug!("[cursor-shader] Alt-screen disable set to {}", disabled);
385 self.cursor_shader_disabled_for_alt_screen = disabled;
386 } else {
387 self.cursor_shader_disabled_for_alt_screen = disabled;
388 }
389 }
390
391 pub fn update_window_padding(&mut self, logical_padding: f32) -> Option<(usize, usize)> {
395 let physical_padding = logical_padding * self.cell_renderer.scale_factor;
396 let result = self.cell_renderer.update_window_padding(physical_padding);
397 self.graphics_renderer.update_cell_dimensions(
399 self.cell_renderer.cell_width(),
400 self.cell_renderer.cell_height(),
401 physical_padding,
402 );
403 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
405 custom_shader.update_cell_dimensions(
406 self.cell_renderer.cell_width(),
407 self.cell_renderer.cell_height(),
408 physical_padding,
409 );
410 }
411 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
413 cursor_shader.update_cell_dimensions(
414 self.cell_renderer.cell_width(),
415 self.cell_renderer.cell_height(),
416 physical_padding,
417 );
418 }
419 self.dirty = true;
420 result
421 }
422
423 pub fn set_background_image_enabled(
425 &mut self,
426 enabled: bool,
427 path: Option<&str>,
428 mode: par_term_config::BackgroundImageMode,
429 opacity: f32,
430 ) {
431 let path = if enabled { path } else { None };
432 self.cell_renderer.set_background_image(path, mode, opacity);
433
434 self.sync_background_texture_to_shader();
436
437 self.dirty = true;
438 }
439
440 pub fn set_background(
444 &mut self,
445 mode: par_term_config::BackgroundMode,
446 color: [u8; 3],
447 image_path: Option<&str>,
448 image_mode: par_term_config::BackgroundImageMode,
449 image_opacity: f32,
450 image_enabled: bool,
451 ) {
452 self.cell_renderer.set_background(
453 mode,
454 color,
455 image_path,
456 image_mode,
457 image_opacity,
458 image_enabled,
459 );
460
461 self.sync_background_texture_to_shader();
463
464 let is_solid_color = matches!(mode, par_term_config::BackgroundMode::Color);
466 let is_image_mode = matches!(mode, par_term_config::BackgroundMode::Image);
467 let normalized_color = color_u8_to_f32(color);
468
469 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
471 let has_background_shader = self.custom_shader_renderer.is_some();
474
475 if has_background_shader {
476 cursor_shader.set_background_color([0.0, 0.0, 0.0], false);
478 cursor_shader.set_background_texture(self.cell_renderer.device(), None);
479 cursor_shader.update_use_background_as_channel0(self.cell_renderer.device(), false);
480 } else {
481 cursor_shader.set_background_color(normalized_color, is_solid_color);
482
483 if is_image_mode && image_enabled {
485 let bg_texture = self.cell_renderer.get_background_as_channel_texture();
486 cursor_shader.set_background_texture(self.cell_renderer.device(), bg_texture);
487 cursor_shader
488 .update_use_background_as_channel0(self.cell_renderer.device(), true);
489 } else {
490 cursor_shader.set_background_texture(self.cell_renderer.device(), None);
492 cursor_shader
493 .update_use_background_as_channel0(self.cell_renderer.device(), false);
494 }
495 }
496 }
497
498 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
503 custom_shader.set_background_color(normalized_color, false);
504 }
505
506 self.dirty = true;
507 }
508
509 pub fn update_scrollbar_appearance(
512 &mut self,
513 logical_width: f32,
514 thumb_color: [f32; 4],
515 track_color: [f32; 4],
516 ) {
517 let physical_width = logical_width * self.cell_renderer.scale_factor;
518 self.cell_renderer
519 .update_scrollbar_appearance(physical_width, thumb_color, track_color);
520 self.last_scrollbar_state = (usize::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0);
523 self.dirty = true;
524 }
525
526 pub fn update_scrollbar_position(&mut self, position: &str) {
528 self.cell_renderer.update_scrollbar_position(position);
529 self.dirty = true;
530 }
531
532 pub fn update_background_image_opacity(&mut self, opacity: f32) {
534 self.cell_renderer.update_background_image_opacity(opacity);
535 self.dirty = true;
536 }
537
538 pub fn load_pane_background(&mut self, path: &str) -> Result<bool, crate::error::RenderError> {
541 self.cell_renderer.load_pane_background(path)
542 }
543
544 pub fn update_image_scaling_mode(&mut self, scaling_mode: par_term_config::ImageScalingMode) {
549 self.graphics_renderer
550 .update_scaling_mode(self.cell_renderer.device(), scaling_mode);
551 self.dirty = true;
552 }
553
554 pub fn update_image_preserve_aspect_ratio(&mut self, preserve: bool) {
556 self.graphics_renderer.set_preserve_aspect_ratio(preserve);
557 self.dirty = true;
558 }
559
560 pub fn needs_continuous_render(&self) -> bool {
565 let custom_needs = self
566 .custom_shader_renderer
567 .as_ref()
568 .is_some_and(|r| r.animation_enabled() || r.cursor_needs_animation());
569 let cursor_needs = self
570 .cursor_shader_renderer
571 .as_ref()
572 .is_some_and(|r| r.animation_enabled() || r.cursor_needs_animation());
573 custom_needs || cursor_needs
574 }
575}