par_term/terminal/
graphics.rs

1use super::TerminalManager;
2use par_term_emu_core_rust::graphics::TerminalGraphic;
3
4impl TerminalManager {
5    /// Get all graphics (Sixel, iTerm2, Kitty)
6    /// Returns a vector of cloned TerminalGraphic objects for rendering
7    #[allow(dead_code)]
8    pub fn get_graphics(&self) -> Vec<TerminalGraphic> {
9        let pty = self.pty_session.lock();
10        let terminal = pty.terminal();
11        let term = terminal.lock();
12        let graphics: Vec<_> = term.all_graphics().to_vec();
13        if !graphics.is_empty() {
14            debug_info!(
15                "TERMINAL",
16                "Returning {} graphics from core library",
17                graphics.len()
18            );
19            for (i, g) in graphics.iter().enumerate() {
20                debug_trace!(
21                    "TERMINAL",
22                    "  [{}] protocol={:?}, pos=({},{}), size={}x{}",
23                    i,
24                    g.protocol,
25                    g.position.0,
26                    g.position.1,
27                    g.width,
28                    g.height
29                );
30            }
31        }
32        graphics
33    }
34
35    /// Get graphics at a specific row
36    #[allow(dead_code)]
37    pub fn get_graphics_at_row(&self, row: usize) -> Vec<TerminalGraphic> {
38        let pty = self.pty_session.lock();
39        let terminal = pty.terminal();
40        let term = terminal.lock();
41        term.graphics_at_row(row)
42            .iter()
43            .map(|g| (*g).clone())
44            .collect()
45    }
46
47    /// Get total graphics count
48    #[allow(dead_code)]
49    pub fn graphics_count(&self) -> usize {
50        let pty = self.pty_session.lock();
51        let terminal = pty.terminal();
52        let term = terminal.lock();
53        term.graphics_count()
54    }
55
56    /// Get all scrollback graphics
57    pub fn get_scrollback_graphics(&self) -> Vec<TerminalGraphic> {
58        let pty = self.pty_session.lock();
59        let terminal = pty.terminal();
60        let term = terminal.lock();
61        term.all_scrollback_graphics().to_vec()
62    }
63
64    /// Update animations and return true if any frames changed
65    ///
66    /// This should be called periodically (e.g., in the redraw loop) to advance
67    /// animation frames based on timing. Returns true if any animation advanced
68    /// to a new frame, indicating that a redraw is needed.
69    pub fn update_animations(&self) -> bool {
70        let pty = self.pty_session.lock();
71        let terminal = pty.terminal();
72        let mut term = terminal.lock();
73        let changed_images = term.graphics_store_mut().update_animations();
74        !changed_images.is_empty()
75    }
76
77    /// Get all graphics with current animation frames
78    ///
79    /// For animated graphics, returns the current frame based on animation state.
80    /// For static graphics, returns the original graphic unchanged.
81    pub fn get_graphics_with_animations(&self) -> Vec<TerminalGraphic> {
82        let pty = self.pty_session.lock();
83        let terminal = pty.terminal();
84        let term = terminal.lock();
85
86        let mut graphics = Vec::new();
87
88        // First, collect all base graphics
89        let base_graphics: Vec<_> = term.all_graphics().to_vec();
90
91        debug_log!(
92            "TERMINAL",
93            "get_graphics_with_animations() - base_graphics count: {}",
94            base_graphics.len()
95        );
96
97        // Then, for each graphic, check if it has an animation and get current frame
98        for (idx, graphic) in base_graphics.iter().enumerate() {
99            debug_trace!(
100                "TERMINAL",
101                "Processing graphic {} - pos=({},{}), size={}x{}, kitty_id={:?}",
102                idx,
103                graphic.position.0,
104                graphic.position.1,
105                graphic.width,
106                graphic.height,
107                graphic.kitty_image_id
108            );
109
110            // Check if this graphic has an active animation
111            if let Some(image_id) = graphic.kitty_image_id
112                && let Some(anim) = term.graphics_store().get_animation(image_id)
113                && let Some(current_frame) = anim.current_frame()
114            {
115                // Create a graphic from the current animation frame
116                let mut animated_graphic = graphic.clone();
117                animated_graphic.pixels = current_frame.pixels.clone();
118                animated_graphic.width = current_frame.width;
119                animated_graphic.height = current_frame.height;
120
121                debug_info!(
122                    "TERMINAL",
123                    "Using animated frame {} for image {}",
124                    anim.current_frame,
125                    image_id
126                );
127
128                graphics.push(animated_graphic);
129                continue;
130            }
131            // Not animated or no current frame - use original graphic
132            debug_trace!("TERMINAL", "Using static graphic {}", idx);
133            graphics.push(graphic.clone());
134        }
135
136        debug_log!("TERMINAL", "Returning {} graphics total", graphics.len());
137        graphics
138    }
139}