Add Linux system window decorations setting

Expose a per-user setting to toggle system window decorations on Linux
and apply it to the UI and window behavior.

- Add a SettingsScreen option (Linux-only) to toggle "System window decorations" and bind it to the app store.
- Track the preference in app store with persistent localStorage key and getter/setter (setSystemDecorations) that updates the Tauri window decorations via getCurrentWindow().setDecorations().
- Respect the setting when rendering the main App.svelte by disabling rounded corners and custom Linux window border when system decorations are enabled. This change is needed to let Linux users choose native title bar/window chrome for better integration with their desktop environment.
This commit is contained in:
Tristan Michael 2026-04-14 05:58:17 -07:00
parent 31af983640
commit 34d7e8b17d
3 changed files with 38 additions and 3 deletions

View file

@ -14,11 +14,11 @@
</script>
<div class={app.isDark ? "dark" : ""} data-theme={app.currentTheme ?? ""}>
<div class="h-screen w-screen" class:p-2={isLinux}>
<div class="h-screen w-screen" class:p-2={isLinux && !app.systemDecorations}>
<div
class="relative h-full w-full overflow-hidden bg-surface-light text-text-light dark:bg-surface-dark dark:text-text-dark"
class:rounded-xl={isLinux}
class:linux-window-border={isLinux}
class:rounded-xl={isLinux && !app.systemDecorations}
class:linux-window-border={isLinux && !app.systemDecorations}
style="container-type: inline-size"
>
{#if app.error}

View file

@ -1,8 +1,11 @@
<script lang="ts">
import { invoke } from "@tauri-apps/api/core";
import { platform } from "@tauri-apps/plugin-os";
import { app } from "../stores/app.svelte";
import ConfirmDialog from "../components/ConfirmDialog.svelte";
const isLinux = platform() === "linux";
let { onclose, workspaceId, ondelete }: { onclose?: () => void; workspaceId: string; ondelete?: (id: string) => void } = $props();
let ws = $derived(app.config?.workspaces[workspaceId]);
@ -264,6 +267,24 @@
</select>
</section>
{#if isLinux}
<!-- Window decorations (Linux only) -->
<section class="mt-6">
<label class="flex cursor-pointer items-center justify-between gap-3">
<div>
<p class="text-sm font-medium">System window decorations</p>
<p class="text-xs opacity-50">Use the system title bar instead of the custom border</p>
</div>
<input
type="checkbox"
checked={app.systemDecorations}
onchange={(e) => app.setSystemDecorations((e.target as HTMLInputElement).checked)}
class="h-4 w-4 cursor-pointer accent-primary"
/>
</label>
</section>
{/if}
<p class="mt-8 text-center text-xs opacity-30">Tauri v2 + Svelte</p>
</main>

View file

@ -18,6 +18,10 @@ listen("fs-changed", () => {
// ── Reactive state ───────────────────────────────────────────────────
const LS_DECORATIONS_KEY = "systemDecorations";
let systemDecorations = $state(localStorage.getItem(LS_DECORATIONS_KEY) === "true");
if (systemDecorations) getCurrentWindow().setDecorations(true);
let screen = $state<Screen>("setup");
let config = $state<AppConfig | null>(null);
let lists = $state<TaskList[]>([]);
@ -429,6 +433,12 @@ async function setSyncIntervalUnfocused(secs: number | null) {
}
}
function setSystemDecorations(value: boolean) {
systemDecorations = value;
localStorage.setItem(LS_DECORATIONS_KEY, String(value));
getCurrentWindow().setDecorations(value);
}
async function setTheme(theme: string | null) {
if (!config?.current_workspace) return;
try {
@ -549,6 +559,9 @@ export const app = {
get lastSyncResult() {
return lastSyncResult;
},
get systemDecorations() {
return systemDecorations;
},
get error() {
return error;
},
@ -582,6 +595,7 @@ export const app = {
stopAutoSync,
setSyncInterval,
setSyncIntervalUnfocused,
setSystemDecorations,
setTheme,
addWebdavWorkspace,
forgetMissingWorkspace,