1package config
2
3// Config represents the complete configuration for dumber.
4type Config struct {
5 Database DatabaseConfig `mapstructure:"database" yaml:"database" toml:"database"`
6 History HistoryConfig `mapstructure:"history" yaml:"history" toml:"history"`
7 SearchShortcuts map[string]SearchShortcut `mapstructure:"search_shortcuts" yaml:"search_shortcuts" toml:"search_shortcuts"`
8 // DefaultSearchEngine is the URL template for the default search engine (must contain %s placeholder)
9 DefaultSearchEngine string `mapstructure:"default_search_engine" yaml:"default_search_engine" toml:"default_search_engine"`
10 Dmenu DmenuConfig `mapstructure:"dmenu" yaml:"dmenu" toml:"dmenu"`
11 Logging LoggingConfig `mapstructure:"logging" yaml:"logging" toml:"logging"`
12 Appearance AppearanceConfig `mapstructure:"appearance" yaml:"appearance" toml:"appearance"`
13 Debug DebugConfig `mapstructure:"debug" yaml:"debug" toml:"debug"`
14 // DefaultWebpageZoom sets the default zoom level for pages without saved zoom settings (1.0 = 100%, 1.2 = 120%)
15 DefaultWebpageZoom float64 `mapstructure:"default_webpage_zoom" yaml:"default_webpage_zoom" toml:"default_webpage_zoom"`
16 // DefaultUIScale sets the default UI scale for GTK widgets (1.0 = 100%, 2.0 = 200%)
17 DefaultUIScale float64 `mapstructure:"default_ui_scale" yaml:"default_ui_scale" toml:"default_ui_scale"`
18 // Workspace defines workspace, pane, and tab handling behavior.
19 Workspace WorkspaceConfig `mapstructure:"workspace" yaml:"workspace" toml:"workspace"`
20 // Session controls session persistence and restoration.
21 Session SessionConfig `mapstructure:"session" yaml:"session" toml:"session"`
22 // ContentFiltering controls ad blocking and content filtering
23 ContentFiltering ContentFilteringConfig `mapstructure:"content_filtering" yaml:"content_filtering" toml:"content_filtering"`
24 // Clipboard controls clipboard-related behavior
25 Clipboard ClipboardConfig `mapstructure:"clipboard" yaml:"clipboard" toml:"clipboard"`
26 // Omnibox controls the omnibox behavior (initial history display)
27 Omnibox OmniboxConfig `mapstructure:"omnibox" yaml:"omnibox" toml:"omnibox"`
28 // Rendering controls WebKit, GTK and compositor behavior.
29 Rendering RenderingConfig `mapstructure:"rendering" yaml:"rendering" toml:"rendering"`
30 // Media controls video playback and hardware acceleration
31 Media MediaConfig `mapstructure:"media" yaml:"media" toml:"media"`
32 // Runtime configures optional runtime overrides (e.g., /opt prefix for WebKitGTK/GTK).
33 Runtime RuntimeConfig `mapstructure:"runtime" yaml:"runtime" toml:"runtime"`
34 // Performance holds internal performance tuning options (not exposed in UI).
35 Performance PerformanceConfig `mapstructure:"performance" yaml:"performance" toml:"performance"`
36 // Update controls automatic update checking and downloading.
37 Update UpdateConfig `mapstructure:"update" yaml:"update" toml:"update"`
38}
39
40// RenderingMode selects GPU vs CPU rendering.
41type RenderingMode string
42
43const (
44 RenderingModeAuto RenderingMode = "auto"
45 RenderingModeGPU RenderingMode = "gpu"
46 RenderingModeCPU RenderingMode = "cpu"
47)
48
49// GSKRendererMode controls the GTK Scene Kit renderer selection.
50type GSKRendererMode string
51
52const (
53 GSKRendererAuto GSKRendererMode = "auto"
54 GSKRendererOpenGL GSKRendererMode = "opengl"
55 GSKRendererVulkan GSKRendererMode = "vulkan"
56 GSKRendererCairo GSKRendererMode = "cairo"
57)
58
59// RenderingConfig controls WebKit and GTK/GSK rendering behavior.
60type RenderingConfig struct {
61 // Mode controls GPU/CPU rendering selection for WebKit (auto, gpu, cpu).
62 Mode RenderingMode `mapstructure:"mode" yaml:"mode" toml:"mode"`
63
64 // DisableDMABufRenderer disables DMA-BUF accelerated renderer.
65 // Env: WEBKIT_DISABLE_DMABUF_RENDERER
66 DisableDMABufRenderer bool `mapstructure:"disable_dmabuf_renderer" yaml:"disable_dmabuf_renderer" toml:"disable_dmabuf_renderer"`
67
68 // ForceCompositingMode forces accelerated compositing.
69 // Env: WEBKIT_FORCE_COMPOSITING_MODE
70 ForceCompositingMode bool `mapstructure:"force_compositing_mode" yaml:"force_compositing_mode" toml:"force_compositing_mode"`
71
72 // DisableCompositingMode disables accelerated compositing.
73 // Env: WEBKIT_DISABLE_COMPOSITING_MODE
74 DisableCompositingMode bool `mapstructure:"disable_compositing_mode" yaml:"disable_compositing_mode" toml:"disable_compositing_mode"`
75
76 // GSKRenderer overrides GTK Scene Kit renderer selection.
77 // Env: GSK_RENDERER
78 GSKRenderer GSKRendererMode `mapstructure:"gsk_renderer" yaml:"gsk_renderer" toml:"gsk_renderer"`
79
80 // DisableMipmaps disables mipmap generation.
81 // Env: GSK_GPU_DISABLE=mipmap
82 DisableMipmaps bool `mapstructure:"disable_mipmaps" yaml:"disable_mipmaps" toml:"disable_mipmaps"`
83
84 // PreferGL forces OpenGL over GLES.
85 // Env: GDK_DEBUG=gl-prefer-gl
86 PreferGL bool `mapstructure:"prefer_gl" yaml:"prefer_gl" toml:"prefer_gl"`
87
88 // DrawCompositingIndicators shows compositing layer borders and repaint counters.
89 DrawCompositingIndicators bool `mapstructure:"draw_compositing_indicators" yaml:"draw_compositing_indicators" toml:"draw_compositing_indicators"` //nolint:lll // struct tags exceed lll limit
90
91 // ShowFPS displays WebKit FPS counter.
92 // Env: WEBKIT_SHOW_FPS
93 ShowFPS bool `mapstructure:"show_fps" yaml:"show_fps" toml:"show_fps"`
94
95 // SampleMemory enables memory sampling.
96 // Env: WEBKIT_SAMPLE_MEMORY
97 SampleMemory bool `mapstructure:"sample_memory" yaml:"sample_memory" toml:"sample_memory"`
98
99 // DebugFrames enables frame timing debug output.
100 // Env: GDK_DEBUG=frames
101 DebugFrames bool `mapstructure:"debug_frames" yaml:"debug_frames" toml:"debug_frames"`
102}
103
104// HardwareDecodingMode controls video hardware acceleration.
105type HardwareDecodingMode string
106
107const (
108 // HardwareDecodingAuto lets GStreamer choose (hw preferred, sw fallback)
109 HardwareDecodingAuto HardwareDecodingMode = "auto"
110 // HardwareDecodingForce requires hardware decoding (fails if unavailable)
111 HardwareDecodingForce HardwareDecodingMode = "force"
112 // HardwareDecodingDisable uses software decoding only
113 HardwareDecodingDisable HardwareDecodingMode = "disable"
114)
115
116// GLRenderingMode controls OpenGL API selection for video rendering.
117type GLRenderingMode string
118
119const (
120 // GLRenderingModeAuto lets GStreamer choose the best GL API
121 GLRenderingModeAuto GLRenderingMode = "auto"
122 // GLRenderingModeGLES2 forces GLES2 (better for some mobile/embedded GPUs)
123 GLRenderingModeGLES2 GLRenderingMode = "gles2"
124 // GLRenderingModeGL3 forces OpenGL 3.x desktop
125 GLRenderingModeGL3 GLRenderingMode = "gl3"
126 // GLRenderingModeNone disables GL-based rendering
127 GLRenderingModeNone GLRenderingMode = "none"
128)
129
130// PerformanceProfile selects preset performance tuning settings.
131type PerformanceProfile string
132
133const (
134 // ProfileDefault uses WebKit defaults (no tuning applied).
135 ProfileDefault PerformanceProfile = "default"
136 // ProfileLite reduces resource usage for low-RAM systems.
137 ProfileLite PerformanceProfile = "lite"
138 // ProfileMax maximizes responsiveness for heavy pages (GitHub PRs, etc).
139 ProfileMax PerformanceProfile = "max"
140 // ProfileCustom allows full control over individual performance settings.
141 ProfileCustom PerformanceProfile = "custom"
142)
143
144// ThemeDefault is the default theme setting (follows system).
145const ThemeDefault = "default"
146
147const (
148 // ThemePreferDark explicitly selects dark theme.
149 ThemePreferDark = "prefer-dark"
150 // ThemePreferLight explicitly selects light theme.
151 ThemePreferLight = "prefer-light"
152)
153
154// MediaConfig holds video playback and hardware acceleration preferences.
155type MediaConfig struct {
156 // HardwareDecodingMode controls hardware vs software video decoding
157 // Values: "auto" (default), "force", "disable"
158 HardwareDecodingMode HardwareDecodingMode `mapstructure:"hardware_decoding" yaml:"hardware_decoding" toml:"hardware_decoding"`
159 // PreferAV1 prioritizes AV1 codec (most efficient) when available
160 PreferAV1 bool `mapstructure:"prefer_av1" yaml:"prefer_av1" toml:"prefer_av1"`
161 // ShowDiagnosticsOnStartup shows media capability warnings at startup
162 ShowDiagnosticsOnStartup bool `mapstructure:"show_diagnostics" yaml:"show_diagnostics" toml:"show_diagnostics"`
163 // ForceVSync forces vertical sync for video playback (may help with tearing)
164 ForceVSync bool `mapstructure:"force_vsync" yaml:"force_vsync" toml:"force_vsync"`
165 // GLRenderingMode controls OpenGL API selection for video rendering
166 // Values: "auto" (default), "gles2", "gl3", "none"
167 GLRenderingMode GLRenderingMode `mapstructure:"gl_rendering_mode" yaml:"gl_rendering_mode" toml:"gl_rendering_mode"`
168 // GStreamerDebugLevel sets GStreamer debug verbosity (0=off, 1-5=increasing verbosity)
169 GStreamerDebugLevel int `mapstructure:"gstreamer_debug_level" yaml:"gstreamer_debug_level" toml:"gstreamer_debug_level"`
170}
171
172// RuntimeConfig holds optional runtime overrides.
173type RuntimeConfig struct {
174 // Prefix points to a custom runtime prefix (e.g., /opt/webkitgtk).
175 // This is used to influence pkg-config lookup and dynamic library loading.
176 Prefix string `mapstructure:"prefix" yaml:"prefix" toml:"prefix"`
177}
178
179// DatabaseConfig holds database-related configuration.
180type DatabaseConfig struct {
181 Path string `mapstructure:"path" yaml:"path" toml:"path"`
182}
183
184// HistoryConfig holds history-related configuration.
185type HistoryConfig struct {
186 MaxEntries int `mapstructure:"max_entries" yaml:"max_entries" toml:"max_entries"`
187 RetentionPeriodDays int `mapstructure:"retention_period_days" yaml:"retention_period_days" toml:"retention_period_days"`
188 CleanupIntervalDays int `mapstructure:"cleanup_interval_days" yaml:"cleanup_interval_days" toml:"cleanup_interval_days"`
189}
190
191// PerformanceConfig holds internal performance tuning options.
192// These are not exposed in dumb://config UI but can be set in config file.
193type PerformanceConfig struct {
194 // Profile selects a preset performance configuration.
195 // Values: "default" (no tuning), "lite" (low RAM), "max" (heavy pages), "custom" (manual control)
196 // When profile is not "custom", individual tuning fields below are ignored and computed from the profile.
197 // Default: "default"
198 Profile PerformanceProfile `mapstructure:"profile" yaml:"profile" toml:"profile"`
199
200 // ZoomCacheSize is the number of domain zoom levels to cache in memory.
201 // Higher values reduce database queries but use more memory.
202 // Default: 256 domains (~20KB memory)
203 ZoomCacheSize int `mapstructure:"zoom_cache_size" yaml:"zoom_cache_size" toml:"zoom_cache_size"`
204
205 // WebViewPoolPrewarmCount is the number of WebViews to pre-create at startup.
206 // Higher values speed up initial tab creation but use more memory.
207 // Default: 4 (custom mode), computed from profile otherwise
208 WebViewPoolPrewarmCount int `mapstructure:"webview_pool_prewarm_count" yaml:"webview_pool_prewarm_count" toml:"webview_pool_prewarm_count"` //nolint:lll // struct tags must stay on one line
209
210 // --- Skia rendering threads (env vars) ---
211 // NOTE: Fields below only apply when Profile is "custom".
212 // SkiaCPUPaintingThreads sets WEBKIT_SKIA_CPU_PAINTING_THREADS.
213 // Default: 0 (unset, uses WebKit default)
214 SkiaCPUPaintingThreads int `mapstructure:"skia_cpu_painting_threads" yaml:"skia_cpu_painting_threads" toml:"skia_cpu_painting_threads"` //nolint:lll // struct tags must stay on one line
215
216 // SkiaGPUPaintingThreads sets WEBKIT_SKIA_GPU_PAINTING_THREADS.
217 // Default: -1 (unset). Value 0 disables GPU tile painting.
218 SkiaGPUPaintingThreads int `mapstructure:"skia_gpu_painting_threads" yaml:"skia_gpu_painting_threads" toml:"skia_gpu_painting_threads"` //nolint:lll // struct tags must stay on one line
219
220 // SkiaEnableCPURendering forces CPU rendering via WEBKIT_SKIA_ENABLE_CPU_RENDERING=1.
221 // Default: false
222 SkiaEnableCPURendering bool `mapstructure:"skia_enable_cpu_rendering" yaml:"skia_enable_cpu_rendering" toml:"skia_enable_cpu_rendering"` //nolint:lll // struct tags must stay on one line
223
224 // --- Web process memory pressure ---
225 // WebProcessMemoryLimitMB sets memory limit in MB for web processes.
226 // Default: 0 (unset, uses WebKit default: system RAM capped at 3GB)
227 WebProcessMemoryLimitMB int `mapstructure:"web_process_memory_limit_mb" yaml:"web_process_memory_limit_mb" toml:"web_process_memory_limit_mb"` //nolint:lll // struct tags must stay on one line
228
229 // WebProcessMemoryPollIntervalSec sets poll interval for memory checks.
230 // Default: 0 (unset, uses WebKit default: 30 seconds)
231 WebProcessMemoryPollIntervalSec float64 `mapstructure:"web_process_memory_poll_interval_sec" yaml:"web_process_memory_poll_interval_sec" toml:"web_process_memory_poll_interval_sec"` //nolint:lll // struct tags must stay on one line
232
233 // WebProcessMemoryConservativeThreshold sets threshold for conservative memory release.
234 // Valid: (0, 1). Default: 0 (unset, uses WebKit default: 0.33)
235 WebProcessMemoryConservativeThreshold float64 `mapstructure:"web_process_memory_conservative_threshold" yaml:"web_process_memory_conservative_threshold" toml:"web_process_memory_conservative_threshold"` //nolint:lll // struct tags must stay on one line
236
237 // WebProcessMemoryStrictThreshold sets threshold for strict memory release.
238 // Valid: (0, 1). Default: 0 (unset, uses WebKit default: 0.5)
239 WebProcessMemoryStrictThreshold float64 `mapstructure:"web_process_memory_strict_threshold" yaml:"web_process_memory_strict_threshold" toml:"web_process_memory_strict_threshold"` //nolint:lll // struct tags must stay on one line
240
241 // --- Network process memory pressure ---
242 // NetworkProcessMemoryLimitMB sets memory limit in MB for network process.
243 // Default: 0 (unset)
244 NetworkProcessMemoryLimitMB int `mapstructure:"network_process_memory_limit_mb" yaml:"network_process_memory_limit_mb" toml:"network_process_memory_limit_mb"` //nolint:lll // struct tags must stay on one line
245
246 // NetworkProcessMemoryPollIntervalSec sets poll interval for memory checks.
247 // Default: 0 (unset)
248 NetworkProcessMemoryPollIntervalSec float64 `mapstructure:"network_process_memory_poll_interval_sec" yaml:"network_process_memory_poll_interval_sec" toml:"network_process_memory_poll_interval_sec"` //nolint:lll // struct tags must stay on one line
249
250 // NetworkProcessMemoryConservativeThreshold sets threshold for conservative memory release.
251 // Valid: (0, 1). Default: 0 (unset)
252 NetworkProcessMemoryConservativeThreshold float64 `mapstructure:"network_process_memory_conservative_threshold" yaml:"network_process_memory_conservative_threshold" toml:"network_process_memory_conservative_threshold"` //nolint:lll // struct tags must stay on one line
253
254 // NetworkProcessMemoryStrictThreshold sets threshold for strict memory release.
255 // Valid: (0, 1). Default: 0 (unset)
256 NetworkProcessMemoryStrictThreshold float64 `mapstructure:"network_process_memory_strict_threshold" yaml:"network_process_memory_strict_threshold" toml:"network_process_memory_strict_threshold"` //nolint:lll // struct tags must stay on one line
257}
258
259// SearchShortcut represents a search shortcut configuration.
260type SearchShortcut struct {
261 URL string `mapstructure:"url" toml:"url" yaml:"url" json:"url"`
262 Description string `mapstructure:"description" toml:"description" yaml:"description" json:"description"`
263}
264
265// ShortcutURLs returns a simple map of shortcut keys to URL templates.
266// This is useful for passing to url.BuildSearchURL.
267func (c *Config) ShortcutURLs() map[string]string {
268 result := make(map[string]string, len(c.SearchShortcuts))
269 for key, shortcut := range c.SearchShortcuts {
270 result[key] = shortcut.URL
271 }
272 return result
273}
274
275// DmenuConfig holds dmenu/rofi integration configuration.
276type DmenuConfig struct {
277 MaxHistoryDays int `mapstructure:"max_history_days" yaml:"max_history_days" toml:"max_history_days"`
278 ShowVisitCount bool `mapstructure:"show_visit_count" yaml:"show_visit_count" toml:"show_visit_count"`
279 ShowLastVisited bool `mapstructure:"show_last_visited" yaml:"show_last_visited" toml:"show_last_visited"`
280 HistoryPrefix string `mapstructure:"history_prefix" yaml:"history_prefix" toml:"history_prefix"`
281 ShortcutPrefix string `mapstructure:"shortcut_prefix" yaml:"shortcut_prefix" toml:"shortcut_prefix"`
282 URLPrefix string `mapstructure:"url_prefix" yaml:"url_prefix" toml:"url_prefix"`
283 DateFormat string `mapstructure:"date_format" yaml:"date_format" toml:"date_format"`
284 SortByVisitCount bool `mapstructure:"sort_by_visit_count" yaml:"sort_by_visit_count" toml:"sort_by_visit_count"`
285}
286
287// LoggingConfig holds logging configuration.
288type LoggingConfig struct {
289 Level string `mapstructure:"level" yaml:"level" toml:"level"`
290 Format string `mapstructure:"format" yaml:"format" toml:"format"`
291 MaxAge int `mapstructure:"max_age" yaml:"max_age" toml:"max_age"`
292
293 // File output configuration
294 LogDir string `mapstructure:"log_dir" yaml:"log_dir" toml:"log_dir"`
295 EnableFileLog bool `mapstructure:"enable_file_log" yaml:"enable_file_log" toml:"enable_file_log"`
296
297 // Capture browser console to logs
298 CaptureConsole bool `mapstructure:"capture_console" yaml:"capture_console" toml:"capture_console" json:"capture_console"`
299}
300
301// AppearanceConfig holds UI/rendering preferences.
302type AppearanceConfig struct {
303 // Default fonts for pages that do not specify fonts.
304 SansFont string `mapstructure:"sans_font" yaml:"sans_font" toml:"sans_font"`
305 SerifFont string `mapstructure:"serif_font" yaml:"serif_font" toml:"serif_font"`
306 MonospaceFont string `mapstructure:"monospace_font" yaml:"monospace_font" toml:"monospace_font"`
307 // Default font size in CSS pixels (approx).
308 DefaultFontSize int `mapstructure:"default_font_size" yaml:"default_font_size" toml:"default_font_size"`
309 LightPalette ColorPalette `mapstructure:"light_palette" yaml:"light_palette" toml:"light_palette"`
310 DarkPalette ColorPalette `mapstructure:"dark_palette" yaml:"dark_palette" toml:"dark_palette"`
311 // ColorScheme controls the initial theme preference: "prefer-dark", "prefer-light", or "default" (follows system)
312 ColorScheme string `mapstructure:"color_scheme" yaml:"color_scheme" toml:"color_scheme"`
313}
314
315// ColorPalette contains semantic color tokens for light/dark themes.
316type ColorPalette struct {
317 Background string `mapstructure:"background" yaml:"background" toml:"background" json:"background"`
318 Surface string `mapstructure:"surface" yaml:"surface" toml:"surface" json:"surface"`
319 SurfaceVariant string `mapstructure:"surface_variant" yaml:"surface_variant" toml:"surface_variant" json:"surface_variant"`
320 Text string `mapstructure:"text" yaml:"text" toml:"text" json:"text"`
321 Muted string `mapstructure:"muted" yaml:"muted" toml:"muted" json:"muted"`
322 Accent string `mapstructure:"accent" yaml:"accent" toml:"accent" json:"accent"`
323 Border string `mapstructure:"border" yaml:"border" toml:"border" json:"border"`
324}
325
326// ContentFilteringConfig holds content filtering and ad blocking preferences
327type ContentFilteringConfig struct {
328 // Enabled controls whether ad blocking is active (default: true)
329 Enabled bool `mapstructure:"enabled" yaml:"enabled" toml:"enabled"`
330 // AutoUpdate controls whether filters are automatically updated (default: true)
331 AutoUpdate bool `mapstructure:"auto_update" yaml:"auto_update" toml:"auto_update"`
332 // Note: Filters are downloaded from bnema/ublock-webkit-filters GitHub releases
333 // Note: Whitelist is managed via database (content_whitelist table)
334}
335
336// ClipboardConfig holds clipboard-related behavior preferences
337type ClipboardConfig struct {
338 // AutoCopyOnSelection automatically copies selected text to clipboard (zellij-style).
339 // When enabled, selecting text in a webview immediately copies it to clipboard.
340 // Does not apply to text selection in input fields or textareas.
341 // Default: true
342 AutoCopyOnSelection bool `mapstructure:"auto_copy_on_selection" yaml:"auto_copy_on_selection" toml:"auto_copy_on_selection" json:"autoCopyOnSelection"` //nolint:lll // struct tags must stay on one line
343}
344
345// OmniboxConfig holds omnibox behavior preferences
346type OmniboxConfig struct {
347 // InitialBehavior controls what to show when omnibox opens with empty input
348 // Values: "recent" (recent visits), "most_visited" (most visited sites), "none" (nothing)
349 InitialBehavior string `mapstructure:"initial_behavior" yaml:"initial_behavior" toml:"initial_behavior"`
350 // AutoOpenOnNewPane opens the omnibox automatically when a new pane is created.
351 // Default: false
352 AutoOpenOnNewPane bool `mapstructure:"auto_open_on_new_pane" yaml:"auto_open_on_new_pane" toml:"auto_open_on_new_pane"`
353}
354
355// DebugConfig holds debug and troubleshooting options
356type DebugConfig struct {
357 // Enable browser developer tools (F12, Inspect Element in context menu)
358 EnableDevTools bool `mapstructure:"enable_devtools" yaml:"enable_devtools" toml:"enable_devtools"`
359}
360
361// UpdateConfig holds automatic update settings.
362type UpdateConfig struct {
363 // EnableOnStartup enables checking for updates when the browser starts.
364 // Default: true
365 EnableOnStartup bool `mapstructure:"enable_on_startup" yaml:"enable_on_startup" toml:"enable_on_startup"`
366 // AutoDownload automatically downloads updates in the background.
367 // When enabled, updates are applied on browser exit.
368 // Default: false
369 AutoDownload bool `mapstructure:"auto_download" yaml:"auto_download" toml:"auto_download"`
370 // NotifyOnNewSettings shows a toast notification on startup when new config settings are available.
371 // Default: true
372 NotifyOnNewSettings bool `mapstructure:"notify_on_new_settings" yaml:"notify_on_new_settings" toml:"notify_on_new_settings"`
373}
374
375// WorkspaceConfig captures layout, pane, and tab behavior preferences.
376type WorkspaceConfig struct {
377 // NewPaneURL is the URL loaded when creating a new empty pane/tab.
378 // Default: "about:blank"
379 NewPaneURL string `mapstructure:"new_pane_url" yaml:"new_pane_url" toml:"new_pane_url"`
380 // PaneMode defines modal pane behavior and bindings.
381 PaneMode PaneModeConfig `mapstructure:"pane_mode" yaml:"pane_mode" toml:"pane_mode" json:"pane_mode"`
382 // TabMode defines modal tab behavior and bindings (Alt+T).
383 TabMode TabModeConfig `mapstructure:"tab_mode" yaml:"tab_mode" toml:"tab_mode" json:"tab_mode"`
384 // ResizeMode defines modal pane resizing behavior and bindings (Ctrl+N).
385 ResizeMode ResizeModeConfig `mapstructure:"resize_mode" yaml:"resize_mode" toml:"resize_mode" json:"resize_mode"`
386 // Shortcuts holds global (non-modal) keyboard shortcuts.
387 Shortcuts GlobalShortcutsConfig `mapstructure:"shortcuts" yaml:"shortcuts" toml:"shortcuts" json:"shortcuts"`
388 // TabBarPosition determines tab bar placement: "top" or "bottom".
389 TabBarPosition string `mapstructure:"tab_bar_position" yaml:"tab_bar_position" toml:"tab_bar_position" json:"tab_bar_position"`
390 // HideTabBarWhenSingleTab hides the tab bar when only one tab exists.
391 HideTabBarWhenSingleTab bool `mapstructure:"hide_tab_bar_when_single_tab" yaml:"hide_tab_bar_when_single_tab" toml:"hide_tab_bar_when_single_tab" json:"hide_tab_bar_when_single_tab"` //nolint:lll // struct tags must stay on one line
392 // SwitchToTabOnMove controls whether moving a pane to another tab switches focus to that tab.
393 // Default: true
394 SwitchToTabOnMove bool `mapstructure:"switch_to_tab_on_move" yaml:"switch_to_tab_on_move" toml:"switch_to_tab_on_move" json:"switch_to_tab_on_move"` //nolint:lll // struct tags must stay on one line
395 // Popups configures default popup placement rules.
396 Popups PopupBehaviorConfig `mapstructure:"popups" yaml:"popups" toml:"popups" json:"popups"`
397 // Styling configures workspace visual appearance.
398 Styling WorkspaceStylingConfig `mapstructure:"styling" yaml:"styling" toml:"styling" json:"styling"`
399}
400
401// PaneModeConfig defines modal behavior for pane management.
402type PaneModeConfig struct {
403 ActivationShortcut string `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
404 TimeoutMilliseconds int `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
405 Actions map[string][]string `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
406}
407
408// GetKeyBindings returns an inverted map for O(1) key→action lookup.
409// This is built from the action→keys structure in the config.
410func (p *PaneModeConfig) GetKeyBindings() map[string]string {
411 keyToAction := make(map[string]string)
412 for action, keys := range p.Actions {
413 for _, key := range keys {
414 keyToAction[key] = action
415 }
416 }
417 return keyToAction
418}
419
420// TabModeConfig defines modal behavior for tab management (Zellij-style).
421type TabModeConfig struct {
422 ActivationShortcut string `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
423 TimeoutMilliseconds int `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
424 Actions map[string][]string `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
425}
426
427// GetKeyBindings returns an inverted map for O(1) key→action lookup.
428// This is built from the action→keys structure in the config.
429func (t *TabModeConfig) GetKeyBindings() map[string]string {
430 keyToAction := make(map[string]string)
431 for action, keys := range t.Actions {
432 for _, key := range keys {
433 keyToAction[key] = action
434 }
435 }
436 return keyToAction
437}
438
439// ResizeModeConfig defines modal behavior for resizing panes (Zellij-style).
440type ResizeModeConfig struct {
441 ActivationShortcut string `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
442 TimeoutMilliseconds int `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
443 StepPercent float64 `mapstructure:"step_percent" yaml:"step_percent" toml:"step_percent" json:"step_percent"`
444 MinPanePercent float64 `mapstructure:"min_pane_percent" yaml:"min_pane_percent" toml:"min_pane_percent" json:"min_pane_percent"` //nolint:lll // struct tags must stay on one line
445 Actions map[string][]string `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
446}
447
448// GetKeyBindings returns an inverted map for O(1) key→action lookup.
449// This is built from the action→keys structure in the config.
450func (r *ResizeModeConfig) GetKeyBindings() map[string]string {
451 keyToAction := make(map[string]string)
452 for action, keys := range r.Actions {
453 for _, key := range keys {
454 keyToAction[key] = action
455 }
456 }
457 return keyToAction
458}
459
460// GlobalShortcutsConfig defines global shortcuts (always active, not modal).
461type GlobalShortcutsConfig struct {
462 ClosePane string `mapstructure:"close_pane" yaml:"close_pane" toml:"close_pane" json:"close_pane"`
463 NextTab string `mapstructure:"next_tab" yaml:"next_tab" toml:"next_tab" json:"next_tab"`
464 PreviousTab string `mapstructure:"previous_tab" yaml:"previous_tab" toml:"previous_tab" json:"previous_tab"`
465
466 ConsumeOrExpelLeft string `mapstructure:"consume_or_expel_left" yaml:"consume_or_expel_left" toml:"consume_or_expel_left" json:"consume_or_expel_left"` //nolint:lll // struct tags must stay on one line
467 ConsumeOrExpelRight string `mapstructure:"consume_or_expel_right" yaml:"consume_or_expel_right" toml:"consume_or_expel_right" json:"consume_or_expel_right"` //nolint:lll // struct tags must stay on one line
468 ConsumeOrExpelUp string `mapstructure:"consume_or_expel_up" yaml:"consume_or_expel_up" toml:"consume_or_expel_up" json:"consume_or_expel_up"` //nolint:lll // struct tags must stay on one line
469 ConsumeOrExpelDown string `mapstructure:"consume_or_expel_down" yaml:"consume_or_expel_down" toml:"consume_or_expel_down" json:"consume_or_expel_down"` //nolint:lll // struct tags must stay on one line
470}
471
472// PopupBehavior defines how popup windows should be opened
473type PopupBehavior string
474
475const (
476 // PopupBehaviorSplit opens popups in a split pane (default)
477 PopupBehaviorSplit PopupBehavior = "split"
478 // PopupBehaviorStacked opens popups in a stacked pane
479 PopupBehaviorStacked PopupBehavior = "stacked"
480 // PopupBehaviorTabbed opens popups as a new tab
481 PopupBehaviorTabbed PopupBehavior = "tabbed"
482 // PopupBehaviorWindowed opens popups in a new workspace window
483 PopupBehaviorWindowed PopupBehavior = "windowed"
484)
485
486// PopupBehaviorConfig defines handling for popup windows.
487type PopupBehaviorConfig struct {
488 // Behavior determines how popups are opened (split/stacked/tabbed/windowed)
489 Behavior PopupBehavior `mapstructure:"behavior" yaml:"behavior" toml:"behavior" json:"behavior"`
490
491 // Placement specifies direction for split behavior ("right", "left", "top", "bottom")
492 // Only used when Behavior is "split"
493 Placement string `mapstructure:"placement" yaml:"placement" toml:"placement" json:"placement"`
494
495 // OpenInNewPane controls whether popups are opened in workspace or blocked
496 OpenInNewPane bool `mapstructure:"open_in_new_pane" yaml:"open_in_new_pane" toml:"open_in_new_pane" json:"open_in_new_pane"`
497
498 // FollowPaneContext determines if popup placement follows parent pane context
499 FollowPaneContext bool `mapstructure:"follow_pane_context" yaml:"follow_pane_context" toml:"follow_pane_context" json:"follow_pane_context"` //nolint:lll // struct tags must stay on one line
500
501 // BlankTargetBehavior determines how target="_blank" links are opened
502 // Accepted values: "split", "stacked" (default), "tabbed"
503 // This is separate from Behavior which controls JavaScript popups
504 BlankTargetBehavior string `mapstructure:"blank_target_behavior" yaml:"blank_target_behavior" toml:"blank_target_behavior" json:"blank_target_behavior"` //nolint:lll // struct tags must stay on one line
505
506 // EnableSmartDetection uses WebKitWindowProperties to detect popup vs tab intents
507 EnableSmartDetection bool `mapstructure:"enable_smart_detection" yaml:"enable_smart_detection" toml:"enable_smart_detection" json:"enable_smart_detection"` //nolint:lll // struct tags must stay on one line
508
509 // OAuthAutoClose enables auto-closing OAuth popups after successful auth redirects
510 OAuthAutoClose bool `mapstructure:"oauth_auto_close" yaml:"oauth_auto_close" toml:"oauth_auto_close" json:"oauth_auto_close"`
511}
512
513// WorkspaceStylingConfig defines visual styling for workspace panes.
514type WorkspaceStylingConfig struct {
515 // BorderWidth in pixels for active pane borders (overlay)
516 BorderWidth int `mapstructure:"border_width" yaml:"border_width" toml:"border_width" json:"border_width"`
517 // BorderColor for focused panes (CSS color value or theme variable)
518 BorderColor string `mapstructure:"border_color" yaml:"border_color" toml:"border_color" json:"border_color"`
519
520 // ModeBorderWidth in pixels for all mode indicator borders (pane, tab, session, resize)
521 ModeBorderWidth int `mapstructure:"mode_border_width" yaml:"mode_border_width" toml:"mode_border_width" json:"mode_border_width"` //nolint:lll // struct tags must stay on one line
522
523 // PaneModeColor for pane mode indicator (border and toaster). Defaults to "#4A90E2" (blue)
524 PaneModeColor string `mapstructure:"pane_mode_color" yaml:"pane_mode_color" toml:"pane_mode_color" json:"pane_mode_color"` //nolint:lll // struct tags must stay on one line
525 // TabModeColor for tab mode indicator (border and toaster). Defaults to "#FFA500" (orange)
526 TabModeColor string `mapstructure:"tab_mode_color" yaml:"tab_mode_color" toml:"tab_mode_color" json:"tab_mode_color"` //nolint:lll // struct tags must stay on one line
527 // SessionModeColor for session mode indicator (border and toaster). Defaults to "#9B59B6" (purple)
528 SessionModeColor string `mapstructure:"session_mode_color" yaml:"session_mode_color" toml:"session_mode_color" json:"session_mode_color"` //nolint:lll // struct tags must stay on one line
529 // ResizeModeColor for resize mode indicator (border and toaster). Defaults to "#00D4AA" (teal)
530 ResizeModeColor string `mapstructure:"resize_mode_color" yaml:"resize_mode_color" toml:"resize_mode_color" json:"resize_mode_color"` //nolint:lll // struct tags must stay on one line
531
532 // ModeIndicatorToasterEnabled shows a toaster notification when modal modes are active.
533 // Default: true
534 ModeIndicatorToasterEnabled bool `mapstructure:"mode_indicator_toaster_enabled" yaml:"mode_indicator_toaster_enabled" toml:"mode_indicator_toaster_enabled" json:"mode_indicator_toaster_enabled"` //nolint:lll // struct tags must stay on one line
535
536 // TransitionDuration in milliseconds for border animations
537 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" toml:"transition_duration" json:"transition_duration"` //nolint:lll // struct tags must stay on one line
538}
539
540// SessionConfig holds session persistence settings.
541type SessionConfig struct {
542 // AutoRestore automatically restores the last session on startup.
543 // Default: false
544 AutoRestore bool `mapstructure:"auto_restore" yaml:"auto_restore" toml:"auto_restore" json:"auto_restore"`
545
546 // SnapshotIntervalMs is the minimum interval between snapshots in milliseconds.
547 // Default: 5000
548 SnapshotIntervalMs int `mapstructure:"snapshot_interval_ms" yaml:"snapshot_interval_ms" toml:"snapshot_interval_ms" json:"snapshot_interval_ms"` //nolint:lll // struct tags must stay on one line
549
550 // MaxExitedSessions is the maximum number of exited sessions to keep.
551 // Default: 50
552 MaxExitedSessions int `mapstructure:"max_exited_sessions" yaml:"max_exited_sessions" toml:"max_exited_sessions" json:"max_exited_sessions"` //nolint:lll // struct tags must stay on one line
553
554 // MaxExitedSessionAgeDays is the maximum age in days for exited sessions.
555 // Sessions older than this will be automatically deleted on startup.
556 // Default: 7
557 MaxExitedSessionAgeDays int `mapstructure:"max_exited_session_age_days" yaml:"max_exited_session_age_days" toml:"max_exited_session_age_days" json:"max_exited_session_age_days"` //nolint:lll // struct tags must stay on one line
558
559 // SessionMode defines modal behavior for session management (Ctrl+O).
560 SessionMode SessionModeConfig `mapstructure:"session_mode" yaml:"session_mode" toml:"session_mode" json:"session_mode"`
561}
562
563// SessionModeConfig defines modal behavior for session management.
564type SessionModeConfig struct {
565 ActivationShortcut string `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
566 TimeoutMilliseconds int `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
567 Actions map[string][]string `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
568}
569
570// GetKeyBindings returns an inverted map for O(1) key→action lookup.
571// This is built from the action→keys structure in the config.
572func (s *SessionModeConfig) GetKeyBindings() map[string]string {
573 keyToAction := make(map[string]string)
574 for action, keys := range s.Actions {
575 for _, key := range keys {
576 keyToAction[key] = action
577 }
578 }
579 return keyToAction
580}