1package config
2
3// Default configuration constants
4const (
5 // History defaults
6 defaultMaxHistoryEntries = 10000 // entries
7 defaultRetentionDays = 365 // 1 year
8
9 // Dmenu defaults
10 defaultMaxHistoryDays = 30 // days
11
12 // Logging defaults
13 defaultMaxLogAgeDays = 7 // days
14
15 // Appearance defaults
16 defaultFontSize = 16 // points
17
18 // Workspace defaults
19 defaultNewPaneURL = "about:blank"
20
21 // Omnibox defaults
22 defaultOmniboxInitialBehavior = "recent"
23 defaultOmniboxAutoOpenOnNewPane = false
24
25 // Workspace defaults
26 defaultPaneActivationShortcut = "ctrl+p"
27 defaultPaneTimeoutMilliseconds = 3000
28 defaultTabActivationShortcut = "ctrl+t"
29 defaultTabTimeoutMilliseconds = 3000
30 defaultResizeActivationShortcut = "ctrl+n"
31 defaultResizeTimeoutMilliseconds = 3000
32 defaultResizeStepPercent = 5.0
33 defaultResizeMinPanePercent = 10.0
34 defaultTabBarPosition = "bottom"
35 defaultPopupPlacement = "right"
36
37 // Session defaults
38 defaultSessionActivationShortcut = "ctrl+o"
39 defaultSessionTimeoutMilliseconds = 3000
40 defaultSnapshotIntervalMs = 5000
41 defaultMaxExitedSessions = 50
42 defaultMaxExitedSessionAgeDays = 7
43
44 // Workspace styling defaults
45 // Active pane border (overlay)
46 defaultBorderWidth = 1
47 defaultBorderColor = "@theme_selected_bg_color"
48
49 // Mode border width (consolidated for all modes)
50 defaultModeBorderWidth = 4
51
52 // Mode colors (used for both borders and toaster)
53 defaultPaneModeColor = "#4A90E2" // Blue for pane mode
54 defaultTabModeColor = "#FFA500" // Orange for tab mode
55 defaultSessionModeColor = "#9B59B6" // Purple for session mode
56 defaultResizeModeColor = "#00D4AA" // Cyan/teal for resize mode
57
58 // Mode indicator toaster
59 defaultModeIndicatorToasterEnabled = true
60
61 // Other styling
62 defaultTransitionDuration = 120
63 defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
64
65 // Performance defaults
66 defaultZoomCacheSize = 256 // domains to cache (~20KB memory)
67 defaultWebViewPoolPrewarmCount = 4 // WebViews to pre-create at startup
68
69 // Skia threading defaults (0 = unset, -1 = unset for GPU threads)
70 defaultSkiaCPUPaintingThreads = 0
71 defaultSkiaGPUPaintingThreads = -1 // -1 means unset; 0 would disable GPU tile painting
72)
73
74// getDefaultLogDir returns the default log directory, falls back to empty string on error
75func getDefaultLogDir() string {
76 logDir, err := GetLogDir()
77 if err != nil {
78 return ""
79 }
80 return logDir
81}
82
83// DefaultConfig returns the default configuration values for dumber.
84func DefaultConfig() *Config {
85 return &Config{
86 Database: DatabaseConfig{
87 // Path is set dynamically in config.Load()
88 },
89 History: HistoryConfig{
90 MaxEntries: defaultMaxHistoryEntries,
91 RetentionPeriodDays: defaultRetentionDays, // 1 year
92 CleanupIntervalDays: 1, // daily cleanup
93 },
94 SearchShortcuts: GetDefaultSearchShortcuts(),
95 DefaultSearchEngine: "https://duckduckgo.com/?q=%s",
96 Dmenu: DmenuConfig{
97 MaxHistoryDays: defaultMaxHistoryDays,
98 ShowVisitCount: true,
99 ShowLastVisited: true,
100 HistoryPrefix: "🕒",
101 ShortcutPrefix: "🔍",
102 URLPrefix: "🌐",
103 DateFormat: "2006-01-02 15:04",
104 SortByVisitCount: true,
105 },
106 Logging: LoggingConfig{
107 Level: "info",
108 Format: "text", // text or json
109 MaxAge: defaultMaxLogAgeDays,
110 LogDir: getDefaultLogDir(),
111 EnableFileLog: true,
112 CaptureConsole: false, // Disabled by default
113 CaptureGTKLogs: false, // Disabled by default
114 },
115 Appearance: AppearanceConfig{
116 SansFont: "Fira Sans",
117 SerifFont: "Fira Sans",
118 MonospaceFont: "Fira Code",
119 DefaultFontSize: defaultFontSize,
120 LightPalette: ColorPalette{
121 Background: "#fafafa",
122 Surface: "#f4f4f5",
123 SurfaceVariant: "#e4e4e7",
124 Text: "#18181b",
125 Muted: "#71717a",
126 Accent: "#22c55e", // Green-500 - vibrant primary
127 Border: "#d4d4d8",
128 },
129 DarkPalette: ColorPalette{
130 Background: "#0a0a0b",
131 Surface: "#18181b",
132 SurfaceVariant: "#27272a",
133 Text: "#fafafa",
134 Muted: "#a1a1aa",
135 Accent: "#4ade80", // Green-400 - vibrant primary
136 Border: "#3f3f46",
137 },
138 ColorScheme: "default", // default follows system theme
139 },
140 Debug: DebugConfig{
141 EnableDevTools: true,
142 },
143 Rendering: RenderingConfig{
144 Mode: RenderingModeGPU,
145 DisableDMABufRenderer: false,
146 ForceCompositingMode: false,
147 DisableCompositingMode: false,
148 GSKRenderer: GSKRendererAuto, // Let GTK choose - Vulkan can conflict with WebKit's DMA-BUF
149 DisableMipmaps: false,
150 PreferGL: false,
151 DrawCompositingIndicators: false,
152 ShowFPS: false,
153 SampleMemory: false,
154 DebugFrames: false,
155 },
156 DefaultWebpageZoom: 1.2, // 120% default zoom for better readability
157 DefaultUIScale: defaultUIScale, // 1.0 = 100%, 2.0 = 200%
158 Workspace: WorkspaceConfig{
159 NewPaneURL: defaultNewPaneURL,
160 SwitchToTabOnMove: true,
161 PaneMode: PaneModeConfig{
162 ActivationShortcut: defaultPaneActivationShortcut,
163 TimeoutMilliseconds: defaultPaneTimeoutMilliseconds,
164 Actions: map[string]ActionBinding{
165 "split-right": {Keys: []string{"arrowright", "r"}, Desc: "Split pane to the right"},
166 "split-left": {Keys: []string{"arrowleft", "l"}, Desc: "Split pane to the left"},
167 "split-up": {Keys: []string{"arrowup", "u"}, Desc: "Split pane upward"},
168 "split-down": {Keys: []string{"arrowdown", "d"}, Desc: "Split pane downward"},
169 "stack-pane": {Keys: []string{"s"}, Desc: "Stack pane with sibling"},
170 "close-pane": {Keys: []string{"x"}, Desc: "Close current pane"},
171 "move-pane-to-tab": {Keys: []string{"m"}, Desc: "Move pane to different tab"},
172 "move-pane-to-next-tab": {Keys: []string{"M", "shift+m"}, Desc: "Move pane to next tab"},
173
174 "consume-or-expel-left": {Keys: []string{"["}, Desc: "Consume/expel pane left"},
175 "consume-or-expel-right": {Keys: []string{"]"}, Desc: "Consume/expel pane right"},
176 "consume-or-expel-up": {Keys: []string{"{"}, Desc: "Consume/expel pane up"},
177 "consume-or-expel-down": {Keys: []string{"}"}, Desc: "Consume/expel pane down"},
178
179 "focus-right": {Keys: []string{"shift+arrowright", "shift+l"}, Desc: "Focus pane to the right"},
180 "focus-left": {Keys: []string{"shift+arrowleft", "shift+h"}, Desc: "Focus pane to the left"},
181 "focus-up": {Keys: []string{"shift+arrowup", "shift+k"}, Desc: "Focus pane above"},
182 "focus-down": {Keys: []string{"shift+arrowdown", "shift+j"}, Desc: "Focus pane below"},
183 "confirm": {Keys: []string{"enter"}, Desc: "Confirm action"},
184 "cancel": {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
185 },
186 },
187 TabMode: TabModeConfig{
188 ActivationShortcut: defaultTabActivationShortcut,
189 TimeoutMilliseconds: defaultTabTimeoutMilliseconds,
190 Actions: map[string]ActionBinding{
191 "new-tab": {Keys: []string{"n", "c"}, Desc: "Create new tab"},
192 "close-tab": {Keys: []string{"x"}, Desc: "Close current tab"},
193 "next-tab": {Keys: []string{"l", "tab"}, Desc: "Switch to next tab"},
194 "previous-tab": {Keys: []string{"h", "shift+tab"}, Desc: "Switch to previous tab"},
195 "rename-tab": {Keys: []string{"r"}, Desc: "Rename current tab"},
196 "confirm": {Keys: []string{"enter"}, Desc: "Confirm action"},
197 "cancel": {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
198 },
199 },
200 ResizeMode: ResizeModeConfig{
201 ActivationShortcut: defaultResizeActivationShortcut,
202 TimeoutMilliseconds: defaultResizeTimeoutMilliseconds,
203 StepPercent: defaultResizeStepPercent,
204 MinPanePercent: defaultResizeMinPanePercent,
205 Actions: map[string]ActionBinding{
206 "resize-increase-left": {Keys: []string{"h", "arrowleft"}, Desc: "Increase size leftward"},
207 "resize-increase-down": {Keys: []string{"j", "arrowdown"}, Desc: "Increase size downward"},
208 "resize-increase-up": {Keys: []string{"k", "arrowup"}, Desc: "Increase size upward"},
209 "resize-increase-right": {Keys: []string{"l", "arrowright"}, Desc: "Increase size rightward"},
210 "resize-decrease-left": {Keys: []string{"H"}, Desc: "Decrease size leftward"},
211 "resize-decrease-down": {Keys: []string{"J"}, Desc: "Decrease size downward"},
212 "resize-decrease-up": {Keys: []string{"K"}, Desc: "Decrease size upward"},
213 "resize-decrease-right": {Keys: []string{"L"}, Desc: "Decrease size rightward"},
214 "resize-increase": {Keys: []string{"+", "="}, Desc: "Increase pane size"},
215 "resize-decrease": {Keys: []string{"-"}, Desc: "Decrease pane size"},
216 "confirm": {Keys: []string{"enter"}, Desc: "Confirm action"},
217 "cancel": {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
218 },
219 },
220 Shortcuts: GlobalShortcutsConfig{
221 Actions: map[string]ActionBinding{
222 "close_pane": {Keys: []string{"ctrl+w"}, Desc: "Close active pane"},
223 "next_tab": {Keys: []string{"ctrl+tab"}, Desc: "Switch to next tab"},
224 "previous_tab": {Keys: []string{"ctrl+shift+tab"}, Desc: "Switch to previous tab"},
225 "consume_or_expel_left": {Keys: []string{"alt+["}, Desc: "Consume/expel pane left"},
226 "consume_or_expel_right": {Keys: []string{"alt+]"}, Desc: "Consume/expel pane right"},
227 "consume_or_expel_up": {Keys: []string{"alt+{"}, Desc: "Consume/expel pane up"},
228 "consume_or_expel_down": {Keys: []string{"alt+}"}, Desc: "Consume/expel pane down"},
229 },
230 },
231 TabBarPosition: defaultTabBarPosition,
232 HideTabBarWhenSingleTab: true,
233 Popups: PopupBehaviorConfig{
234 Behavior: PopupBehaviorSplit, // Default: open JavaScript popups in split panes
235 Placement: defaultPopupPlacement,
236 OpenInNewPane: true,
237 FollowPaneContext: true,
238 BlankTargetBehavior: "stacked", // Default: open _blank links in stacked mode
239 EnableSmartDetection: true, // Use WindowProperties to detect popup vs tab
240 OAuthAutoClose: true, // Auto-close OAuth popups on success
241 },
242 Styling: WorkspaceStylingConfig{
243 BorderWidth: defaultBorderWidth,
244 BorderColor: defaultBorderColor,
245 ModeBorderWidth: defaultModeBorderWidth,
246 PaneModeColor: defaultPaneModeColor,
247 TabModeColor: defaultTabModeColor,
248 SessionModeColor: defaultSessionModeColor,
249 ResizeModeColor: defaultResizeModeColor,
250 ModeIndicatorToasterEnabled: defaultModeIndicatorToasterEnabled,
251 TransitionDuration: defaultTransitionDuration,
252 },
253 },
254 ContentFiltering: ContentFilteringConfig{
255 Enabled: true, // Ad blocking enabled by default
256 AutoUpdate: true, // Auto-update filters from GitHub releases
257 },
258 Clipboard: ClipboardConfig{
259 AutoCopyOnSelection: true, // Enabled by default (zellij-style)
260 },
261 Omnibox: OmniboxConfig{
262 InitialBehavior: defaultOmniboxInitialBehavior,
263 AutoOpenOnNewPane: defaultOmniboxAutoOpenOnNewPane,
264 },
265 Session: SessionConfig{
266 AutoRestore: false,
267 SnapshotIntervalMs: defaultSnapshotIntervalMs,
268 MaxExitedSessions: defaultMaxExitedSessions,
269 MaxExitedSessionAgeDays: defaultMaxExitedSessionAgeDays,
270 SessionMode: SessionModeConfig{
271 ActivationShortcut: defaultSessionActivationShortcut,
272 TimeoutMilliseconds: defaultSessionTimeoutMilliseconds,
273 Actions: map[string]ActionBinding{
274 "session-manager": {Keys: []string{"s", "w"}, Desc: "Open session manager"},
275 "confirm": {Keys: []string{"enter"}, Desc: "Confirm action"},
276 "cancel": {Keys: []string{"escape"}, Desc: "Cancel/exit mode"},
277 },
278 },
279 },
280 Media: MediaConfig{
281 HardwareDecodingMode: HardwareDecodingAuto, // auto allows sw fallback
282 PreferAV1: false, // Don't force codec preference, let site choose
283 ShowDiagnosticsOnStartup: false, // Disabled - diagnostics can be noisy
284 ForceVSync: false, // Let compositor handle VSync
285 GLRenderingMode: GLRenderingModeAuto, // GStreamer picks best GL API
286 GStreamerDebugLevel: 0, // Disabled by default
287 },
288 Runtime: RuntimeConfig{
289 Prefix: "",
290 },
291 Performance: PerformanceConfig{
292 Profile: ProfileDefault, // Use WebKit defaults, no tuning
293 ZoomCacheSize: defaultZoomCacheSize,
294 WebViewPoolPrewarmCount: defaultWebViewPoolPrewarmCount,
295 // Skia threading - balanced defaults (unset = use WebKit defaults)
296 // These only apply when Profile is "custom"
297 SkiaCPUPaintingThreads: defaultSkiaCPUPaintingThreads,
298 SkiaGPUPaintingThreads: defaultSkiaGPUPaintingThreads,
299 SkiaEnableCPURendering: false,
300 // Web process memory pressure - all unset by default
301 WebProcessMemoryLimitMB: 0,
302 WebProcessMemoryPollIntervalSec: 0,
303 WebProcessMemoryConservativeThreshold: 0,
304 WebProcessMemoryStrictThreshold: 0,
305 // Network process memory pressure - all unset by default
306 NetworkProcessMemoryLimitMB: 0,
307 NetworkProcessMemoryPollIntervalSec: 0,
308 NetworkProcessMemoryConservativeThreshold: 0,
309 NetworkProcessMemoryStrictThreshold: 0,
310 },
311 Update: UpdateConfig{
312 EnableOnStartup: true, // Check for updates on startup by default
313 AutoDownload: false, // Conservative: don't auto-download by default
314 NotifyOnNewSettings: true, // Show toast when new config settings available
315 },
316 Downloads: DownloadsConfig{
317 Path: "", // Empty = use XDG_DOWNLOAD_DIR or ~/Downloads
318 },
319 }
320}
321
322// GetDefaultSearchShortcuts returns the default search shortcuts.
323func GetDefaultSearchShortcuts() map[string]SearchShortcut {
324 return map[string]SearchShortcut{
325 "ddg": {
326 URL: "https://duckduckgo.com/?q=%s",
327 Description: "DuckDuckGo search",
328 },
329 "g": {
330 URL: "https://www.google.com/search?q=%s",
331 Description: "Google search",
332 },
333 "gi": {
334 URL: "https://www.google.com/search?tbm=isch&q=%s",
335 Description: "Google Images search",
336 },
337 "gh": {
338 URL: "https://github.com/search?q=%s",
339 Description: "GitHub search",
340 },
341 "go": {
342 URL: "https://pkg.go.dev/search?q=%s",
343 Description: "Go package search",
344 },
345 "mdn": {
346 URL: "https://developer.mozilla.org/en-US/search?q=%s",
347 Description: "MDN Web Docs search",
348 },
349 "npm": {
350 URL: "https://www.npmjs.com/search?q=%s",
351 Description: "npm package search",
352 },
353 "r": {
354 URL: "https://www.reddit.com/search?q=%s",
355 Description: "Reddit search",
356 },
357 "so": {
358 URL: "https://stackoverflow.com/search?q=%s",
359 Description: "Stack Overflow search",
360 },
361 "w": {
362 URL: "https://en.wikipedia.org/wiki/%s",
363 Description: "Wikipedia search",
364 },
365 "yt": {
366 URL: "https://www.youtube.com/results?search_query=%s",
367 Description: "YouTube search",
368 },
369 }
370}