From 319db02e5219c557c8f03b0e33a8eb4075cabb85 Mon Sep 17 00:00:00 2001 From: leyoda Date: Fri, 24 Apr 2026 06:50:48 +0200 Subject: [PATCH] yoda: gate clipboard_x11 behind an opt-in feature Upstream pulled clipboard_x11 unconditionally on unix, which drags x11rb + x11rb-protocol and ~500 symbols of X11 clipboard code into every Wayland-only iced build. Add an x11 feature (default-on for compat) that gates: - the clipboard_x11 workspace dep (now optional) - `pub use clipboard_x11 as x11` re-export - the Clipboard::X11 enum variant - every match arm that handles it - the fallback branch in `unsafe fn connect` (returns a helpful error when called with a non-Wayland display handle) Wayland-only builds set `window_clipboard = { ..., default-features = false, features = ["wayland"] }` and skip the x11 backend entirely. --- Cargo.toml | 14 ++++++++++++-- src/platform/linux.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2aacaa0..4d13334 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,16 @@ readme = "README.md" keywords = ["clipboard", "window", "ui", "gui", "raw-window-handle"] categories = ["gui"] +[features] +# Yoda: put the unix clipboard backends behind opt-in features. Upstream +# pulled both X11 + Wayland unconditionally on unix — pure bloat for +# Wayland-only builds (clipboard_x11 pulls x11rb + its protocol machinery). +# Default keeps both enabled to preserve upstream behaviour; yoda consumers +# pass default-features=false + "wayland" at the dep declaration. +default = ["x11", "wayland"] +x11 = ["dep:clipboard_x11"] +wayland = ["dep:clipboard_wayland"] + [dependencies] raw-window-handle = { version = "0.6", features = ["std"] } thiserror = "1.0" @@ -24,8 +34,8 @@ clipboard-win = { version = "5.0", features = ["std"] } clipboard_macos = { version = "0.1", path = "./macos" } [target.'cfg(all(unix, not(any(target_os="macos", target_os="android", target_os="emscripten", target_os="ios", target_os="redox"))))'.dependencies] -clipboard_x11 = { version = "0.4.2", path = "./x11" } -clipboard_wayland = { version = "0.2.2", path = "./wayland" } +clipboard_x11 = { version = "0.4.2", path = "./x11", optional = true } +clipboard_wayland = { version = "0.2.2", path = "./wayland", optional = true } [dev-dependencies] rand = "0.8" diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 3d953f1..755dfb9 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -11,10 +11,12 @@ use std::{borrow::Cow, error::Error, sync::Arc}; use wayland::DndSender; pub use clipboard_wayland as wayland; +#[cfg(feature = "x11")] pub use clipboard_x11 as x11; pub enum Clipboard { Wayland(wayland::Clipboard), + #[cfg(feature = "x11")] X11(x11::Clipboard), } @@ -22,6 +24,7 @@ impl ClipboardProvider for Clipboard { fn read(&self) -> Result> { match self { Clipboard::Wayland(c) => c.read(), + #[cfg(feature = "x11")] Clipboard::X11(c) => c.read().map_err(Box::from), } } @@ -29,6 +32,7 @@ impl ClipboardProvider for Clipboard { fn write(&mut self, contents: String) -> Result<(), Box> { match self { Clipboard::Wayland(c) => c.write(contents), + #[cfg(feature = "x11")] Clipboard::X11(c) => c.write(contents).map_err(Box::from), } } @@ -36,6 +40,7 @@ impl ClipboardProvider for Clipboard { fn read_primary(&self) -> Option>> { match self { Clipboard::Wayland(c) => Some(c.read_primary()), + #[cfg(feature = "x11")] Clipboard::X11(c) => Some(c.read_primary().map_err(Box::from)), } } @@ -46,6 +51,7 @@ impl ClipboardProvider for Clipboard { ) -> Option>> { match self { Clipboard::Wayland(c) => Some(c.write_primary(contents)), + #[cfg(feature = "x11")] Clipboard::X11(c) => { Some(c.write_primary(contents).map_err(Box::from)) } @@ -61,6 +67,7 @@ impl ClipboardProvider for Clipboard { let ret = c.read_data::>(); Some(ret.map(|ret| ret.0)) } + #[cfg(feature = "x11")] Clipboard::X11(_) => None, } } @@ -76,6 +83,7 @@ impl ClipboardProvider for Clipboard { Clipboard::Wayland(c) => { Some(c.write_data::>(contents)) } + #[cfg(feature = "x11")] Clipboard::X11(_) => None, } } @@ -89,6 +97,7 @@ impl ClipboardProvider for Clipboard { let ret = c.read_primary_data::>(); Some(ret.map(|ret| ret.0)) } + #[cfg(feature = "x11")] Clipboard::X11(_) => None, } } @@ -99,6 +108,7 @@ impl ClipboardProvider for Clipboard { ) -> Option, String), Box>> { match self { Clipboard::Wayland(c) => Some(c.read_primary_raw(allowed)), + #[cfg(feature = "x11")] Clipboard::X11(_) => None, } } @@ -109,6 +119,7 @@ impl ClipboardProvider for Clipboard { ) -> Option, String), Box>> { match self { Clipboard::Wayland(c) => Some(c.read_raw(allowed)), + #[cfg(feature = "x11")] Clipboard::X11(_) => None, } } @@ -124,6 +135,7 @@ impl ClipboardProvider for Clipboard { Clipboard::Wayland(c) => { Some(c.write_primary_data::>(contents)) } + #[cfg(feature = "x11")] Clipboard::X11(_) => None, } } @@ -136,6 +148,7 @@ impl DndProvider for Clipboard { ) { match self { Clipboard::Wayland(c) => c.init_dnd(DndSender(Arc::from(tx))), + #[cfg(feature = "x11")] Clipboard::X11(_) => {} } } @@ -156,6 +169,7 @@ impl DndProvider for Clipboard { content, actions, ), + #[cfg(feature = "x11")] Clipboard::X11(_) => {} } } @@ -163,6 +177,7 @@ impl DndProvider for Clipboard { fn end_dnd(&self) { match self { Clipboard::Wayland(c) => c.end_dnd(), + #[cfg(feature = "x11")] Clipboard::X11(_) => {} } } @@ -176,6 +191,7 @@ impl DndProvider for Clipboard { Clipboard::Wayland(c) => { c.register_dnd_destination(surface, rectangles) } + #[cfg(feature = "x11")] Clipboard::X11(_) => {} } } @@ -183,6 +199,7 @@ impl DndProvider for Clipboard { fn set_action(&self, action: DndAction) { match self { Clipboard::Wayland(c) => c.set_action(action), + #[cfg(feature = "x11")] Clipboard::X11(_) => {} } } @@ -193,6 +210,7 @@ impl DndProvider for Clipboard { ) -> std::io::Result { match self { Clipboard::Wayland(c) => c.peek_offer::(mime_type), + #[cfg(feature = "x11")] Clipboard::X11(_) => Err(std::io::Error::new( std::io::ErrorKind::Other, "DnD not supported", @@ -208,7 +226,15 @@ pub unsafe fn connect( RawDisplayHandle::Wayland(handle) => Clipboard::Wayland( wayland::Clipboard::connect(handle.display.as_ptr()), ) as _, + #[cfg(feature = "x11")] _ => Clipboard::X11(x11::Clipboard::connect()?) as _, + #[cfg(not(feature = "x11"))] + _ => { + return Err(Box::from( + "Yoda window_clipboard: X11 feature disabled; \ + non-Wayland display handles are not supported", + )) + } }; Ok(clipboard)