logiguard fork: add Window::activate_with_token for externally-minted xdg-activation tokens
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
Track duplicate bot effectiveness / classify-closed-issue (push) Has been cancelled
Track duplicate bot effectiveness / classify-open (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
Update Duplicate Magnets Issue / update-duplicate-magnets (push) Has been cancelled
Close Stale Issues / stale (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled

Mutter honors xdg_activation_v1.activate() only when the token carries a
valid grab serial on the surface being activated. activate_window() mints
its own token using this client's KeyboardEnter serial, which is stale
after a tray-menu click (the tray popup held focus, not the app window).

Add Window::activate_with_token(&str) so callers can feed in a token
minted by GTK (via g_app_launch_context_get_startup_notify_id) on the
connection that actually received the user gesture. That token carries
the real grab serial + focused surface, which Mutter accepts.

- crates/gpui/src/platform.rs: PlatformWindow::activate_with_token with
  default impl that falls back to activate().
- crates/gpui/src/window.rs: public Window::activate_with_token.
- crates/gpui_linux/src/linux/wayland/window.rs: WaylandWindow impl that
  issues xdg_activation_v1.activate(token, surface) directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 22:19:17 +03:30
parent b72a46db68
commit 237fd0ba93
3 changed files with 35 additions and 0 deletions

View File

@@ -623,6 +623,16 @@ pub trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
answers: &[PromptButton],
) -> Option<oneshot::Receiver<usize>>;
fn activate(&self);
/// Activate with an externally-generated xdg-activation token.
/// Wayland: issues `xdg_activation_v1.activate(token, surface)` directly,
/// bypassing this client's own (possibly stale) serial. The caller is
/// responsible for obtaining a token that carries a valid grab serial —
/// e.g. from GTK's `GdkAppLaunchContext::startup_notify_id()` on the
/// connection that received the user gesture.
/// Non-Wayland backends: ignore the token and fall back to `activate()`.
fn activate_with_token(&self, _token: &str) {
self.activate();
}
fn is_active(&self) -> bool;
fn is_hovered(&self) -> bool;
fn background_appearance(&self) -> WindowBackgroundAppearance;

View File

@@ -4883,6 +4883,15 @@ impl Window {
self.platform_window.activate();
}
/// Focus the current window using an externally-generated xdg-activation token.
/// On Wayland this issues `xdg_activation_v1.activate(token, surface)`, which
/// Mutter honors when the token carries a valid grab serial (e.g. minted by
/// GTK on the connection that received the user gesture). On other platforms
/// this is equivalent to [`activate_window`](Self::activate_window).
pub fn activate_with_token(&self, token: &str) {
self.platform_window.activate_with_token(token);
}
/// Minimize the current window at the platform level.
pub fn minimize_window(&self) {
self.platform_window.minimize();

View File

@@ -1263,6 +1263,22 @@ impl PlatformWindow for WaylandWindow {
}
}
fn activate_with_token(&self, token: &str) {
// Activate using a token minted externally (e.g. by GTK on the
// connection that received the tray-click gesture). We pass it straight
// to `xdg_activation_v1.activate(token, surface)` — Mutter honors it
// because the token carries a valid grab serial + the focused surface,
// unlike `activate()` above which may use a stale serial.
let state = self.borrow();
if let Some(activation) = &state.globals.activation {
activation.activate(token.to_string(), &state.surface);
} else {
// No xdg-activation global (e.g. older compositor): best-effort fallback.
drop(state);
self.activate();
}
}
fn is_active(&self) -> bool {
self.borrow().active
}