1use crate::{ContentFormats, ffi};
6use glib::{
7 object::ObjectType as _,
8 prelude::*,
9 signal::{SignalHandlerId, connect_raw},
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 unsafe {
235 let mut error = std::ptr::null_mut();
236 ffi::gdk_content_provider_write_mime_type_finish(
237 _source_object as *mut _,
238 res,
239 &mut error,
240 );
241 let result = if error.is_null() {
242 Ok(())
243 } else {
244 Err(from_glib_full(error))
245 };
246 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
247 Box_::from_raw(user_data as *mut _);
248 let callback: P = callback.into_inner();
249 callback(result);
250 }
251 }
252 let callback = write_mime_type_async_trampoline::<P>;
253 unsafe {
254 ffi::gdk_content_provider_write_mime_type_async(
255 self.as_ref().to_glib_none().0,
256 mime_type.to_glib_none().0,
257 stream.as_ref().to_glib_none().0,
258 io_priority.into_glib(),
259 cancellable.map(|p| p.as_ref()).to_glib_none().0,
260 Some(callback),
261 Box_::into_raw(user_data) as *mut _,
262 );
263 }
264 }
265
266 fn write_mime_type_future(
267 &self,
268 mime_type: &str,
269 stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
270 io_priority: glib::Priority,
271 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
272 let mime_type = String::from(mime_type);
273 let stream = stream.clone();
274 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
275 obj.write_mime_type_async(
276 &mime_type,
277 &stream,
278 io_priority,
279 Some(cancellable),
280 move |res| {
281 send.resolve(res);
282 },
283 );
284 }))
285 }
286
287 #[doc(alias = "content-changed")]
289 fn connect_content_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
290 unsafe extern "C" fn content_changed_trampoline<
291 P: IsA<ContentProvider>,
292 F: Fn(&P) + 'static,
293 >(
294 this: *mut ffi::GdkContentProvider,
295 f: glib::ffi::gpointer,
296 ) {
297 unsafe {
298 let f: &F = &*(f as *const F);
299 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
300 }
301 }
302 unsafe {
303 let f: Box_<F> = Box_::new(f);
304 connect_raw(
305 self.as_ptr() as *mut _,
306 c"content-changed".as_ptr() as *const _,
307 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
308 content_changed_trampoline::<Self, F> as *const (),
309 )),
310 Box_::into_raw(f),
311 )
312 }
313 }
314
315 #[doc(alias = "formats")]
316 fn connect_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
317 unsafe extern "C" fn notify_formats_trampoline<
318 P: IsA<ContentProvider>,
319 F: Fn(&P) + 'static,
320 >(
321 this: *mut ffi::GdkContentProvider,
322 _param_spec: glib::ffi::gpointer,
323 f: glib::ffi::gpointer,
324 ) {
325 unsafe {
326 let f: &F = &*(f as *const F);
327 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
328 }
329 }
330 unsafe {
331 let f: Box_<F> = Box_::new(f);
332 connect_raw(
333 self.as_ptr() as *mut _,
334 c"notify::formats".as_ptr() as *const _,
335 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
336 notify_formats_trampoline::<Self, F> as *const (),
337 )),
338 Box_::into_raw(f),
339 )
340 }
341 }
342
343 #[doc(alias = "storable-formats")]
344 fn connect_storable_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
345 unsafe extern "C" fn notify_storable_formats_trampoline<
346 P: IsA<ContentProvider>,
347 F: Fn(&P) + 'static,
348 >(
349 this: *mut ffi::GdkContentProvider,
350 _param_spec: glib::ffi::gpointer,
351 f: glib::ffi::gpointer,
352 ) {
353 unsafe {
354 let f: &F = &*(f as *const F);
355 f(ContentProvider::from_glib_borrow(this).unsafe_cast_ref())
356 }
357 }
358 unsafe {
359 let f: Box_<F> = Box_::new(f);
360 connect_raw(
361 self.as_ptr() as *mut _,
362 c"notify::storable-formats".as_ptr() as *const _,
363 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
364 notify_storable_formats_trampoline::<Self, F> as *const (),
365 )),
366 Box_::into_raw(f),
367 )
368 }
369 }
370}
371
372impl<O: IsA<ContentProvider>> ContentProviderExt for O {}