libpanel/
save_delegate.rs

1use crate::{prelude::*, SaveDelegate};
2use futures_core::future::Future;
3use glib::{signal::connect_raw, translate::*, SignalHandlerId};
4use std::mem::transmute;
5
6pub trait SaveDelegateExtManual {
7    fn connect_save<F, R>(&self, f: F) -> SignalHandlerId
8    where
9        F: Fn(&Self, &gio::Task<bool>) -> R + 'static,
10        R: Future<Output = Result<(), glib::Error>> + 'static;
11}
12
13impl<O: IsA<SaveDelegate>> SaveDelegateExtManual for O {
14    fn connect_save<F, R>(&self, f: F) -> SignalHandlerId
15    where
16        F: Fn(&Self, &gio::Task<bool>) -> R + 'static,
17        R: Future<Output = Result<(), glib::Error>> + 'static,
18    {
19        unsafe extern "C" fn save_trampoline<
20            P: IsA<SaveDelegate>,
21            F: Fn(&P, &gio::Task<bool>) -> R + 'static,
22            R: Future<Output = Result<(), glib::Error>> + 'static,
23        >(
24            this: *mut ffi::PanelSaveDelegate,
25            task: *mut gio::ffi::GTask,
26            f: glib::ffi::gpointer,
27        ) -> glib::ffi::gboolean {
28            let f: &F = &*(f as *const F);
29            let task: gio::Task<bool> = from_glib_none(task);
30            let delegate = SaveDelegate::from_glib_borrow(this);
31            let fut = f(delegate.unsafe_cast_ref(), &task);
32            task.context().spawn_local(async move {
33                task.return_result(fut.await.map(|_| true));
34            });
35            true.into_glib()
36        }
37        unsafe {
38            let f: Box<F> = Box::new(f);
39            connect_raw(
40                self.as_ptr() as *mut _,
41                b"save\0".as_ptr() as *const _,
42                Some(transmute::<*const (), unsafe extern "C" fn()>(
43                    save_trampoline::<Self, F, R> as *const (),
44                )),
45                Box::into_raw(f),
46            )
47        }
48    }
49}