fix(chrome): P5-47 — Mica vs frameless conflict broke custom window chrome

Root cause: lib.rs applies a Mica backdrop to the main window at startup;
set_custom_chrome then stripped the frame with set_decorations(false), and
Mica + frameless is a broken combination on Windows (DWM backdrop glitches
the whole surface).

- set_custom_chrome: clear_mica() before undecorating, re-apply_mica() when
  restoring the native frame; set_shadow(true) so the frameless window keeps
  its drop shadow + resize borders.
- window-state plugin: exclude StateFlags::DECORATIONS — the chrome toggle
  owns the decorated flag; restoring a saved decorated=false at startup would
  recreate the Mica-on-frameless glitch before the web side loads.

Pairs with the web-side TitleBar drag fix (explicit window_start_drag on
mousedown instead of data-tauri-drag-region) in the cinny repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 16:42:17 -04:00
parent e9132b4489
commit e8fba393f0
2 changed files with 35 additions and 6 deletions
+13 -1
View File
@@ -411,7 +411,19 @@ pub fn run() {
native::toast::show_rich_toast,
])
.plugin(tauri_plugin_localhost::Builder::new(port).build())
.plugin(tauri_plugin_window_state::Builder::default().build())
.plugin(
// DECORATIONS is excluded: the custom-chrome toggle (set_custom_chrome)
// owns the decorated flag. Letting window-state restore a saved
// decorated=false at startup would re-create the frameless window
// BEFORE lib.rs applies Mica (a broken combination) and before the web
// side has pushed the user's current setting.
tauri_plugin_window_state::Builder::default()
.with_state_flags(
tauri_plugin_window_state::StateFlags::all()
& !tauri_plugin_window_state::StateFlags::DECORATIONS,
)
.build(),
)
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_deep_link::init());
+22 -5
View File
@@ -6,11 +6,12 @@
//! `decorations(true)` and only `set_custom_chrome(true)` makes it frameless, so
//! the safe default is the untouched native frame.
//!
//! Everything here goes through the cross-platform Tauri v2 window API — there is
//! no `windows` crate dependency, so the same code path runs on Windows, macOS
//! and Linux. Each command resolves the "main" window and silently no-ops if it
//! isn't present (e.g. during teardown); the `Result`s are intentionally ignored
//! since a failed chrome tweak should never surface as an error to the user.
//! Everything here goes through the cross-platform Tauri v2 window API (plus a
//! Windows-only `window_vibrancy` dance in `set_custom_chrome`, since Mica and a
//! frameless window can't coexist). Each command resolves the "main" window and
//! silently no-ops if it isn't present (e.g. during teardown); the `Result`s are
//! intentionally ignored since a failed chrome tweak should never surface as an
//! error to the user.
use tauri::{AppHandle, Manager};
@@ -21,7 +22,23 @@ use tauri::{AppHandle, Manager};
#[tauri::command]
pub fn set_custom_chrome(app: AppHandle, enabled: bool) {
if let Some(window) = app.get_webview_window("main") {
// Windows: the Mica backdrop (applied at startup in lib.rs) and a
// frameless window are a known-bad combo — stripping WS_CAPTION under a
// system backdrop glitches the whole surface (black/blank window). Drop
// the backdrop before undecorating, and restore it together with the
// native frame when custom chrome turns off.
#[cfg(target_os = "windows")]
if enabled {
let _ = window_vibrancy::clear_mica(&window);
}
let _ = window.set_decorations(!enabled);
// Re-assert the DWM shadow so a frameless window keeps its drop shadow
// and resize borders on Windows (no-op / harmless elsewhere).
let _ = window.set_shadow(true);
#[cfg(target_os = "windows")]
if !enabled {
let _ = window_vibrancy::apply_mica(&window, Some(true));
}
}
}