feat(appearance): phase 2 of match-system-window-chrome (transparent)
Rounded-corner window chrome now actually works. The toggle in
Settings > Appearance persists to the window_settings SQLite store and
gates the Tauri window transparency decision at startup, so on next
launch the main window is rebuilt with `transparent: true` and the
border-radius plus edge outline apply without painting white corners.
Flow:
* Toggle in Settings > Appearance -> windowChromeStore saves to
localStorage and calls v2_set_match_system_window_chrome which
writes match_system_window_chrome to window_settings.db.
* Toast reminds the user to restart.
* On next launch, should_use_main_window_transparency() reads the
setting and returns true, Tauri builds the window transparent.
* Setup stores the decision in MAIN_WINDOW_TRANSPARENT. A new command
v2_main_window_is_transparent reports it back to the frontend.
* +page.svelte only applies .app.match-chrome when the window is
actually transparent AND the custom titlebar is visible, so
stale-state toggling never produces white wedges.
* CSS sets html/body transparent via a global class on <html>, then
.app.match-chrome.floating paints the rounded corners plus a
12/28 rgba drop shadow and a 1px darkening outline.
* Maximized state clears the radius automatically.
Env vars QBZ_FORCE_TRANSPARENT_WINDOWS / QBZ_FORCE_OPAQUE_WINDOWS still
take precedence over the DB-persisted toggle.
cc
This commit is contained in:
1 parent
8502c2fdb3
commit
57e63e3ef5
8 files changed
+158
-6
No files matched your search
+35
-2
@@ -111,6 +111,8 @@
|
||||
getMatchSystemWindowChrome,
|
||||
getCornerRadiusPx,
|
||||
setCornerRadiusPx,
|
||||
setWindowIsTransparent,
|
||||
getWindowIsTransparent,
|
||||
} from '$lib/stores/windowChromeStore';
|
||||
import { detectDesktopThemeCached } from '$lib/stores/windowControlsStore';
|
||||
|
||||
@@ -501,6 +503,7 @@
|
||||
let showTitleBar = $state(shouldShowTitleBar());
|
||||
let matchSystemChrome = $state(getMatchSystemWindowChrome());
|
||||
let chromeRadiusPx = $state(getCornerRadiusPx());
|
||||
let windowTransparent = $state(getWindowIsTransparent());
|
||||
let showWindowControls = $state(getShowWindowControls());
|
||||
|
||||
// Search Bar Location State
|
||||
@@ -4218,11 +4221,20 @@
|
||||
sidebarExpanded = getIsExpanded();
|
||||
});
|
||||
|
||||
// Declared upfront because subscribeTitleBar invokes the callback
|
||||
// immediately on subscription, which references this helper.
|
||||
const applyChromeClass = () => {
|
||||
if (typeof document === 'undefined') return;
|
||||
const active = matchSystemChrome && showTitleBar && windowTransparent;
|
||||
document.documentElement.classList.toggle('match-chrome-transparent', active);
|
||||
};
|
||||
|
||||
// Initialize and subscribe to title bar state changes
|
||||
initTitleBarStore();
|
||||
const unsubscribeTitleBar = subscribeTitleBar(() => {
|
||||
showTitleBar = shouldShowTitleBar();
|
||||
showWindowControls = getShowWindowControls();
|
||||
applyChromeClass();
|
||||
});
|
||||
|
||||
// Window chrome: subscribe to the "match system" toggle and fetch the
|
||||
@@ -4232,7 +4244,21 @@
|
||||
const unsubscribeWindowChrome = subscribeWindowChrome(() => {
|
||||
matchSystemChrome = getMatchSystemWindowChrome();
|
||||
chromeRadiusPx = getCornerRadiusPx();
|
||||
windowTransparent = getWindowIsTransparent();
|
||||
applyChromeClass();
|
||||
});
|
||||
// Ask the Rust side whether the main window was actually built
|
||||
// transparent. If not, the radius CSS is a no-op (white corners
|
||||
// otherwise). The backend captured the decision at setup time.
|
||||
void (async () => {
|
||||
try {
|
||||
const { invoke } = await import('@tauri-apps/api/core');
|
||||
const transparent = (await invoke('v2_main_window_is_transparent')) as boolean;
|
||||
setWindowIsTransparent(transparent);
|
||||
} catch (e) {
|
||||
console.warn('[windowChrome] could not query transparency:', e);
|
||||
}
|
||||
})();
|
||||
void detectDesktopThemeCached().then((info) => {
|
||||
if (info && typeof info.windowCornerRadiusPx === 'number') {
|
||||
setCornerRadiusPx(info.windowCornerRadiusPx);
|
||||
@@ -5011,7 +5037,7 @@
|
||||
class="app"
|
||||
class:no-titlebar={!showTitleBar}
|
||||
class:floating={isWindowFloating}
|
||||
class:match-chrome={matchSystemChrome && showTitleBar}
|
||||
class:match-chrome={matchSystemChrome && showTitleBar && windowTransparent}
|
||||
style="--chrome-radius: {chromeRadiusPx}px;"
|
||||
>
|
||||
<!-- macOS: drag region for window movement (overlay title bar has no native drag area) -->
|
||||
@@ -6195,7 +6221,14 @@
|
||||
/* Match system window chrome (Plasma / GNOME): apply the detected
|
||||
decoration radius and a thin edge outline so the window reads as
|
||||
its own surface against the desktop. Only takes effect in floating
|
||||
state (not maximized) and when the custom title bar is active. */
|
||||
state (not maximized) and when the custom title bar is active.
|
||||
Requires the Tauri window to have been built transparent (Phase 2:
|
||||
match_system_window_chrome persists to window_settings and gates the
|
||||
transparency path at startup). */
|
||||
:global(html.match-chrome-transparent),
|
||||
:global(html.match-chrome-transparent body) {
|
||||
background: transparent !important;
|
||||
}
|
||||
.app.match-chrome.floating {
|
||||
border-radius: var(--chrome-radius, 10px);
|
||||
box-shadow:
|
||||
|
||||
Reference in new issue
Block a user