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
138mod sealed {
139 pub trait Sealed {}
140 impl<T: super::IsA<super::ContentProvider>> Sealed for T {}
141}
142
143pub trait ContentProviderExt: IsA<ContentProvider> + sealed::Sealed + 'static {
149 #[doc(alias = "gdk_content_provider_content_changed")]
151 fn content_changed(&self) {
152 unsafe {
153 ffi::gdk_content_provider_content_changed(self.as_ref().to_glib_none().0);
154 }
155 }
156
157 #[doc(alias = "gdk_content_provider_ref_formats")]
163 #[doc(alias = "ref_formats")]
164 fn formats(&self) -> ContentFormats {
165 unsafe {
166 from_glib_full(ffi::gdk_content_provider_ref_formats(
167 self.as_ref().to_glib_none().0,
168 ))
169 }
170 }
171
172 #[doc(alias = "gdk_content_provider_ref_storable_formats")]
183 #[doc(alias = "ref_storable_formats")]
184 #[doc(alias = "storable-formats")]
185 fn storable_formats(&self) -> ContentFormats {
186 unsafe {
187 from_glib_full(ffi::gdk_content_provider_ref_storable_formats(
188 self.as_ref().to_glib_none().0,
189 ))
190 }
191 }
192
193 #[doc(alias = "gdk_content_provider_write_mime_type_async")]
212 fn write_mime_type_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
213 &self,
214 mime_type: &str,
215 stream: &impl IsA<gio::OutputStream>,
216 io_priority: glib::Priority,
217 cancellable: Option<&impl IsA<gio::Cancellable>>,
218 callback: P,
219 ) {
220 let main_context = glib::MainContext::ref_thread_default();
221 let is_main_context_owner = main_context.is_owner();
222 let has_acquired_main_context = (!is_main_context_owner)
223 .then(|| main_context.acquire().ok())
224 .flatten();
225 assert!(
226 is_main_context_owner || has_acquired_main_context.is_some(),
227 "Async operations only allowed if the thread is owning the MainContext"
228 );
229
230 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
231 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
232 unsafe extern "C" fn write_mime_type_async_trampoline<
233 P: FnOnce(Result<(), glib::Error>) + 'static,
234 >(
235 _source_object: *mut glib::gobject_ffi::GObject,
236 res: *mut gio::ffi::GAsyncResult,
237 user_data: glib::ffi::gpointer,
238 ) {
239 let mut error = std::ptr::null_mut();
240 let _ = ffi::gdk_content_provider_write_mime_type_finish(
241 _source_object as *mut _,
242 res,
243 &mut error,
244 );
245 let result = if error.is_null() {
246 Ok(())
247 } else {
248 Err(from_glib_full(error))
249 };
250 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
251 Box_::from_raw(user_data as *mut _);
252 let callback: P = callback.into_inner();
253 callback(result);
254 }
255 let callback = write_mime_type_async_trampoline::<P>;
256 unsafe {
257 ffi::gdk_content_provider_write_mime_type_async(
258 self.as_ref().to_glib_none().0,
259 mime_type.to_glib_none().0,
260 stream.as_ref().to_glib_none().0,
261 io_priority.into_glib(),
262 cancellable.map(|p| p.as_ref()).to_glib_none().0,
263 Some(callback),
264 Box_::into_raw(user_data) as *mut _,
265 );
266 }
267 }
268
269 fn write_mime_type_future(
270 &self,
271 mime_type: &str,
272 stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
273 io_priority: glib::Priority,
274 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
275 let mime_type = String::from(mime_type);
276 let stream = stream.clone();
277 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
278 obj.write_mime_type_async(
279 &mime_type,
280 &stream,
281 io_priority,
282 Some(cancellable),
283 move |res| {
284 send.resolve(res);
285 },
286 );
287 }))
288 }
289
290 #[doc(alias = "content-changed")]
292 fn connect_content_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
293 unsafe extern "C" fn content_changed_trampoline<
294 P: IsA<ContentProvider>,
295 F: Fn(&P) + 'static,
296 >(
297 this: *mut ffi::GdkContentProvider,
298 f: glib::ffi::gpointer,
299 ) {
300 let f: &F = &*(f as *const F);
301 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
302 }
303 unsafe {
304 let f: Box_<F> = Box_::new(f);
305 connect_raw(
306 self.as_ptr() as *mut _,
307 b"content-changed\0".as_ptr() as *const _,
308 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
309 content_changed_trampoline::<Self, F> as *const (),
310 )),
311 Box_::into_raw(f),
312 )
313 }
314 }
315
316 #[doc(alias = "formats")]
317 fn connect_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
318 unsafe extern "C" fn notify_formats_trampoline<
319 P: IsA<ContentProvider>,
320 F: Fn(&P) + 'static,
321 >(
322 this: *mut ffi::GdkContentProvider,
323 _param_spec: glib::ffi::gpointer,
324 f: glib::ffi::gpointer,
325 ) {
326 let f: &F = &*(f as *const F);
327 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
328 }
329 unsafe {
330 let f: Box_<F> = Box_::new(f);
331 connect_raw(
332 self.as_ptr() as *mut _,
333 b"notify::formats\0".as_ptr() as *const _,
334 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
335 notify_formats_trampoline::<Self, F> as *const (),
336 )),
337 Box_::into_raw(f),
338 )
339 }
340 }
341
342 #[doc(alias = "storable-formats")]
343 fn connect_storable_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
344 unsafe extern "C" fn notify_storable_formats_trampoline<
345 P: IsA<ContentProvider>,
346 F: Fn(&P) + 'static,
347 >(
348 this: *mut ffi::GdkContentProvider,
349 _param_spec: glib::ffi::gpointer,
350 f: glib::ffi::gpointer,
351 ) {
352 let f: &F = &*(f as *const F);
353 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
354 }
355 unsafe {
356 let f: Box_<F> = Box_::new(f);
357 connect_raw(
358 self.as_ptr() as *mut _,
359 b"notify::storable-formats\0".as_ptr() as *const _,
360 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
361 notify_storable_formats_trampoline::<Self, F> as *const (),
362 )),
363 Box_::into_raw(f),
364 )
365 }
366 }
367}
368
369impl<O: IsA<ContentProvider>> ContentProviderExt for O {}