From 7f31a90e05d1bf39871ffd4a8aef012ee8d98af5 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Fri, 8 May 2026 22:34:33 -0400 Subject: [PATCH] docs(plan): record Win32-opacity decision Replaces the eval-based set_window_opacity in the plan with the SetLayeredWindowAttributes implementation that actually shipped. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/superpowers/plans/2026-05-08-browserlay-mvp.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/superpowers/plans/2026-05-08-browserlay-mvp.md b/docs/superpowers/plans/2026-05-08-browserlay-mvp.md index 79909bf..cb7cacd 100644 --- a/docs/superpowers/plans/2026-05-08-browserlay-mvp.md +++ b/docs/superpowers/plans/2026-05-08-browserlay-mvp.md @@ -1883,8 +1883,9 @@ pub fn get_hotkey_status(app: AppHandle) -> Result Ok(guard.clone()) } -/// Set window opacity. Tauri 2's JS WebviewWindow does NOT expose setOpacity -/// (only the Rust side does), so the JS layer routes through this command. +/// Set window opacity. Tauri 2.11 does NOT expose set_opacity on either side +/// (open issue tauri-apps/tauri#3279), so we drop down to Win32 directly via +/// SetLayeredWindowAttributes. See `apply_window_opacity` for details. #[tauri::command] pub fn set_window_opacity( app: AppHandle, @@ -1894,10 +1895,12 @@ pub fn set_window_opacity( let Some(window) = app.get_webview_window(&label) else { return Err(format!("window not found: {label}")); }; - window.set_opacity(opacity).map_err(|e| e.to_string()) + apply_window_opacity(&window, opacity) } ``` +> **Window opacity implementation note:** Tauri 2.11.x's `WebviewWindow` doesn't expose `set_opacity` on either the JS or Rust side (long-running open issue tauri-apps/tauri#3279). To get true OS-level window translucency we drop down to the Win32 API directly. Pin `windows = "0.61"` in `Cargo.toml` to match Tauri's transitive `windows` version (otherwise `WebviewWindow::hwnd()` returns an HWND from a different `windows` major and you get a diamond-dependency type mismatch). The `apply_window_opacity` helper sets `WS_EX_LAYERED` if not already present, then calls `SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA)`. + > **Note on the design:** Tauri 2 doesn't expose a getter for `ignore_cursor_events` / `opacity` on `WebviewWindow`. Rather than rely on getters, we keep a tiny Rust-side cache (`AppState.click_through`) that the JS side keeps in sync via `sync_click_through_cache`. The global shortcut handler reads this cache, computes the inverse, calls `apply_state`. The JS-driven toggle path uses `toggle_click_through(current)` and skips the cache. - [ ] **Step 3: Commit**