gdk4/
clipboard.rs
1use std::{future, pin::Pin, ptr};
4
5use glib::{translate::*, GString};
6
7use crate::{ffi, prelude::*, Clipboard};
8
9impl Clipboard {
10 #[doc(alias = "gdk_clipboard_read_async")]
24 pub fn read_async<Q: FnOnce(Result<(gio::InputStream, GString), glib::Error>) + 'static>(
25 &self,
26 mime_types: &[&str],
27 io_priority: glib::Priority,
28 cancellable: Option<&impl IsA<gio::Cancellable>>,
29 callback: Q,
30 ) {
31 let main_context = glib::MainContext::ref_thread_default();
32 let is_main_context_owner = main_context.is_owner();
33 let has_acquired_main_context = (!is_main_context_owner)
34 .then(|| main_context.acquire().ok())
35 .flatten();
36 assert!(
37 is_main_context_owner || has_acquired_main_context.is_some(),
38 "Async operations only allowed if the thread is owning the MainContext"
39 );
40
41 let user_data: Box<glib::thread_guard::ThreadGuard<Q>> =
42 Box::new(glib::thread_guard::ThreadGuard::new(callback));
43 unsafe extern "C" fn read_async_trampoline<
44 Q: FnOnce(Result<(gio::InputStream, GString), glib::Error>) + 'static,
45 >(
46 _source_object: *mut glib::gobject_ffi::GObject,
47 res: *mut gio::ffi::GAsyncResult,
48 user_data: glib::ffi::gpointer,
49 ) {
50 let mut error = ptr::null_mut();
51 let mut out_mime_type = ptr::null();
52 let ret = ffi::gdk_clipboard_read_finish(
53 _source_object as *mut _,
54 res,
55 &mut out_mime_type,
56 &mut error,
57 );
58 let result = if error.is_null() {
59 Ok((from_glib_full(ret), from_glib_none(out_mime_type)))
60 } else {
61 Err(from_glib_full(error))
62 };
63 let callback: Box<glib::thread_guard::ThreadGuard<Q>> =
64 Box::from_raw(user_data as *mut _);
65 let callback = callback.into_inner();
66 callback(result);
67 }
68 let callback = read_async_trampoline::<Q>;
69 unsafe {
70 ffi::gdk_clipboard_read_async(
71 self.to_glib_none().0,
72 mime_types.to_glib_none().0,
73 io_priority.into_glib(),
74 cancellable.map(|p| p.as_ref()).to_glib_none().0,
75 Some(callback),
76 Box::into_raw(user_data) as *mut _,
77 );
78 }
79 }
80
81 #[allow(clippy::type_complexity)]
82 pub fn read_future(
83 &self,
84 mime_types: &[&str],
85 io_priority: glib::Priority,
86 ) -> Pin<
87 Box<
88 dyn future::Future<Output = Result<(gio::InputStream, GString), glib::Error>> + 'static,
89 >,
90 > {
91 let mime_types = mime_types
92 .iter()
93 .copied()
94 .map(String::from)
95 .collect::<Vec<_>>();
96 Box::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
97 let mime_types = mime_types.iter().map(|s| s.as_str()).collect::<Vec<_>>();
98 obj.read_async(&mime_types, io_priority, Some(cancellable), move |res| {
99 send.resolve(res);
100 });
101 }))
102 }
103
104 #[doc(alias = "gdk_clipboard_set")]
120 #[doc(alias = "gdk_clipboard_set_value")]
121 #[doc(alias = "gdk_clipboard_set_valist")]
122 #[doc(alias = "set_value")]
123 #[doc(alias = "set_valist")]
124 pub fn set(&self, value: &impl ToValue) {
125 unsafe {
126 ffi::gdk_clipboard_set_value(self.to_glib_none().0, value.to_value().to_glib_none().0);
127 }
128 }
129}