1use sdl3::video::Window; 2 3pub struct Clipboard { 4 #[cfg(all(unix, not(target_os = "macos")))] 5 smithay: Option<smithay_clipboard::Clipboard>, 6 arboard: Option<arboard::Clipboard>, 7 fallback: String, 8} 9 10impl Clipboard { 11 /// Create a new clipboard. 12 /// 13 /// # Safety 14 /// 15 /// The returned clipboard must not outlive the referenced window. 16 #[allow(unused_variables)] // window param is not used on Windows/MacOS 17 pub unsafe fn new(window: &Window) -> Self { 18 Self { 19 #[cfg(all(unix, not(target_os = "macos")))] 20 smithay: unsafe { try_create_smithay_clipboard(window) }, 21 arboard: arboard::Clipboard::new().ok(), 22 fallback: String::new(), 23 } 24 } 25 26 pub fn load(&mut self) -> String { 27 // Prefer smithay-clipboard on Wayland; arboard's Wayland support has some caveats 28 #[cfg(all(unix, not(target_os = "macos")))] 29 if let Some(clipboard) = &self.smithay { 30 match clipboard.load() { 31 Ok(text) => return text, 32 Err(_) => { 33 log::error!( 34 "smithay-clipboard thread died; falling back to other clipboard implementations" 35 ); 36 self.smithay = None; 37 } 38 } 39 } 40 41 if let Some(clipboard) = &mut self.arboard 42 && let Ok(text) = clipboard.get_text() 43 { 44 return text; 45 } 46 47 self.fallback.clone() 48 } 49 50 pub fn store(&mut self, text: String) { 51 self.fallback.clone_from(&text); 52 53 #[cfg(all(unix, not(target_os = "macos")))] 54 if let Some(clipboard) = &self.smithay { 55 clipboard.store(text); 56 return; 57 } 58 59 if let Some(clipboard) = &mut self.arboard { 60 let _ = clipboard.set_text(text); 61 } 62 } 63} 64 65// SAFETY: The returned clipboard must not outlive the referenced window 66#[cfg(all(unix, not(target_os = "macos")))] 67unsafe fn try_create_smithay_clipboard(window: &Window) -> Option<smithay_clipboard::Clipboard> { 68 use raw_window_handle::{HasDisplayHandle, RawDisplayHandle}; 69 70 match window.display_handle().ok()?.as_raw() { 71 RawDisplayHandle::Wayland(handle) => { 72 // SAFETY: This is guaranteed to be a valid wl_display pointer 73 unsafe { Some(smithay_clipboard::Clipboard::new(handle.display.as_ptr())) } 74 } 75 _ => None, 76 } 77}