use crate::app::window_state::WindowState;
pub(super) type DisplayActionHandler = fn(&mut WindowState) -> bool;
pub(super) static DISPLAY_ACTION_HANDLERS: &[(&str, DisplayActionHandler)] = &[
("increase_font_size", |s: &mut WindowState| {
s.config.rcu(|old| {
let mut new = (**old).clone();
new.font_size = (old.font_size + 1.0).min(72.0);
std::sync::Arc::new(new)
});
s.render_loop.pending_font_rebuild = true;
log::info!(
"Font size increased to {} via keybinding",
s.config.load().font_size
);
s.request_redraw();
true
}),
("decrease_font_size", |s: &mut WindowState| {
s.config.rcu(|old| {
let mut new = (**old).clone();
new.font_size = (old.font_size - 1.0).max(6.0);
std::sync::Arc::new(new)
});
s.render_loop.pending_font_rebuild = true;
log::info!(
"Font size decreased to {} via keybinding",
s.config.load().font_size
);
s.request_redraw();
true
}),
("reset_font_size", |s: &mut WindowState| {
s.config.rcu(|old| {
let mut new = (**old).clone();
new.font_size = 14.0;
std::sync::Arc::new(new)
});
s.render_loop.pending_font_rebuild = true;
log::info!("Font size reset to default (14.0) via keybinding");
s.request_redraw();
true
}),
("cycle_cursor_style", cycle_cursor_style),
("move_tab_left", |s: &mut WindowState| {
s.move_tab_left();
log::debug!("Moved tab left via keybinding");
true
}),
("move_tab_right", |s: &mut WindowState| {
s.move_tab_right();
log::debug!("Moved tab right via keybinding");
true
}),
("switch_to_tab_1", |s: &mut WindowState| {
s.switch_to_tab_index(1);
true
}),
("switch_to_tab_2", |s: &mut WindowState| {
s.switch_to_tab_index(2);
true
}),
("switch_to_tab_3", |s: &mut WindowState| {
s.switch_to_tab_index(3);
true
}),
("switch_to_tab_4", |s: &mut WindowState| {
s.switch_to_tab_index(4);
true
}),
("switch_to_tab_5", |s: &mut WindowState| {
s.switch_to_tab_index(5);
true
}),
("switch_to_tab_6", |s: &mut WindowState| {
s.switch_to_tab_index(6);
true
}),
("switch_to_tab_7", |s: &mut WindowState| {
s.switch_to_tab_index(7);
true
}),
("switch_to_tab_8", |s: &mut WindowState| {
s.switch_to_tab_index(8);
true
}),
("switch_to_tab_9", |s: &mut WindowState| {
s.switch_to_tab_index(9);
true
}),
("toggle_throughput_mode", |s: &mut WindowState| {
s.config.rcu(|old| {
let mut new = (**old).clone();
new.rendering.maximize_throughput = !old.rendering.maximize_throughput;
std::sync::Arc::new(new)
});
let message = if s.config.load().rendering.maximize_throughput {
"Throughput Mode: ON"
} else {
"Throughput Mode: OFF"
};
s.show_toast(message);
log::info!(
"Throughput mode {}",
if s.config.load().rendering.maximize_throughput {
"enabled"
} else {
"disabled"
}
);
true
}),
("reopen_closed_tab", |s: &mut WindowState| {
s.reopen_closed_tab();
true
}),
("save_arrangement", |s: &mut WindowState| {
s.overlay_state.open_settings_window_requested = true;
s.request_redraw();
log::info!("Save arrangement requested via keybinding");
true
}),
("ssh_quick_connect", |s: &mut WindowState| {
s.overlay_ui.ssh_connect_ui.open(
s.config.load().ssh.enable_mdns_discovery,
s.config.load().ssh.mdns_scan_timeout_secs,
);
s.request_redraw();
log::info!("SSH Quick Connect opened via keybinding");
true
}),
("reload_dynamic_profiles", |s: &mut WindowState| {
s.overlay_state.reload_dynamic_profiles_requested = true;
s.request_redraw();
log::info!("Dynamic profiles reload requested via keybinding");
true
}),
];
fn cycle_cursor_style(s: &mut WindowState) -> bool {
use crate::config::CursorStyle;
use par_term_emu_core_rust::cursor::CursorStyle as TermCursorStyle;
s.config.rcu(|old| {
let mut new = (**old).clone();
new.cursor.cursor_style = match old.cursor.cursor_style {
CursorStyle::Block => CursorStyle::Beam,
CursorStyle::Beam => CursorStyle::Underline,
CursorStyle::Underline => CursorStyle::Block,
};
std::sync::Arc::new(new)
});
s.invalidate_tab_cache();
s.focus_state.needs_redraw = true;
log::info!(
"Cycled cursor style to {:?} via keybinding",
s.config.load().cursor.cursor_style
);
let term_style = if s.config.load().cursor.cursor_blink {
match s.config.load().cursor.cursor_style {
CursorStyle::Block => TermCursorStyle::BlinkingBlock,
CursorStyle::Beam => TermCursorStyle::BlinkingBar,
CursorStyle::Underline => TermCursorStyle::BlinkingUnderline,
}
} else {
match s.config.load().cursor.cursor_style {
CursorStyle::Block => TermCursorStyle::SteadyBlock,
CursorStyle::Beam => TermCursorStyle::SteadyBar,
CursorStyle::Underline => TermCursorStyle::SteadyUnderline,
}
};
if let Some(tab) = s.tab_manager.active_tab()
&& let Ok(mut term) = tab.terminal.try_write()
{
term.set_cursor_style(term_style);
}
true
}
impl WindowState {
pub(crate) fn execute_display_keybinding_action(&mut self, action: &str) -> Option<bool> {
let (_, handler) = DISPLAY_ACTION_HANDLERS
.iter()
.find(|(name, _)| *name == action)?;
Some(handler(self))
}
}