From fbd88c6281f06a1dab43bc254378e4aa04f9c6ac Mon Sep 17 00:00:00 2001 From: dvorakmortonxd Date: Sun, 11 Oct 2026 18:22:56 +0200 Subject: [PATCH] integrate the titlebar into the tab strip (no more native GTK titlebar) - Linux: the chrome webview is promoted into the GTK titlebar slot via gtk_window_set_titlebar, so the window keeps GTK's client-side shadow, edge-resizing and snap behaviour while drawing its own titlebar - custom minimize / maximize-restore / close buttons in the tab strip row, with hover states and tooltips; window state is synced on resize - drag the window from the grip next to the tabs or from the empty tab strip area; double-click toggles maximize - '+' new tab button now sits right next to the last tab instead of the far right edge - window is created hidden and shown after the titlebar is installed, avoiding Gtk's realized-window warning on startup - non-Linux builds keep native decorations and hide the custom controls - tab row height 34 -> 38 (chrome height 84 -> 88) --- src/webview.rs | 153 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 9 deletions(-) diff --git a/src/webview.rs b/src/webview.rs index 6de827d..c8a20bf 100644 --- a/src/webview.rs +++ b/src/webview.rs @@ -25,7 +25,7 @@ const DEFAULT_HOME: &str = "https://duckduckgo.com"; const NEW_TAB_URL: &str = "https://duckduckgo.com"; const SEARCH_URL_PREFIX: &str = "https://duckduckgo.com/?q="; const MODERN_BROWSER_UA_BASE: &str = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"; -const CHROME_HEIGHT_BASE: f64 = 84.0; +const CHROME_HEIGHT_BASE: f64 = 88.0; const CHROME_HEIGHT_DOWNLOADS_EXTRA: f64 = 104.0; const CHROME_HEIGHT_POPUP_PROMPT_EXTRA: f64 = 44.0; const MAX_HISTORY_ENTRIES: usize = 250; @@ -206,7 +206,7 @@ body { /* ---------- Tab strip ---------- */ #tabs-row { display: flex; align-items: center; gap: 6px; - flex: 0 0 34px; height: 34px; min-width: 0; + flex: 0 0 38px; height: 38px; min-width: 0; } #tabs { display: flex; align-items: center; gap: 4px; @@ -216,6 +216,26 @@ body { #tabs::-webkit-scrollbar { display: none; } #add-btn { width: 28px; height: 28px; } #add-btn svg { width: 15px; height: 15px; } +#drag-grip { flex: 0 0 auto; width: 14px; height: 100%; } +#window-controls { display: flex; align-items: center; gap: 2px; margin-left: 2px; } +body:not(.frameless) #drag-grip, +body:not(.frameless) #window-controls { display: none; } +.win-btn { + flex: 0 0 auto; + display: inline-flex; align-items: center; justify-content: center; + width: 36px; height: 30px; padding: 0; + border: 0; border-radius: var(--radius-sm); + background: transparent; color: var(--text-dim); + cursor: pointer; outline: none; + transition: background-color var(--speed) var(--ease), color var(--speed) var(--ease); +} +.win-btn svg { display: block; width: 14px; height: 14px; } +.win-btn:hover { background: var(--surface-hover); color: var(--text); } +.win-btn:focus-visible { box-shadow: 0 0 0 2px var(--accent-soft); color: var(--text); } +#win-close:hover { background: #d64550; color: #fff; } +#win-max .icon-restore { display: none; } +body.maximized #win-max .icon-max { display: none; } +body.maximized #win-max .icon-restore { display: block; } .tab { position: relative; display: flex; align-items: center; gap: 4px; @@ -383,12 +403,27 @@ body { +
-
- +
+ +
+ +
+ + + +