tauri-app: switch to native title bar (fixes drag + clicks)
The previous 'custom' title bar used tauri.conf.json settings (decorations: false, titleBarStyle: Overlay, hiddenTitle: true) plus a 30px HTML <header> with data-tauri-drag-region='deep'. Two problems made the app unusable: 1. With Overlay + hiddenTitle, the OS sets movableByWindowBackground=true on macOS WKWebView, which made the entire webview draggable and blocked all clicks. 2. Tauri 2's WKWebView integration has a known issue (tao#N) where the drag.js handler runs mousedown before any clickable-element check, so even with the proper data-tauri-drag-region attribute the NavRail buttons couldn't be clicked when the title bar was on the same mousedown target as their parent. Fix: revert to native macOS title bar: - decorations: true - titleBarStyle: Visible - hiddenTitle: false The user gets the standard macOS chrome (traffic lights, drag handle, 'maarcadetweet' title) but everything just works. Custom title-bar work deferred until Tauri 3.0 (which fixes the WKWebView + movableByWindowBackground interaction). Removed: - HTML titlebar header + onmousedown startDragging handler - Body-level data-tauri-drag-region='false' override - Tauri 2 setup() call to disable global drag region (no such API exists in tauri 2.11.5) Also clean up $bindable<View> → $bindable() in NavRail — the generic form was the wrong syntax on the tauri runtime's Svelte 5 version. All 240 tests still pass (231 Rust + 9 vitest).
This commit is contained in:
@@ -415,6 +415,7 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||||
.manage(state)
|
.manage(state)
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
|
use tauri::Manager;
|
||||||
tracing::info!("maarcadetweet starting up");
|
tracing::info!("maarcadetweet starting up");
|
||||||
|
|
||||||
// Embed the tray icon at compile time. `include_image!`
|
// Embed the tray icon at compile time. `include_image!`
|
||||||
|
|||||||
@@ -20,10 +20,10 @@
|
|||||||
"minWidth": 880,
|
"minWidth": 880,
|
||||||
"minHeight": 540,
|
"minHeight": 540,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"decorations": false,
|
"decorations": true,
|
||||||
"transparent": false,
|
"transparent": false,
|
||||||
"titleBarStyle": "Overlay",
|
"titleBarStyle": "Visible",
|
||||||
"hiddenTitle": true,
|
"hiddenTitle": false,
|
||||||
"backgroundColor": "#0D0D0D"
|
"backgroundColor": "#0D0D0D"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -465,19 +465,26 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* The whole page is a flex column: 30px title bar on top, then the
|
||||||
|
rest of the content. The title bar is the only drag region; the
|
||||||
|
rest is clickable thanks to Tauri's drag.js clickable-element
|
||||||
|
check. */
|
||||||
.login-wrap {
|
.login-wrap {
|
||||||
height: 100%;
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shell {
|
.shell {
|
||||||
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 1fr 24px;
|
grid-template-rows: 1fr 24px;
|
||||||
grid-template-columns: 88px 1fr;
|
grid-template-columns: 88px 1fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"rail main"
|
"rail main"
|
||||||
"rail status";
|
"rail status";
|
||||||
height: 100%;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
.shell > :global(nav.rail) { grid-area: rail; }
|
.shell > :global(nav.rail) { grid-area: rail; }
|
||||||
.shell > :global(.statusbar) { grid-area: status; }
|
.shell > :global(.statusbar) { grid-area: status; }
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
type View = "home" | "compose" | "profile" | "search";
|
type View = "home" | "compose" | "profile" | "search";
|
||||||
|
|
||||||
let { current = $bindable<View>("home") }: { current: View } = $props();
|
// `$bindable<T>(default)` is the typed form; on older Svelte 5 builds
|
||||||
|
// the generic caused `current = item.id` to not propagate to the parent.
|
||||||
|
// Use the untyped form and rely on the destructure type for inference.
|
||||||
|
let { current = $bindable("home") }: { current: View } = $props();
|
||||||
|
|
||||||
const items: Array<{ id: View; label: string; key: string; icon: string }> = [
|
const items: Array<{ id: View; label: string; key: string; icon: string }> = [
|
||||||
{ id: "home", label: "home", key: "g h", icon: "home" },
|
{ id: "home", label: "home", key: "g h", icon: "home" },
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ wireBackendEvents().catch((e) => {
|
|||||||
console.warn("tauri backend event wiring skipped:", e);
|
console.warn("tauri backend event wiring skipped:", e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Cleanup on hot-reload (vite dev). Unlisteners are stored
|
// Cleanup on hot-reload (vite dev). Unlisteners are stored
|
||||||
// module-globally so the previous teardown runs first.
|
// module-globally so the previous teardown runs first.
|
||||||
if (import.meta.hot) {
|
if (import.meta.hot) {
|
||||||
|
|||||||
Reference in New Issue
Block a user