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