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 reconfigure_after_display_change(&mut self, width: u32, height: u32) {
41 self.cell_renderer
42 .reconfigure_after_display_change(width, height);
43 self.dirty = true;
44 }
45
46 pub fn is_vsync_mode_supported(&self, mode: par_term_config::VsyncMode) -> bool {
48 self.cell_renderer.is_vsync_mode_supported(mode)
49 }
50
51 pub fn update_vsync_mode(
54 &mut self,
55 mode: par_term_config::VsyncMode,
56 ) -> (par_term_config::VsyncMode, bool) {
57 let result = self.cell_renderer.update_vsync_mode(mode);
58 if result.1 {
59 self.dirty = true;
60 }
61 result
62 }
63
64 pub fn current_vsync_mode(&self) -> par_term_config::VsyncMode {
66 self.cell_renderer.current_vsync_mode()
67 }
68
69 pub fn clear_glyph_cache(&mut self) {
72 self.cell_renderer.clear_glyph_cache();
73 self.dirty = true;
74 }
75
76 pub fn update_font_antialias(&mut self, enabled: bool) -> bool {
79 let changed = self.cell_renderer.update_font_antialias(enabled);
80 if changed {
81 self.dirty = true;
82 }
83 changed
84 }
85
86 pub fn update_font_hinting(&mut self, enabled: bool) -> bool {
89 let changed = self.cell_renderer.update_font_hinting(enabled);
90 if changed {
91 self.dirty = true;
92 }
93 changed
94 }
95
96 pub fn update_font_thin_strokes(&mut self, mode: par_term_config::ThinStrokesMode) -> bool {
99 let changed = self.cell_renderer.update_font_thin_strokes(mode);
100 if changed {
101 self.dirty = true;
102 }
103 changed
104 }
105
106 pub fn update_minimum_contrast(&mut self, value: f32) -> bool {
109 let changed = self.cell_renderer.update_minimum_contrast(value);
110 if changed {
111 self.dirty = true;
112 }
113 changed
114 }
115
116 pub fn scrollbar_contains_point(&self, x: f32, y: f32) -> bool {
122 self.cell_renderer.scrollbar_contains_point(x, y)
123 }
124
125 pub fn scrollbar_thumb_bounds(&self) -> Option<(f32, f32)> {
127 self.cell_renderer.scrollbar_thumb_bounds()
128 }
129
130 pub fn scrollbar_track_contains_x(&self, x: f32) -> bool {
132 self.cell_renderer.scrollbar_track_contains_x(x)
133 }
134
135 pub fn scrollbar_mouse_y_to_scroll_offset(&self, mouse_y: f32) -> Option<usize> {
143 self.cell_renderer
144 .scrollbar_mouse_y_to_scroll_offset(mouse_y)
145 }
146
147 pub fn scrollbar_mark_at_position(
157 &self,
158 mouse_x: f32,
159 mouse_y: f32,
160 tolerance: f32,
161 ) -> Option<&par_term_config::ScrollbackMark> {
162 self.cell_renderer
163 .scrollbar_mark_at_position(mouse_x, mouse_y, tolerance)
164 }
165}
166
167impl Renderer {
168 pub fn update_cells(&mut self, cells: &[Cell]) {
169 if self.cell_renderer.update_cells(cells) {
170 self.dirty = true;
171 }
172 }
173
174 pub fn clear_all_cells(&mut self) {
177 self.cell_renderer.clear_all_cells();
178 self.dirty = true;
179 }
180
181 pub fn update_cursor(
183 &mut self,
184 position: (usize, usize),
185 opacity: f32,
186 style: par_term_emu_core_rust::cursor::CursorStyle,
187 ) {
188 if self.cell_renderer.update_cursor(position, opacity, style) {
189 self.dirty = true;
190 }
191 }
192
193 pub fn clear_cursor(&mut self) {
195 if self.cell_renderer.clear_cursor() {
196 self.dirty = true;
197 }
198 }
199
200 pub fn update_scrollbar(
202 &mut self,
203 scroll_offset: usize,
204 visible_lines: usize,
205 total_lines: usize,
206 marks: &[par_term_config::ScrollbackMark],
207 ) {
208 let new_state = (
209 scroll_offset,
210 visible_lines,
211 total_lines,
212 marks.len(),
213 self.cell_renderer.config.width,
214 self.cell_renderer.config.height,
215 0,
217 0,
218 0,
219 0,
220 );
221 if new_state == self.last_scrollbar_state {
222 return;
223 }
224 self.last_scrollbar_state = new_state;
225 self.cell_renderer
226 .update_scrollbar(scroll_offset, visible_lines, total_lines, marks);
227 self.dirty = true;
228 }
229
230 pub fn set_visual_bell_intensity(&mut self, intensity: f32) {
235 self.cell_renderer.set_visual_bell_intensity(intensity);
236 if intensity > 0.0 {
237 self.dirty = true; }
239 }
240
241 pub fn set_visual_bell_color(&mut self, color: [f32; 3]) {
243 self.cell_renderer.set_visual_bell_color(color);
244 }
245
246 pub fn update_opacity(&mut self, opacity: f32) {
248 self.cell_renderer.update_opacity(opacity);
249
250 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
252 custom_shader.set_opacity(opacity);
253 }
254
255 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
257 cursor_shader.set_opacity(opacity);
258 }
259
260 self.dirty = true;
261 }
262
263 pub fn update_cursor_color(&mut self, color: [u8; 3]) {
265 self.cell_renderer.update_cursor_color(color);
266 self.dirty = true;
267 }
268
269 pub fn update_cursor_text_color(&mut self, color: Option<[u8; 3]>) {
271 self.cell_renderer.update_cursor_text_color(color);
272 self.dirty = true;
273 }
274
275 pub fn set_cursor_hidden_for_shader(&mut self, hidden: bool) {
277 if self.cell_renderer.set_cursor_hidden_for_shader(hidden) {
278 self.dirty = true;
279 }
280 }
281
282 pub fn set_focused(&mut self, focused: bool) {
284 if self.cell_renderer.set_focused(focused) {
285 self.dirty = true;
286 }
287 }
288
289 pub fn update_cursor_guide(&mut self, enabled: bool, color: [u8; 4]) {
291 self.cell_renderer.update_cursor_guide(enabled, color);
292 self.dirty = true;
293 }
294
295 pub fn update_cursor_shadow(
298 &mut self,
299 enabled: bool,
300 color: [u8; 4],
301 offset: [f32; 2],
302 blur: f32,
303 ) {
304 let scale = self.cell_renderer.scale_factor;
305 let physical_offset = [offset[0] * scale, offset[1] * scale];
306 let physical_blur = blur * scale;
307 self.cell_renderer
308 .update_cursor_shadow(enabled, color, physical_offset, physical_blur);
309 self.dirty = true;
310 }
311
312 pub fn update_cursor_boost(&mut self, intensity: f32, color: [u8; 3]) {
314 self.cell_renderer.update_cursor_boost(intensity, color);
315 self.dirty = true;
316 }
317
318 pub fn update_unfocused_cursor_style(&mut self, style: par_term_config::UnfocusedCursorStyle) {
320 self.cell_renderer.update_unfocused_cursor_style(style);
321 self.dirty = true;
322 }
323
324 pub fn update_command_separator(
327 &mut self,
328 enabled: bool,
329 logical_thickness: f32,
330 opacity: f32,
331 exit_color: bool,
332 color: [u8; 3],
333 ) {
334 let physical_thickness = logical_thickness * self.cell_renderer.scale_factor;
335 self.cell_renderer.update_command_separator(
336 enabled,
337 physical_thickness,
338 opacity,
339 exit_color,
340 color,
341 );
342 self.dirty = true;
343 }
344
345 pub fn set_separator_marks(&mut self, marks: Vec<SeparatorMark>) {
347 if self.cell_renderer.set_separator_marks(marks) {
348 self.dirty = true;
349 }
350 }
351
352 pub fn set_gutter_indicators(&mut self, indicators: Vec<(usize, [f32; 4])>) {
354 self.cell_renderer.set_gutter_indicators(indicators);
355 self.dirty = true;
356 }
357
358 pub fn set_transparency_affects_only_default_background(&mut self, value: bool) {
361 self.cell_renderer
362 .set_transparency_affects_only_default_background(value);
363 self.dirty = true;
364 }
365
366 pub fn set_keep_text_opaque(&mut self, value: bool) {
369 self.cell_renderer.set_keep_text_opaque(value);
370
371 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
373 custom_shader.set_keep_text_opaque(value);
374 }
375
376 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
378 cursor_shader.set_keep_text_opaque(value);
379 }
380
381 self.dirty = true;
382 }
383
384 pub fn set_link_underline_style(&mut self, style: par_term_config::LinkUnderlineStyle) {
385 self.cell_renderer.set_link_underline_style(style);
386 self.dirty = true;
387 }
388
389 pub fn set_cursor_shader_disabled_for_alt_screen(&mut self, disabled: bool) {
394 if self.cursor_shader_disabled_for_alt_screen != disabled {
395 log::debug!("[cursor-shader] Alt-screen disable set to {}", disabled);
396 self.cursor_shader_disabled_for_alt_screen = disabled;
397 } else {
398 self.cursor_shader_disabled_for_alt_screen = disabled;
399 }
400 }
401
402 pub fn update_window_padding(&mut self, logical_padding: f32) -> Option<(usize, usize)> {
406 let physical_padding = logical_padding * self.cell_renderer.scale_factor;
407 let result = self.cell_renderer.update_window_padding(physical_padding);
408 self.graphics_renderer.update_cell_dimensions(
410 self.cell_renderer.cell_width(),
411 self.cell_renderer.cell_height(),
412 physical_padding,
413 );
414 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
416 custom_shader.update_cell_dimensions(
417 self.cell_renderer.cell_width(),
418 self.cell_renderer.cell_height(),
419 physical_padding,
420 );
421 }
422 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
424 cursor_shader.update_cell_dimensions(
425 self.cell_renderer.cell_width(),
426 self.cell_renderer.cell_height(),
427 physical_padding,
428 );
429 }
430 self.dirty = true;
431 result
432 }
433
434 pub fn set_background_image_enabled(
436 &mut self,
437 enabled: bool,
438 path: Option<&str>,
439 mode: par_term_config::BackgroundImageMode,
440 opacity: f32,
441 ) {
442 let path = if enabled { path } else { None };
443 self.cell_renderer.set_background_image(path, mode, opacity);
444
445 self.sync_background_texture_to_shader();
447
448 self.dirty = true;
449 }
450
451 pub fn set_background(
455 &mut self,
456 mode: par_term_config::BackgroundMode,
457 color: [u8; 3],
458 image_path: Option<&str>,
459 image_mode: par_term_config::BackgroundImageMode,
460 image_opacity: f32,
461 image_enabled: bool,
462 ) {
463 self.cell_renderer.set_background(
464 mode,
465 color,
466 image_path,
467 image_mode,
468 image_opacity,
469 image_enabled,
470 );
471
472 self.sync_background_texture_to_shader();
474
475 let is_solid_color = matches!(mode, par_term_config::BackgroundMode::Color);
477 let is_image_mode = matches!(mode, par_term_config::BackgroundMode::Image);
478 let normalized_color = color_u8_to_f32(color);
479
480 if let Some(ref mut cursor_shader) = self.cursor_shader_renderer {
482 let has_background_shader = self.custom_shader_renderer.is_some();
485
486 if has_background_shader {
487 cursor_shader.set_background_color([0.0, 0.0, 0.0], false);
489 cursor_shader.set_background_texture(self.cell_renderer.device(), None);
490 cursor_shader.update_use_background_as_channel0(self.cell_renderer.device(), false);
491 } else {
492 cursor_shader.set_background_color(normalized_color, is_solid_color);
493
494 if is_image_mode && image_enabled {
496 let bg_texture = self.cell_renderer.get_background_as_channel_texture();
497 cursor_shader.set_background_texture(self.cell_renderer.device(), bg_texture);
498 cursor_shader
499 .update_use_background_as_channel0(self.cell_renderer.device(), true);
500 } else {
501 cursor_shader.set_background_texture(self.cell_renderer.device(), None);
503 cursor_shader
504 .update_use_background_as_channel0(self.cell_renderer.device(), false);
505 }
506 }
507 }
508
509 if let Some(ref mut custom_shader) = self.custom_shader_renderer {
514 custom_shader.set_background_color(normalized_color, false);
515 }
516
517 self.dirty = true;
518 }
519
520 pub fn update_scrollbar_appearance(
523 &mut self,
524 logical_width: f32,
525 thumb_color: [f32; 4],
526 track_color: [f32; 4],
527 ) {
528 let physical_width = logical_width * self.cell_renderer.scale_factor;
529 self.cell_renderer
530 .update_scrollbar_appearance(physical_width, thumb_color, track_color);
531 self.last_scrollbar_state = (usize::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0);
534 self.dirty = true;
535 }
536
537 pub fn update_scrollbar_position(&mut self, position: &str) {
539 self.cell_renderer.update_scrollbar_position(position);
540 self.dirty = true;
541 }
542
543 pub fn update_background_image_opacity(&mut self, opacity: f32) {
545 self.cell_renderer.update_background_image_opacity(opacity);
546 self.dirty = true;
547 }
548
549 pub fn load_pane_background(&mut self, path: &str) -> Result<bool, crate::error::RenderError> {
552 self.cell_renderer.load_pane_background(path)
553 }
554
555 pub fn update_image_scaling_mode(&mut self, scaling_mode: par_term_config::ImageScalingMode) {
560 self.graphics_renderer
561 .update_scaling_mode(self.cell_renderer.device(), scaling_mode);
562 self.dirty = true;
563 }
564
565 pub fn update_image_preserve_aspect_ratio(&mut self, preserve: bool) {
567 self.graphics_renderer.set_preserve_aspect_ratio(preserve);
568 self.dirty = true;
569 }
570
571 pub fn needs_continuous_render(&self) -> bool {
576 let custom_needs = self
577 .custom_shader_renderer
578 .as_ref()
579 .is_some_and(|r| r.animation_enabled() || r.cursor_needs_animation());
580 let cursor_needs = self
581 .cursor_shader_renderer
582 .as_ref()
583 .is_some_and(|r| r.animation_enabled() || r.cursor_needs_animation());
584 custom_needs || cursor_needs
585 }
586}