From fe86356399138973f6d85e900f729e4709343310 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Fri, 27 Mar 2026 08:39:49 +0300 Subject: [PATCH] wayland: use arc-swap over Mutex for `FOCUSED_APP` for better concurrency Signed-off-by: NotAShelf Change-Id: Id6b40d5c533c35dda5bce7b852b836f26a6a6964 --- Cargo.lock | 10 ++++++++++ Cargo.toml | 3 ++- src/wayland/mod.rs | 19 +++++++++---------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe1039d..8ea168d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,15 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arc-swap" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6" +dependencies = [ + "rustversion", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -2409,6 +2418,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" name = "stash-clipboard" version = "0.3.6" dependencies = [ + "arc-swap", "base64", "blocking", "clap", diff --git a/Cargo.toml b/Cargo.toml index bfc3800..bae39c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ name = "stash" # actual binary name for Nix, Cargo, etc. path = "src/main.rs" [dependencies] +arc-swap = { version = "1.9.0", optional = true } base64 = "0.22.1" blocking = "1.6.2" clap = { version = "4.6.0", features = [ "derive", "env" ] } @@ -50,7 +51,7 @@ tempfile = "3.27.0" [features] default = [ "notifications", "use-toplevel" ] notifications = [ "dep:notify-rust" ] -use-toplevel = [ "dep:wayland-client", "dep:wayland-protocols-wlr" ] +use-toplevel = [ "dep:arc-swap", "dep:wayland-client", "dep:wayland-protocols-wlr" ] [profile.release] lto = true diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 9cfa765..38f6ff5 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -1,8 +1,9 @@ use std::{ collections::HashMap, - sync::{LazyLock, Mutex}, + sync::{Arc, LazyLock, Mutex}, }; +use arc_swap::ArcSwapOption; use log::debug; use wayland_client::{ Connection as WaylandConnection, @@ -17,7 +18,7 @@ use wayland_protocols_wlr::foreign_toplevel::v1::client::{ zwlr_foreign_toplevel_manager_v1::{self, ZwlrForeignToplevelManagerV1}, }; -static FOCUSED_APP: Mutex> = Mutex::new(None); +static FOCUSED_APP: ArcSwapOption = ArcSwapOption::const_empty(); static TOPLEVEL_APPS: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); @@ -32,12 +33,11 @@ pub fn init_wayland_state() { /// Get the currently focused window application name using Wayland protocols pub fn get_focused_window_app() -> Option { - // Try Wayland protocol first - if let Ok(focused) = FOCUSED_APP.lock() - && let Some(ref app) = *focused - { + // Load the focused app using lock-free arc-swap + let focused = FOCUSED_APP.load(); + if let Some(app) = focused.as_ref() { debug!("Found focused app via Wayland protocol: {app}"); - return Some(app.clone()); + return Some(app.to_string()); } debug!("No focused window detection method worked"); @@ -152,12 +152,11 @@ impl Dispatch for AppState { }) { debug!("Toplevel activated"); // Update focused app to the `app_id` of this handle - if let (Ok(apps), Ok(mut focused)) = - (TOPLEVEL_APPS.lock(), FOCUSED_APP.lock()) + if let Ok(apps) = TOPLEVEL_APPS.lock() && let Some(app_id) = apps.get(&handle_id) { debug!("Setting focused app to: {app_id}"); - *focused = Some(app_id.clone()); + FOCUSED_APP.store(Some(Arc::new(app_id.clone()))); } } },