1use crate::{ffi, ContentFormats};
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 = "GdkContentProvider")]
51 pub struct ContentProvider(Object<ffi::GdkContentProvider, ffi::GdkContentProviderClass>);
52
53 match fn {
54 type_ => || ffi::gdk_content_provider_get_type(),
55 }
56}
57
58impl ContentProvider {
59 pub const NONE: Option<&'static ContentProvider> = None;
60
61 #[doc(alias = "gdk_content_provider_new_for_bytes")]
72 #[doc(alias = "new_for_bytes")]
73 pub fn for_bytes(mime_type: &str, bytes: &glib::Bytes) -> ContentProvider {
74 assert_initialized_main_thread!();
75 unsafe {
76 from_glib_full(ffi::gdk_content_provider_new_for_bytes(
77 mime_type.to_glib_none().0,
78 bytes.to_glib_none().0,
79 ))
80 }
81 }
82
83 #[doc(alias = "gdk_content_provider_new_for_value")]
91 #[doc(alias = "new_for_value")]
92 pub fn for_value(value: &glib::Value) -> ContentProvider {
93 assert_initialized_main_thread!();
94 unsafe {
95 from_glib_full(ffi::gdk_content_provider_new_for_value(
96 value.to_glib_none().0,
97 ))
98 }
99 }
100
101 #[doc(alias = "gdk_content_provider_new_union")]
126 pub fn new_union(providers: &[ContentProvider]) -> ContentProvider {
127 assert_initialized_main_thread!();
128 let n_providers = providers.len() as _;
129 unsafe {
130 from_glib_full(ffi::gdk_content_provider_new_union(
131 providers.to_glib_full(),
132 n_providers,
133 ))
134 }
135 }
136}
137
138pub trait ContentProviderExt: IsA<ContentProvider> + 'static {
144 #[doc(alias = "gdk_content_provider_content_changed")]
146 fn content_changed(&self) {
147 unsafe {
148 ffi::gdk_content_provider_content_changed(self.as_ref().to_glib_none().0);
149 }
150 }
151
152 #[doc(alias = "gdk_content_provider_ref_formats")]
158 #[doc(alias = "ref_formats")]
159 fn formats(&self) -> ContentFormats {
160 unsafe {
161 from_glib_full(ffi::gdk_content_provider_ref_formats(
162 self.as_ref().to_glib_none().0,
163 ))
164 }
165 }
166
167 #[doc(alias = "gdk_content_provider_ref_storable_formats")]
178 #[doc(alias = "ref_storable_formats")]
179 #[doc(alias = "storable-formats")]
180 fn storable_formats(&self) -> ContentFormats {
181 unsafe {
182 from_glib_full(ffi::gdk_content_provider_ref_storable_formats(
183 self.as_ref().to_glib_none().0,
184 ))
185 }
186 }
187
188 #[doc(alias = "gdk_content_provider_write_mime_type_async")]
207 fn write_mime_type_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
208 &self,
209 mime_type: &str,
210 stream: &impl IsA<gio::OutputStream>,
211 io_priority: glib::Priority,
212 cancellable: Option<&impl IsA<gio::Cancellable>>,
213 callback: P,
214 ) {
215 let main_context = glib::MainContext::ref_thread_default();
216 let is_main_context_owner = main_context.is_owner();
217 let has_acquired_main_context = (!is_main_context_owner)
218 .then(|| main_context.acquire().ok())
219 .flatten();
220 assert!(
221 is_main_context_owner || has_acquired_main_context.is_some(),
222 "Async operations only allowed if the thread is owning the MainContext"
223 );
224
225 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
226 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
227 unsafe extern "C" fn write_mime_type_async_trampoline<
228 P: FnOnce(Result<(), glib::Error>) + 'static,
229 >(
230 _source_object: *mut glib::gobject_ffi::GObject,
231 res: *mut gio::ffi::GAsyncResult,
232 user_data: glib::ffi::gpointer,
233 ) {
234 let mut error = std::ptr::null_mut();
235 ffi::gdk_content_provider_write_mime_type_finish(
236 _source_object as *mut _,
237 res,
238 &mut error,
239 );
240 let result = if error.is_null() {
241 Ok(())
242 } else {
243 Err(from_glib_full(error))
244 };
245 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
246 Box_::from_raw(user_data as *mut _);
247 let callback: P = callback.into_inner();
248 callback(result);
249 }
250 let callback = write_mime_type_async_trampoline::<P>;
251 unsafe {
252 ffi::gdk_content_provider_write_mime_type_async(
253 self.as_ref().to_glib_none().0,
254 mime_type.to_glib_none().0,
255 stream.as_ref().to_glib_none().0,
256 io_priority.into_glib(),
257 cancellable.map(|p| p.as_ref()).to_glib_none().0,
258 Some(callback),
259 Box_::into_raw(user_data) as *mut _,
260 );
261 }
262 }
263
264 fn write_mime_type_future(
265 &self,
266 mime_type: &str,
267 stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
268 io_priority: glib::Priority,
269 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
270 let mime_type = String::from(mime_type);
271 let stream = stream.clone();
272 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
273 obj.write_mime_type_async(
274 &mime_type,
275 &stream,
276 io_priority,
277 Some(cancellable),
278 move |res| {
279 send.resolve(res);
280 },
281 );
282 }))
283 }
284
285 #[doc(alias = "content-changed")]
287 fn connect_content_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
288 unsafe extern "C" fn content_changed_trampoline<
289 P: IsA<ContentProvider>,
290 F: Fn(&P) + 'static,
291 >(
292 this: *mut ffi::GdkContentProvider,
293 f: glib::ffi::gpointer,
294 ) {
295 let f: &F = &*(f as *const F);
296 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
297 }
298 unsafe {
299 let f: Box_<F> = Box_::new(f);
300 connect_raw(
301 self.as_ptr() as *mut _,
302 c"content-changed".as_ptr() as *const _,
303 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
304 content_changed_trampoline::<Self, F> as *const (),
305 )),
306 Box_::into_raw(f),
307 )
308 }
309 }
310
311 #[doc(alias = "formats")]
312 fn connect_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
313 unsafe extern "C" fn notify_formats_trampoline<
314 P: IsA<ContentProvider>,
315 F: Fn(&P) + 'static,
316 >(
317 this: *mut ffi::GdkContentProvider,
318 _param_spec: glib::ffi::gpointer,
319 f: glib::ffi::gpointer,
320 ) {
321 let f: &F = &*(f as *const F);
322 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
323 }
324 unsafe {
325 let f: Box_<F> = Box_::new(f);
326 connect_raw(
327 self.as_ptr() as *mut _,
328 c"notify::formats".as_ptr() as *const _,
329 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
330 notify_formats_trampoline::<Self, F> as *const (),
331 )),
332 Box_::into_raw(f),
333 )
334 }
335 }
336
337 #[doc(alias = "storable-formats")]
338 fn connect_storable_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
339 unsafe extern "C" fn notify_storable_formats_trampoline<
340 P: IsA<ContentProvider>,
341 F: Fn(&P) + 'static,
342 >(
343 this: *mut ffi::GdkContentProvider,
344 _param_spec: glib::ffi::gpointer,
345 f: glib::ffi::gpointer,
346 ) {
347 let f: &F = &*(f as *const F);
348 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
349 }
350 unsafe {
351 let f: Box_<F> = Box_::new(f);
352 connect_raw(
353 self.as_ptr() as *mut _,
354 c"notify::storable-formats".as_ptr() as *const _,
355 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
356 notify_storable_formats_trampoline::<Self, F> as *const (),
357 )),
358 Box_::into_raw(f),
359 )
360 }
361 }
362}
363
364impl<O: IsA<ContentProvider>> ContentProviderExt for O {}