From be1e4aad3f2ef7990b243ffa3f8035fa16846262 Mon Sep 17 00:00:00 2001 From: marcus hinz Date: Fri, 17 Jul 2026 00:17:17 +0200 Subject: [PATCH] =?UTF-8?q?Popup-Blur-Guard=20ohne=20Timer:=20Sperre=20f?= =?UTF-8?q?=C3=A4llt=20mit=20dem=20ersten=20Focused(true)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bisher löste ein Thread die Sperre nach 350 ms (geraten gegen das spuriose Focused(false), das KDE direkt nach show/set_focus feuert). Jetzt steht die Sperre ab dem Anzeigen und fällt deterministisch mit dem ersten echten Fokus-Event des Popups. --- src-tauri/src/app.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index ea3580b..d67bef4 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -9,8 +9,9 @@ use crate::domain::watcher::spawn_session_watcher; use crate::platform::Anchor; use crate::{commands, terminal}; -/// Sperrt das Auto-Hide des Popups bei Fokusverlust für einen Moment nach dem -/// Anzeigen (KDE-Erststart-Race). Als Tauri-State geführt. +/// Sperrt das Auto-Hide des Popups bei Fokusverlust nach dem Anzeigen, bis das +/// Popup einmal Focused(true) gemeldet hat (KDE feuert nach show/set_focus ein +/// spurioses Focused(false)). Als Tauri-State geführt. #[cfg(target_os = "linux")] pub(crate) struct PopupBlurGuard(pub(crate) std::sync::Arc); @@ -65,6 +66,7 @@ pub(crate) fn show_popup(app: &tauri::AppHandle, anchor: Anchor) { Anchor::Cursor => { #[cfg(target_os = "linux")] { + // Gelöst wird die Sperre vom ersten Focused(true) im Event-Handler. if let Some(g) = win.try_state::() { g.0.store(true, std::sync::atomic::Ordering::SeqCst); } @@ -74,15 +76,6 @@ pub(crate) fn show_popup(app: &tauri::AppHandle, anchor: Anchor) { let _ = w.center(); } } - // Guard nach kurzer Zeit lösen — danach schließt Fokusverlust wieder - // normal. - let g2 = win.clone(); - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(350)); - if let Some(g) = g2.try_state::() { - g.0.store(false, std::sync::atomic::Ordering::SeqCst); - } - }); } } // GNOME-Extension/KWin: der Compositor positioniert selbst. @@ -197,21 +190,26 @@ pub(crate) fn main_builder() -> tauri::Builder { window.hide().unwrap(); } // Popup schließt bei Fokusverlust. - if let tauri::WindowEvent::Focused(false) = event { + if let tauri::WindowEvent::Focused(focused) = event { if window.label() == "popup" { - // KDE feuert direkt nach show/set_focus ein Focused(false) — ohne - // diese kurze Sperre verschwände das Popup sofort wieder (erst der - // zweite Klick hielte). GNOME/macOS setzen die Sperre nie. + // KDE feuert direkt nach show/set_focus ein spurioses Focused(false), + // vor dem echten Fokus. Die Sperre steht ab dem Anzeigen und fällt mit + // dem ersten Focused(true) — das spuriose Blur läuft ins Leere. + // GNOME/macOS setzen die Sperre nie. #[cfg(target_os = "linux")] { use tauri::Manager; if let Some(g) = window.try_state::() { - if g.0.load(std::sync::atomic::Ordering::SeqCst) { + if *focused { + g.0.store(false, std::sync::atomic::Ordering::SeqCst); + } else if g.0.load(std::sync::atomic::Ordering::SeqCst) { return; } } } - let _ = window.hide(); + if !focused { + let _ = window.hide(); + } } } })