par_term/app/tab_ops/
tab_reopen.rs1use std::sync::Arc;
11
12use super::super::window_state::WindowState;
13
14impl WindowState {
15 pub fn reopen_closed_tab(&mut self) {
17 if self.config.load().session_restore.session_undo_timeout_secs > 0 {
19 let timeout = std::time::Duration::from_secs(
20 self.config.load().session_restore.session_undo_timeout_secs as u64,
21 );
22 let now = std::time::Instant::now();
23 self.overlay_state
24 .closed_tabs
25 .retain(|info| now.duration_since(info.closed_at) < timeout);
26 }
27
28 let info = match self.overlay_state.closed_tabs.pop_front() {
29 Some(info) => info,
30 None => {
31 self.show_toast("No recently closed tabs");
32 return;
33 }
34 };
35
36 if self.config.load().tabs.max_tabs > 0
38 && self.tab_manager.tab_count() >= self.config.load().tabs.max_tabs
39 {
40 log::warn!(
41 "Cannot reopen tab: max_tabs limit ({}) reached",
42 self.config.load().tabs.max_tabs
43 );
44 self.show_toast("Cannot reopen tab: max tabs limit reached");
45 self.overlay_state.closed_tabs.push_front(info);
47 return;
48 }
49
50 let old_tab_count = self.tab_manager.tab_count();
52
53 if let Some(hidden_tab) = info.hidden_tab {
54 let tab_id = self.tab_manager.insert_tab_at(hidden_tab, info.index);
62
63 self.handle_tab_bar_resize_after_add(old_tab_count, tab_id);
65
66 if let Some(window) = &self.window
68 && let Some(tab) = self.tab_manager.get_tab_mut(tab_id)
69 {
70 tab.start_refresh_task(
71 Arc::clone(&self.runtime),
72 Arc::clone(window),
73 self.config.load().rendering.max_fps,
74 self.config.load().power.inactive_tab_fps,
75 );
76
77 tab.active_cache_mut().cells = None;
79
80 if let Some(renderer) = &self.renderer
83 && let Ok(mut term) = tab.terminal.try_write()
84 {
85 let (cols, rows) = renderer.grid_size();
86 let cell_width = renderer.cell_width();
87 let cell_height = renderer.cell_height();
88 let width_px = (cols as f32 * cell_width) as usize;
89 let height_px = (rows as f32 * cell_height) as usize;
90 term.set_cell_dimensions(cell_width as u32, cell_height as u32);
91 if let Err(e) = term.resize_with_pixels(cols, rows, width_px, height_px) {
92 crate::debug_error!(
93 "TERMINAL",
94 "resize_with_pixels failed (reopen_preserved): {e}"
95 );
96 }
97 }
98 }
99
100 self.play_alert_sound(crate::config::AlertEvent::NewTab);
101 self.show_toast("Tab restored (session preserved)");
102 self.focus_state.needs_redraw = true;
103 self.request_redraw();
104 } else {
105 let grid_size = self.renderer.as_ref().map(|r| r.grid_size());
107
108 match self.tab_manager.new_tab_with_cwd(
109 &self.config.load(),
110 Arc::clone(&self.runtime),
111 info.cwd,
112 grid_size,
113 ) {
114 Ok(tab_id) => {
115 self.handle_tab_bar_resize_after_add(old_tab_count, tab_id);
117
118 if let Some(tab) = self.tab_manager.get_tab_mut(tab_id) {
120 if !info.has_default_title {
121 tab.set_title(&info.title);
122 }
123 tab.custom_color = info.custom_color;
124 }
125
126 self.tab_manager.move_tab_to_index(tab_id, info.index);
128
129 if let Some(window) = &self.window
131 && let Some(tab) = self.tab_manager.get_tab_mut(tab_id)
132 {
133 tab.start_refresh_task(
134 Arc::clone(&self.runtime),
135 Arc::clone(window),
136 self.config.load().rendering.max_fps,
137 self.config.load().power.inactive_tab_fps,
138 );
139
140 if let Some(renderer) = &self.renderer
143 && let Ok(mut term) = tab.terminal.try_write()
144 {
145 let (cols, rows) = renderer.grid_size();
146 let cell_width = renderer.cell_width();
147 let cell_height = renderer.cell_height();
148 let width_px = (cols as f32 * cell_width) as usize;
149 let height_px = (rows as f32 * cell_height) as usize;
150 term.set_cell_dimensions(cell_width as u32, cell_height as u32);
151 if let Err(e) = term.resize_with_pixels(cols, rows, width_px, height_px)
152 {
153 crate::debug_error!(
154 "TERMINAL",
155 "resize_with_pixels failed (reopen_cwd): {e}"
156 );
157 }
158 }
159 }
160
161 if let Some(pane_layout) = &info.pane_layout
163 && let Some(tab) = self.tab_manager.get_tab_mut(tab_id)
164 {
165 tab.restore_pane_layout(
166 pane_layout,
167 &self.config.load(),
168 Arc::clone(&self.runtime),
169 );
170 if let Some(window) = &self.window
172 && let Some(tab) = self.tab_manager.get_tab_mut(tab_id)
173 {
174 tab.start_pane_refresh_tasks(
175 Arc::clone(&self.runtime),
176 Arc::clone(window),
177 self.config.load().rendering.max_fps,
178 self.config.load().power.inactive_tab_fps,
179 );
180 }
181 }
182
183 self.play_alert_sound(crate::config::AlertEvent::NewTab);
184 self.show_toast("Tab restored");
185 self.focus_state.needs_redraw = true;
186 self.request_redraw();
187 }
188 Err(e) => {
189 log::error!("Failed to reopen closed tab: {}", e);
190 self.show_toast("Failed to reopen tab");
191 }
192 }
193 }
194 }
195
196 pub(super) fn handle_tab_bar_resize_after_add(
199 &mut self,
200 old_tab_count: usize,
201 new_tab_id: crate::tab::TabId,
202 ) {
203 let new_tab_count = self.tab_manager.tab_count();
204 let old_tab_bar_height = self
205 .tab_bar_ui
206 .get_height(old_tab_count, &self.config.load());
207 let new_tab_bar_height = self
208 .tab_bar_ui
209 .get_height(new_tab_count, &self.config.load());
210 let old_tab_bar_width = self
211 .tab_bar_ui
212 .get_width(old_tab_count, &self.config.load());
213 let new_tab_bar_width = self
214 .tab_bar_ui
215 .get_width(new_tab_count, &self.config.load());
216
217 if ((new_tab_bar_height - old_tab_bar_height).abs() > 0.1
218 || (new_tab_bar_width - old_tab_bar_width).abs() > 0.1)
219 && let Some(renderer) = &mut self.renderer
220 && let Some((new_cols, new_rows)) = Self::apply_tab_bar_offsets_for_position(
221 self.config.load().tabs.tab_bar_position,
222 renderer,
223 new_tab_bar_height,
224 new_tab_bar_width,
225 )
226 {
227 let cell_width = renderer.cell_width();
228 let cell_height = renderer.cell_height();
229 let width_px = (new_cols as f32 * cell_width) as usize;
230 let height_px = (new_rows as f32 * cell_height) as usize;
231
232 for tab in self.tab_manager.tabs_mut() {
233 if tab.id != new_tab_id {
234 if let Ok(mut term) = tab.terminal.try_write() {
237 term.set_cell_dimensions(cell_width as u32, cell_height as u32);
238 if let Err(e) =
239 term.resize_with_pixels(new_cols, new_rows, width_px, height_px)
240 {
241 crate::debug_error!(
242 "TERMINAL",
243 "resize_with_pixels failed (tab_bar_resize): {e}"
244 );
245 }
246 }
247 tab.active_cache_mut().cells = None;
248 }
249 }
250 }
251 }
252}