Skip to main content

fret_platform_native/
clipboard.rs

1use fret_platform::clipboard::{Clipboard, ClipboardError, ClipboardErrorKind};
2
3#[cfg(all(
4    unix,
5    not(any(
6        target_os = "macos",
7        target_os = "android",
8        target_os = "ios",
9        target_os = "emscripten"
10    ))
11))]
12use arboard::{GetExtLinux as _, LinuxClipboardKind, SetExtLinux as _};
13
14pub struct NativeClipboard {
15    #[cfg(all(
16        not(target_arch = "wasm32"),
17        any(target_os = "windows", target_os = "macos", target_os = "linux")
18    ))]
19    inner: Option<arboard::Clipboard>,
20}
21
22pub type DesktopClipboard = NativeClipboard;
23
24impl Default for NativeClipboard {
25    fn default() -> Self {
26        #[cfg(all(
27            not(target_arch = "wasm32"),
28            any(target_os = "windows", target_os = "macos", target_os = "linux")
29        ))]
30        {
31            Self {
32                inner: arboard::Clipboard::new().ok(),
33            }
34        }
35
36        #[cfg(not(all(
37            not(target_arch = "wasm32"),
38            any(target_os = "windows", target_os = "macos", target_os = "linux")
39        )))]
40        {
41            Self {}
42        }
43    }
44}
45
46impl Clipboard for NativeClipboard {
47    fn set_text(&mut self, text: &str) -> Result<(), ClipboardError> {
48        #[cfg(all(
49            not(target_arch = "wasm32"),
50            any(target_os = "windows", target_os = "macos", target_os = "linux")
51        ))]
52        {
53            let Some(cb) = self.inner.as_mut() else {
54                return Err(ClipboardError {
55                    kind: ClipboardErrorKind::Unavailable,
56                    message: None,
57                });
58            };
59            cb.set_text(text.to_string()).map_err(|_| ClipboardError {
60                kind: ClipboardErrorKind::BackendError,
61                message: None,
62            })
63        }
64
65        #[cfg(not(all(
66            not(target_arch = "wasm32"),
67            any(target_os = "windows", target_os = "macos", target_os = "linux")
68        )))]
69        {
70            let _ = text;
71            Err(ClipboardError {
72                kind: ClipboardErrorKind::Unavailable,
73                message: None,
74            })
75        }
76    }
77
78    fn get_text(&mut self) -> Result<Option<String>, ClipboardError> {
79        #[cfg(all(
80            not(target_arch = "wasm32"),
81            any(target_os = "windows", target_os = "macos", target_os = "linux")
82        ))]
83        {
84            let Some(cb) = self.inner.as_mut() else {
85                return Err(ClipboardError {
86                    kind: ClipboardErrorKind::Unavailable,
87                    message: None,
88                });
89            };
90            match cb.get_text() {
91                Ok(text) => Ok(Some(text)),
92                Err(_) => Err(ClipboardError {
93                    kind: ClipboardErrorKind::BackendError,
94                    message: None,
95                }),
96            }
97        }
98
99        #[cfg(not(all(
100            not(target_arch = "wasm32"),
101            any(target_os = "windows", target_os = "macos", target_os = "linux")
102        )))]
103        {
104            Err(ClipboardError {
105                kind: ClipboardErrorKind::Unavailable,
106                message: None,
107            })
108        }
109    }
110}
111
112impl NativeClipboard {
113    pub fn set_primary_text(&mut self, text: &str) -> Result<(), ClipboardError> {
114        #[cfg(all(
115            not(target_arch = "wasm32"),
116            any(target_os = "windows", target_os = "macos", target_os = "linux")
117        ))]
118        {
119            #[cfg(all(
120                unix,
121                not(any(
122                    target_os = "macos",
123                    target_os = "android",
124                    target_os = "ios",
125                    target_os = "emscripten"
126                ))
127            ))]
128            {
129                let Some(cb) = self.inner.as_mut() else {
130                    return Err(ClipboardError {
131                        kind: ClipboardErrorKind::Unavailable,
132                        message: None,
133                    });
134                };
135                cb.set()
136                    .clipboard(LinuxClipboardKind::Primary)
137                    .text(text.to_string())
138                    .map_err(|_| ClipboardError {
139                        kind: ClipboardErrorKind::BackendError,
140                        message: None,
141                    })
142            }
143
144            #[cfg(not(all(
145                unix,
146                not(any(
147                    target_os = "macos",
148                    target_os = "android",
149                    target_os = "ios",
150                    target_os = "emscripten"
151                ))
152            )))]
153            {
154                let _ = text;
155                Err(ClipboardError {
156                    kind: ClipboardErrorKind::Unavailable,
157                    message: None,
158                })
159            }
160        }
161
162        #[cfg(not(all(
163            not(target_arch = "wasm32"),
164            any(target_os = "windows", target_os = "macos", target_os = "linux")
165        )))]
166        {
167            let _ = text;
168            Err(ClipboardError {
169                kind: ClipboardErrorKind::Unavailable,
170                message: None,
171            })
172        }
173    }
174
175    pub fn get_primary_text(&mut self) -> Result<Option<String>, ClipboardError> {
176        #[cfg(all(
177            not(target_arch = "wasm32"),
178            any(target_os = "windows", target_os = "macos", target_os = "linux")
179        ))]
180        {
181            #[cfg(all(
182                unix,
183                not(any(
184                    target_os = "macos",
185                    target_os = "android",
186                    target_os = "ios",
187                    target_os = "emscripten"
188                ))
189            ))]
190            {
191                let Some(cb) = self.inner.as_mut() else {
192                    return Err(ClipboardError {
193                        kind: ClipboardErrorKind::Unavailable,
194                        message: None,
195                    });
196                };
197                cb.get()
198                    .clipboard(LinuxClipboardKind::Primary)
199                    .text()
200                    .map(Some)
201                    .map_err(|_| ClipboardError {
202                        kind: ClipboardErrorKind::BackendError,
203                        message: None,
204                    })
205            }
206
207            #[cfg(not(all(
208                unix,
209                not(any(
210                    target_os = "macos",
211                    target_os = "android",
212                    target_os = "ios",
213                    target_os = "emscripten"
214                ))
215            )))]
216            {
217                Err(ClipboardError {
218                    kind: ClipboardErrorKind::Unavailable,
219                    message: None,
220                })
221            }
222        }
223
224        #[cfg(not(all(
225            not(target_arch = "wasm32"),
226            any(target_os = "windows", target_os = "macos", target_os = "linux")
227        )))]
228        {
229            Err(ClipboardError {
230                kind: ClipboardErrorKind::Unavailable,
231                message: None,
232            })
233        }
234    }
235}