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 {

Create a new clipboard.

Safety

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    }
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}

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}