From 88255d76bfc58c14bf6242c38d1742265eafa14a Mon Sep 17 00:00:00 2001 From: Chen Mulong Date: Mon, 16 Feb 2026 16:24:24 +0800 Subject: [PATCH] feat: add X11 fallback for Wayland compositors Add test_protocol_available() function to check if the wlr_data_control protocol is available before selecting the Wayland backend. This allows richclip to fall back to X11 when running on Wayland compositors that don't support the wlroots-specific protocol (e.g., WSLg, GNOME Mutter). Also improve error messages for bind_singleton failures to make debugging easier when the protocol is not available. --- src/clipboard/mod.rs | 11 +++++++++-- src/clipboard/wayland.rs | 10 ++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/clipboard/mod.rs b/src/clipboard/mod.rs index c533be6..e30ce68 100644 --- a/src/clipboard/mod.rs +++ b/src/clipboard/mod.rs @@ -41,9 +41,16 @@ pub use x::XBackend; #[cfg(target_os = "linux")] pub fn create_backend() -> Result> { + // Try Wayland first, but only if the required protocol is available if std::env::var("WAYLAND_DISPLAY").is_ok() { - return Ok(Box::new(WaylandBackend {})); - } else if std::env::var("DISPLAY").is_ok() { + if wayland::test_protocol_available() { + return Ok(Box::new(WaylandBackend {})); + } + log::debug!("Wayland wlr_data_control protocol not available, trying X11 fallback"); + } + + // Fall back to X11 + if std::env::var("DISPLAY").is_ok() { return Ok(Box::new(XBackend {})); } diff --git a/src/clipboard/wayland.rs b/src/clipboard/wayland.rs index b61589e..256be2a 100644 --- a/src/clipboard/wayland.rs +++ b/src/clipboard/wayland.rs @@ -21,6 +21,10 @@ use wayrs_protocols::wlr_data_control_unstable_v1::{ pub struct WaylandBackend {} +pub fn test_protocol_available() -> bool { + create_wayland_client::<()>().is_ok() +} + struct WaylandClient { conn: Connection, seat: WlSeat, @@ -62,8 +66,10 @@ fn create_wayland_client() -> Result> { conn.blocking_roundtrip() .context("Failed to call 'blocking_roundtrip'")?; - let seat: WlSeat = conn.bind_singleton(2..=4).context("")?; - let data_ctl_mgr: ZwlrDataControlManagerV1 = conn.bind_singleton(..=2).context("")?; + let seat: WlSeat = conn + .bind_singleton(2..=4) + .context("Failed to bind Wayland seat")?; + let data_ctl_mgr: ZwlrDataControlManagerV1 = conn.bind_singleton(..=2).context("Failed to bind data control manager (wlr_data_control_unstable_v1 protocol may not be available)")?; Ok(WaylandClient:: { conn,