diff --git a/src-tauri/src/config/settings/terminal.rs b/src-tauri/src/config/settings/terminal.rs index e5fa73ef..7b2a7ef7 100644 --- a/src-tauri/src/config/settings/terminal.rs +++ b/src-tauri/src/config/settings/terminal.rs @@ -52,6 +52,8 @@ pub struct TerminalSettings { #[serde(default = "default_keep_alive")] pub keep_alive_interval: u32, #[serde(default)] + pub font_size_delta: f64, + #[serde(default)] pub x11_display: String, #[serde(default = "default_false")] pub hardware_acceleration: bool, @@ -91,6 +93,7 @@ impl Default for TerminalSettings { Self { scrollback_lines: default_scrollback(), keep_alive_interval: default_keep_alive(), + font_size_delta: 0.0, x11_display: String::new(), hardware_acceleration: false, keyword_highlights_enabled: false, diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index cdad128e..a9ee2518 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -49,9 +49,9 @@ import { invoke } from "@/lib/invoke"; import { logger } from "@/lib/logger"; import { isMacOS } from "@/lib/platform"; import { - DEFAULT_TERMINAL_FONT_SIZE, - decreaseTerminalFontSize, - increaseTerminalFontSize, + decreaseTerminalFontSizeDelta, + increaseTerminalFontSizeDelta, + resetTerminalFontSizeDelta, } from "@/lib/terminalFontSize"; import { getActivePane, getTabDisplayName } from "@/lib/workspaceTabs"; import type { SavedConnection, Tab } from "@/types/global"; @@ -208,19 +208,25 @@ export default function Header({ const handleZoom = (delta: number) => { updateAppSettings((prev) => ({ - appearance: { - ...prev.appearance, - font_size: + terminal: { + ...prev.terminal, + font_size_delta: delta > 0 - ? increaseTerminalFontSize(prev.appearance.font_size) - : decreaseTerminalFontSize(prev.appearance.font_size), + ? increaseTerminalFontSizeDelta( + prev.appearance.font_size, + prev.terminal.font_size_delta, + ) + : decreaseTerminalFontSizeDelta( + prev.appearance.font_size, + prev.terminal.font_size_delta, + ), }, })); }; const handleResetZoom = () => updateAppSettings((prev) => ({ - appearance: { ...prev.appearance, font_size: DEFAULT_TERMINAL_FONT_SIZE }, + terminal: { ...prev.terminal, font_size_delta: resetTerminalFontSizeDelta() }, })); const menuKeys = [ diff --git a/src/components/terminal/XTerminal.tsx b/src/components/terminal/XTerminal.tsx index d33a90f7..ae069acf 100644 --- a/src/components/terminal/XTerminal.tsx +++ b/src/components/terminal/XTerminal.tsx @@ -48,6 +48,7 @@ import { } from "@/lib/shortcutRegistry"; import { registerTerminalContextProvider } from "@/lib/terminalContext"; import { getTerminalDropOverlayCopy, handleTerminalFileDrop } from "@/lib/terminalFileDrop"; +import { resolveTerminalFontSize } from "@/lib/terminalFontSize"; import { applyTerminalInputData, applyTerminalInputPreview, @@ -405,7 +406,7 @@ export default function XTerminal({ scrollback: terminalSettings.scrollback_lines, cursorBlink: appearance.cursor_blink, cursorStyle: appearance.cursor_style as "block" | "underline" | "bar", - fontSize: appearance.font_size, + fontSize: resolveTerminalFontSize(appearance.font_size, terminalSettings.font_size_delta), fontFamily: appearance.font_family, minimumContrastRatio: appearance.minimum_contrast_ratio, wordSeparator: interaction.word_separators, diff --git a/src/context/AppContext.tsx b/src/context/AppContext.tsx index f1b11aeb..bce89a04 100644 --- a/src/context/AppContext.tsx +++ b/src/context/AppContext.tsx @@ -236,6 +236,7 @@ const DEFAULT_APP_SETTINGS: AppSettings = { terminal: { scrollback_lines: 10000, keep_alive_interval: 60, + font_size_delta: 0, x11_display: "", hardware_acceleration: false, keyword_highlights_enabled: false, diff --git a/src/context/ChildAppProvider.tsx b/src/context/ChildAppProvider.tsx index 663d9164..4a667a75 100644 --- a/src/context/ChildAppProvider.tsx +++ b/src/context/ChildAppProvider.tsx @@ -62,6 +62,7 @@ const DEFAULT_APP_SETTINGS: AppSettings = { terminal: { scrollback_lines: 10000, keep_alive_interval: 60, + font_size_delta: 0, x11_display: "", hardware_acceleration: false, keyword_highlights_enabled: false, diff --git a/src/hooks/useTerminalSettings.ts b/src/hooks/useTerminalSettings.ts index 3c965b92..dade6d75 100644 --- a/src/hooks/useTerminalSettings.ts +++ b/src/hooks/useTerminalSettings.ts @@ -3,6 +3,7 @@ import { WebglAddon } from "@xterm/addon-webgl"; import type { Terminal } from "@xterm/xterm"; import { useCallback, useEffect, useRef } from "react"; import { isTerminalTransparencyEnabled } from "@/lib/backgroundImage"; +import { resolveTerminalFontSize } from "@/lib/terminalFontSize"; import type { TerminalColors } from "@/lib/themes"; import { installMacImeCompatibilityPatch } from "@/lib/xtermMacImeCompatibility"; import type { AppSettings } from "@/types/global"; @@ -95,7 +96,10 @@ export function useTerminalSettings( if (terminalRef.current) { const options = terminalRef.current.options; options.fontFamily = appearance.font_family; - options.fontSize = appearance.font_size; + options.fontSize = resolveTerminalFontSize( + appearance.font_size, + terminalSettings.font_size_delta, + ); options.cursorBlink = appearance.cursor_blink; options.cursorStyle = appearance.cursor_style as "block" | "underline" | "bar"; options.minimumContrastRatio = appearance.minimum_contrast_ratio; @@ -106,7 +110,13 @@ export function useTerminalSettings( requestAnimationFrame(() => fitAddonRef.current?.fit()); } } - }, [appearance, terminalRef, fitAddonRef, scheduleTextureRefresh]); + }, [ + appearance, + terminalSettings.font_size_delta, + terminalRef, + fitAddonRef, + scheduleTextureRefresh, + ]); // React to terminal core settings changes: scrollback useEffect(() => { diff --git a/src/hooks/useTerminalZoom.ts b/src/hooks/useTerminalZoom.ts index b033dda2..97dbc13b 100644 --- a/src/hooks/useTerminalZoom.ts +++ b/src/hooks/useTerminalZoom.ts @@ -2,9 +2,9 @@ import { useCallback, useEffect, useRef } from "react"; import { resolveShortcutKeys } from "@/hooks/useShortcutMap"; import { matchesKeyEvent } from "@/lib/shortcutRegistry"; import { - DEFAULT_TERMINAL_FONT_SIZE, - decreaseTerminalFontSize, - increaseTerminalFontSize, + decreaseTerminalFontSizeDelta, + increaseTerminalFontSizeDelta, + resetTerminalFontSizeDelta, } from "@/lib/terminalFontSize"; import type { AppSettings } from "@/types/global"; @@ -22,25 +22,31 @@ export function useTerminalZoom( const handleZoomIn = useCallback(() => { updateAppSettings((prev) => ({ - appearance: { - ...prev.appearance, - font_size: increaseTerminalFontSize(prev.appearance.font_size), + terminal: { + ...prev.terminal, + font_size_delta: increaseTerminalFontSizeDelta( + prev.appearance.font_size, + prev.terminal.font_size_delta, + ), }, })); }, [updateAppSettings]); const handleZoomOut = useCallback(() => { updateAppSettings((prev) => ({ - appearance: { - ...prev.appearance, - font_size: decreaseTerminalFontSize(prev.appearance.font_size), + terminal: { + ...prev.terminal, + font_size_delta: decreaseTerminalFontSizeDelta( + prev.appearance.font_size, + prev.terminal.font_size_delta, + ), }, })); }, [updateAppSettings]); const handleResetZoom = useCallback(() => { updateAppSettings((prev) => ({ - appearance: { ...prev.appearance, font_size: DEFAULT_TERMINAL_FONT_SIZE }, + terminal: { ...prev.terminal, font_size_delta: resetTerminalFontSizeDelta() }, })); }, [updateAppSettings]); diff --git a/src/lib/terminalFontSize.ts b/src/lib/terminalFontSize.ts index ce1e7cce..1bb58f82 100644 --- a/src/lib/terminalFontSize.ts +++ b/src/lib/terminalFontSize.ts @@ -7,6 +7,26 @@ export function clampTerminalFontSize(fontSize: number): number { return Math.max(MIN_TERMINAL_FONT_SIZE, Math.min(MAX_TERMINAL_FONT_SIZE, Math.round(fontSize))); } +export function resolveTerminalFontSize(baseFontSize: number, fontSizeDelta = 0): number { + return clampTerminalFontSize(baseFontSize + fontSizeDelta); +} + +export function increaseTerminalFontSizeDelta(baseFontSize: number, fontSizeDelta = 0): number { + return ( + resolveTerminalFontSize(baseFontSize, fontSizeDelta + TERMINAL_FONT_SIZE_STEP) - baseFontSize + ); +} + +export function decreaseTerminalFontSizeDelta(baseFontSize: number, fontSizeDelta = 0): number { + return ( + resolveTerminalFontSize(baseFontSize, fontSizeDelta - TERMINAL_FONT_SIZE_STEP) - baseFontSize + ); +} + +export function resetTerminalFontSizeDelta(): number { + return 0; +} + export function increaseTerminalFontSize(fontSize: number): number { return clampTerminalFontSize(fontSize + TERMINAL_FONT_SIZE_STEP); } diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 90a06c4e..58b3db34 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -565,6 +565,7 @@ export type KeywordHighlightBuiltinRuleSettings = Record; export interface TerminalSettings { scrollback_lines: number; keep_alive_interval: number; + font_size_delta: number; x11_display?: string; hardware_acceleration: boolean; keyword_highlights_enabled: boolean;