1use crate::{ffi, ContentFormats, ContentProvider, Display, Texture};
6use glib::{
7 object::ObjectType as _,
8 prelude::*,
9 signal::{connect_raw, SignalHandlerId},
10 translate::*,
11};
12use std::{boxed::Box as Box_, pin::Pin};
13
14glib::wrapper! {
15 #[doc(alias = "GdkClipboard")]
16 pub struct Clipboard(Object<ffi::GdkClipboard>);
17
18 match fn {
19 type_ => || ffi::gdk_clipboard_get_type(),
20 }
21}
22
23impl Clipboard {
24 #[doc(alias = "gdk_clipboard_get_content")]
25 #[doc(alias = "get_content")]
26 pub fn content(&self) -> Option<ContentProvider> {
27 unsafe { from_glib_none(ffi::gdk_clipboard_get_content(self.to_glib_none().0)) }
28 }
29
30 #[doc(alias = "gdk_clipboard_get_display")]
31 #[doc(alias = "get_display")]
32 pub fn display(&self) -> Display {
33 unsafe { from_glib_none(ffi::gdk_clipboard_get_display(self.to_glib_none().0)) }
34 }
35
36 #[doc(alias = "gdk_clipboard_get_formats")]
37 #[doc(alias = "get_formats")]
38 pub fn formats(&self) -> ContentFormats {
39 unsafe { from_glib_none(ffi::gdk_clipboard_get_formats(self.to_glib_none().0)) }
40 }
41
42 #[doc(alias = "gdk_clipboard_is_local")]
43 #[doc(alias = "local")]
44 pub fn is_local(&self) -> bool {
45 unsafe { from_glib(ffi::gdk_clipboard_is_local(self.to_glib_none().0)) }
46 }
47
48 #[doc(alias = "gdk_clipboard_read_text_async")]
49 pub fn read_text_async<P: FnOnce(Result<Option<glib::GString>, glib::Error>) + 'static>(
50 &self,
51 cancellable: Option<&impl IsA<gio::Cancellable>>,
52 callback: P,
53 ) {
54 let main_context = glib::MainContext::ref_thread_default();
55 let is_main_context_owner = main_context.is_owner();
56 let has_acquired_main_context = (!is_main_context_owner)
57 .then(|| main_context.acquire().ok())
58 .flatten();
59 assert!(
60 is_main_context_owner || has_acquired_main_context.is_some(),
61 "Async operations only allowed if the thread is owning the MainContext"
62 );
63
64 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
65 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
66 unsafe extern "C" fn read_text_async_trampoline<
67 P: FnOnce(Result<Option<glib::GString>, glib::Error>) + 'static,
68 >(
69 _source_object: *mut glib::gobject_ffi::GObject,
70 res: *mut gio::ffi::GAsyncResult,
71 user_data: glib::ffi::gpointer,
72 ) {
73 let mut error = std::ptr::null_mut();
74 let ret =
75 ffi::gdk_clipboard_read_text_finish(_source_object as *mut _, res, &mut error);
76 let result = if error.is_null() {
77 Ok(from_glib_full(ret))
78 } else {
79 Err(from_glib_full(error))
80 };
81 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
82 Box_::from_raw(user_data as *mut _);
83 let callback: P = callback.into_inner();
84 callback(result);
85 }
86 let callback = read_text_async_trampoline::<P>;
87 unsafe {
88 ffi::gdk_clipboard_read_text_async(
89 self.to_glib_none().0,
90 cancellable.map(|p| p.as_ref()).to_glib_none().0,
91 Some(callback),
92 Box_::into_raw(user_data) as *mut _,
93 );
94 }
95 }
96
97 pub fn read_text_future(
98 &self,
99 ) -> Pin<
100 Box_<
101 dyn std::future::Future<Output = Result<Option<glib::GString>, glib::Error>> + 'static,
102 >,
103 > {
104 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
105 obj.read_text_async(Some(cancellable), move |res| {
106 send.resolve(res);
107 });
108 }))
109 }
110
111 #[doc(alias = "gdk_clipboard_read_texture_async")]
112 pub fn read_texture_async<P: FnOnce(Result<Option<Texture>, glib::Error>) + 'static>(
113 &self,
114 cancellable: Option<&impl IsA<gio::Cancellable>>,
115 callback: P,
116 ) {
117 let main_context = glib::MainContext::ref_thread_default();
118 let is_main_context_owner = main_context.is_owner();
119 let has_acquired_main_context = (!is_main_context_owner)
120 .then(|| main_context.acquire().ok())
121 .flatten();
122 assert!(
123 is_main_context_owner || has_acquired_main_context.is_some(),
124 "Async operations only allowed if the thread is owning the MainContext"
125 );
126
127 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
128 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
129 unsafe extern "C" fn read_texture_async_trampoline<
130 P: FnOnce(Result<Option<Texture>, glib::Error>) + 'static,
131 >(
132 _source_object: *mut glib::gobject_ffi::GObject,
133 res: *mut gio::ffi::GAsyncResult,
134 user_data: glib::ffi::gpointer,
135 ) {
136 let mut error = std::ptr::null_mut();
137 let ret =
138 ffi::gdk_clipboard_read_texture_finish(_source_object as *mut _, res, &mut error);
139 let result = if error.is_null() {
140 Ok(from_glib_full(ret))
141 } else {
142 Err(from_glib_full(error))
143 };
144 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
145 Box_::from_raw(user_data as *mut _);
146 let callback: P = callback.into_inner();
147 callback(result);
148 }
149 let callback = read_texture_async_trampoline::<P>;
150 unsafe {
151 ffi::gdk_clipboard_read_texture_async(
152 self.to_glib_none().0,
153 cancellable.map(|p| p.as_ref()).to_glib_none().0,
154 Some(callback),
155 Box_::into_raw(user_data) as *mut _,
156 );
157 }
158 }
159
160 pub fn read_texture_future(
161 &self,
162 ) -> Pin<Box_<dyn std::future::Future<Output = Result<Option<Texture>, glib::Error>> + 'static>>
163 {
164 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
165 obj.read_texture_async(Some(cancellable), move |res| {
166 send.resolve(res);
167 });
168 }))
169 }
170
171 #[doc(alias = "gdk_clipboard_read_value_async")]
172 pub fn read_value_async<P: FnOnce(Result<glib::Value, glib::Error>) + 'static>(
173 &self,
174 type_: glib::types::Type,
175 io_priority: glib::Priority,
176 cancellable: Option<&impl IsA<gio::Cancellable>>,
177 callback: P,
178 ) {
179 let main_context = glib::MainContext::ref_thread_default();
180 let is_main_context_owner = main_context.is_owner();
181 let has_acquired_main_context = (!is_main_context_owner)
182 .then(|| main_context.acquire().ok())
183 .flatten();
184 assert!(
185 is_main_context_owner || has_acquired_main_context.is_some(),
186 "Async operations only allowed if the thread is owning the MainContext"
187 );
188
189 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
190 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
191 unsafe extern "C" fn read_value_async_trampoline<
192 P: FnOnce(Result<glib::Value, glib::Error>) + 'static,
193 >(
194 _source_object: *mut glib::gobject_ffi::GObject,
195 res: *mut gio::ffi::GAsyncResult,
196 user_data: glib::ffi::gpointer,
197 ) {
198 let mut error = std::ptr::null_mut();
199 let ret =
200 ffi::gdk_clipboard_read_value_finish(_source_object as *mut _, res, &mut error);
201 let result = if error.is_null() {
202 Ok(from_glib_none(ret))
203 } else {
204 Err(from_glib_full(error))
205 };
206 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
207 Box_::from_raw(user_data as *mut _);
208 let callback: P = callback.into_inner();
209 callback(result);
210 }
211 let callback = read_value_async_trampoline::<P>;
212 unsafe {
213 ffi::gdk_clipboard_read_value_async(
214 self.to_glib_none().0,
215 type_.into_glib(),
216 io_priority.into_glib(),
217 cancellable.map(|p| p.as_ref()).to_glib_none().0,
218 Some(callback),
219 Box_::into_raw(user_data) as *mut _,
220 );
221 }
222 }
223
224 pub fn read_value_future(
225 &self,
226 type_: glib::types::Type,
227 io_priority: glib::Priority,
228 ) -> Pin<Box_<dyn std::future::Future<Output = Result<glib::Value, glib::Error>> + 'static>>
229 {
230 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
231 obj.read_value_async(type_, io_priority, Some(cancellable), move |res| {
232 send.resolve(res);
233 });
234 }))
235 }
236
237 #[doc(alias = "gdk_clipboard_set_content")]
238 pub fn set_content(
239 &self,
240 provider: Option<&impl IsA<ContentProvider>>,
241 ) -> Result<(), glib::error::BoolError> {
242 unsafe {
243 glib::result_from_gboolean!(
244 ffi::gdk_clipboard_set_content(
245 self.to_glib_none().0,
246 provider.map(|p| p.as_ref()).to_glib_none().0
247 ),
248 "Can't set new clipboard content"
249 )
250 }
251 }
252
253 #[doc(alias = "gdk_clipboard_set_text")]
254 pub fn set_text(&self, text: &str) {
255 unsafe {
256 ffi::gdk_clipboard_set_text(self.to_glib_none().0, text.to_glib_none().0);
257 }
258 }
259
260 #[doc(alias = "gdk_clipboard_set_texture")]
261 pub fn set_texture(&self, texture: &impl IsA<Texture>) {
262 unsafe {
263 ffi::gdk_clipboard_set_texture(
264 self.to_glib_none().0,
265 texture.as_ref().to_glib_none().0,
266 );
267 }
268 }
269
270 #[doc(alias = "gdk_clipboard_store_async")]
271 pub fn store_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
272 &self,
273 io_priority: glib::Priority,
274 cancellable: Option<&impl IsA<gio::Cancellable>>,
275 callback: P,
276 ) {
277 let main_context = glib::MainContext::ref_thread_default();
278 let is_main_context_owner = main_context.is_owner();
279 let has_acquired_main_context = (!is_main_context_owner)
280 .then(|| main_context.acquire().ok())
281 .flatten();
282 assert!(
283 is_main_context_owner || has_acquired_main_context.is_some(),
284 "Async operations only allowed if the thread is owning the MainContext"
285 );
286
287 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
288 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
289 unsafe extern "C" fn store_async_trampoline<
290 P: FnOnce(Result<(), glib::Error>) + 'static,
291 >(
292 _source_object: *mut glib::gobject_ffi::GObject,
293 res: *mut gio::ffi::GAsyncResult,
294 user_data: glib::ffi::gpointer,
295 ) {
296 let mut error = std::ptr::null_mut();
297 ffi::gdk_clipboard_store_finish(_source_object as *mut _, res, &mut error);
298 let result = if error.is_null() {
299 Ok(())
300 } else {
301 Err(from_glib_full(error))
302 };
303 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
304 Box_::from_raw(user_data as *mut _);
305 let callback: P = callback.into_inner();
306 callback(result);
307 }
308 let callback = store_async_trampoline::<P>;
309 unsafe {
310 ffi::gdk_clipboard_store_async(
311 self.to_glib_none().0,
312 io_priority.into_glib(),
313 cancellable.map(|p| p.as_ref()).to_glib_none().0,
314 Some(callback),
315 Box_::into_raw(user_data) as *mut _,
316 );
317 }
318 }
319
320 pub fn store_future(
321 &self,
322 io_priority: glib::Priority,
323 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
324 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
325 obj.store_async(io_priority, Some(cancellable), move |res| {
326 send.resolve(res);
327 });
328 }))
329 }
330
331 #[doc(alias = "changed")]
332 pub fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
333 unsafe extern "C" fn changed_trampoline<F: Fn(&Clipboard) + 'static>(
334 this: *mut ffi::GdkClipboard,
335 f: glib::ffi::gpointer,
336 ) {
337 let f: &F = &*(f as *const F);
338 f(&from_glib_borrow(this))
339 }
340 unsafe {
341 let f: Box_<F> = Box_::new(f);
342 connect_raw(
343 self.as_ptr() as *mut _,
344 c"changed".as_ptr() as *const _,
345 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
346 changed_trampoline::<F> as *const (),
347 )),
348 Box_::into_raw(f),
349 )
350 }
351 }
352
353 #[doc(alias = "content")]
354 pub fn connect_content_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
355 unsafe extern "C" fn notify_content_trampoline<F: Fn(&Clipboard) + 'static>(
356 this: *mut ffi::GdkClipboard,
357 _param_spec: glib::ffi::gpointer,
358 f: glib::ffi::gpointer,
359 ) {
360 let f: &F = &*(f as *const F);
361 f(&from_glib_borrow(this))
362 }
363 unsafe {
364 let f: Box_<F> = Box_::new(f);
365 connect_raw(
366 self.as_ptr() as *mut _,
367 c"notify::content".as_ptr() as *const _,
368 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
369 notify_content_trampoline::<F> as *const (),
370 )),
371 Box_::into_raw(f),
372 )
373 }
374 }
375
376 #[doc(alias = "formats")]
377 pub fn connect_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
378 unsafe extern "C" fn notify_formats_trampoline<F: Fn(&Clipboard) + 'static>(
379 this: *mut ffi::GdkClipboard,
380 _param_spec: glib::ffi::gpointer,
381 f: glib::ffi::gpointer,
382 ) {
383 let f: &F = &*(f as *const F);
384 f(&from_glib_borrow(this))
385 }
386 unsafe {
387 let f: Box_<F> = Box_::new(f);
388 connect_raw(
389 self.as_ptr() as *mut _,
390 c"notify::formats".as_ptr() as *const _,
391 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
392 notify_formats_trampoline::<F> as *const (),
393 )),
394 Box_::into_raw(f),
395 )
396 }
397 }
398
399 #[doc(alias = "local")]
400 pub fn connect_local_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
401 unsafe extern "C" fn notify_local_trampoline<F: Fn(&Clipboard) + 'static>(
402 this: *mut ffi::GdkClipboard,
403 _param_spec: glib::ffi::gpointer,
404 f: glib::ffi::gpointer,
405 ) {
406 let f: &F = &*(f as *const F);
407 f(&from_glib_borrow(this))
408 }
409 unsafe {
410 let f: Box_<F> = Box_::new(f);
411 connect_raw(
412 self.as_ptr() as *mut _,
413 c"notify::local".as_ptr() as *const _,
414 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
415 notify_local_trampoline::<F> as *const (),
416 )),
417 Box_::into_raw(f),
418 )
419 }
420 }
421}