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}