[go: up one dir, main page]

gdk4/
functions.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{future, pin::Pin, ptr};
4
5use glib::translate::*;
6
7pub use crate::auto::functions::*;
8use crate::{ffi, prelude::*, ContentDeserializer, ContentSerializer};
9
10#[repr(C, packed)]
11pub struct GRange(pub i32, pub i32);
12
13#[doc(alias = "gdk_pango_layout_get_clip_region")]
14pub fn pango_layout_get_clip_region(
15    layout: &pango::Layout,
16    x_origin: i32,
17    y_origin: i32,
18    index_ranges: &[GRange],
19) -> cairo::Region {
20    assert_initialized_main_thread!();
21
22    let ptr: *const i32 = index_ranges.as_ptr() as _;
23    unsafe {
24        from_glib_full(ffi::gdk_pango_layout_get_clip_region(
25            layout.to_glib_none().0,
26            x_origin,
27            y_origin,
28            ptr,
29            (index_ranges.len() / 2) as i32,
30        ))
31    }
32}
33
34#[doc(alias = "gdk_content_deserialize_async")]
35pub fn content_deserialize_async<R: FnOnce(Result<glib::Value, glib::Error>) + 'static>(
36    stream: &impl IsA<gio::InputStream>,
37    mime_type: &str,
38    type_: glib::types::Type,
39    io_priority: glib::Priority,
40    cancellable: Option<&impl IsA<gio::Cancellable>>,
41    callback: R,
42) {
43    assert_initialized_main_thread!();
44    let main_context = glib::MainContext::ref_thread_default();
45    let is_main_context_owner = main_context.is_owner();
46    let has_acquired_main_context = (!is_main_context_owner)
47        .then(|| main_context.acquire().ok())
48        .flatten();
49    assert!(
50        is_main_context_owner || has_acquired_main_context.is_some(),
51        "Async operations only allowed if the thread is owning the MainContext"
52    );
53
54    let user_data: Box<glib::thread_guard::ThreadGuard<R>> =
55        Box::new(glib::thread_guard::ThreadGuard::new(callback));
56    unsafe extern "C" fn content_deserialize_async_trampoline<
57        R: FnOnce(Result<glib::Value, glib::Error>) + 'static,
58    >(
59        _source_object: *mut glib::gobject_ffi::GObject,
60        res: *mut gio::ffi::GAsyncResult,
61        user_data: glib::ffi::gpointer,
62    ) {
63        let mut error = ptr::null_mut();
64        let mut value = glib::Value::uninitialized();
65        let _ = ffi::gdk_content_deserialize_finish(res, value.to_glib_none_mut().0, &mut error);
66        let result = if error.is_null() {
67            Ok(value)
68        } else {
69            Err(from_glib_full(error))
70        };
71        let callback: Box<glib::thread_guard::ThreadGuard<R>> = Box::from_raw(user_data as *mut _);
72        let callback = callback.into_inner();
73        callback(result);
74    }
75    let callback = content_deserialize_async_trampoline::<R>;
76    unsafe {
77        ffi::gdk_content_deserialize_async(
78            stream.as_ref().to_glib_none().0,
79            mime_type.to_glib_none().0,
80            type_.into_glib(),
81            io_priority.into_glib(),
82            cancellable.map(|p| p.as_ref()).to_glib_none().0,
83            Some(callback),
84            Box::into_raw(user_data) as *mut _,
85        );
86    }
87}
88
89pub fn content_deserialize_future(
90    stream: &(impl IsA<gio::InputStream> + Clone + 'static),
91    mime_type: &str,
92    type_: glib::types::Type,
93    io_priority: glib::Priority,
94) -> Pin<Box<dyn future::Future<Output = Result<glib::Value, glib::Error>> + 'static>> {
95    assert_initialized_main_thread!();
96
97    let stream = stream.clone();
98    let mime_type = String::from(mime_type);
99    Box::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
100        content_deserialize_async(
101            &stream,
102            &mime_type,
103            type_,
104            io_priority,
105            Some(cancellable),
106            move |res| {
107                send.resolve(res);
108            },
109        );
110    }))
111}
112
113#[doc(alias = "gdk_content_register_deserializer")]
114pub fn content_register_deserializer<
115    T: 'static,
116    P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
117>(
118    mime_type: &str,
119    type_: glib::types::Type,
120    deserialize: P,
121) {
122    assert_initialized_main_thread!();
123    let deserialize_data: Box<P> = Box::new(deserialize);
124    unsafe extern "C" fn deserialize_func<
125        T: 'static,
126        P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
127    >(
128        deserializer: *mut ffi::GdkContentDeserializer,
129    ) {
130        let deserializer: ContentDeserializer = from_glib_full(deserializer);
131        let callback: &P =
132            &*(ffi::gdk_content_deserializer_get_user_data(deserializer.to_glib_none().0)
133                as *mut _);
134
135        let mut task_data: *mut Option<T> =
136            ffi::gdk_content_deserializer_get_task_data(deserializer.to_glib_none().0) as *mut _;
137        if task_data.is_null() {
138            unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
139                let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
140            }
141            task_data = Box::into_raw(Box::new(None));
142            ffi::gdk_content_deserializer_set_task_data(
143                deserializer.to_glib_none().0,
144                task_data as *mut _,
145                Some(notify_func::<T>),
146            );
147        }
148
149        (*callback)(&deserializer, &mut *task_data);
150    }
151    let deserialize = Some(deserialize_func::<T, P> as _);
152    unsafe extern "C" fn notify_func<
153        T: 'static,
154        P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
155    >(
156        data: glib::ffi::gpointer,
157    ) {
158        let _callback: Box<P> = Box::from_raw(data as *mut _);
159    }
160    let destroy_call4 = Some(notify_func::<T, P> as _);
161    let super_callback0: Box<P> = deserialize_data;
162    unsafe {
163        ffi::gdk_content_register_deserializer(
164            mime_type.to_glib_none().0,
165            type_.into_glib(),
166            deserialize,
167            Box::into_raw(super_callback0) as *mut _,
168            destroy_call4,
169        );
170    }
171}
172
173#[doc(alias = "gdk_content_register_serializer")]
174pub fn content_register_serializer<
175    T: 'static,
176    P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
177>(
178    type_: glib::types::Type,
179    mime_type: &str,
180    serialize: P,
181) {
182    assert_initialized_main_thread!();
183    let serialize_data: Box<P> = Box::new(serialize);
184    unsafe extern "C" fn serialize_func<
185        T: 'static,
186        P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
187    >(
188        serializer: *mut ffi::GdkContentSerializer,
189    ) {
190        let serializer: ContentSerializer = from_glib_full(serializer);
191        let callback: &P =
192            &*(ffi::gdk_content_serializer_get_user_data(serializer.to_glib_none().0) as *mut _);
193
194        let mut task_data: *mut Option<T> =
195            ffi::gdk_content_serializer_get_task_data(serializer.to_glib_none().0) as *mut _;
196        if task_data.is_null() {
197            unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
198                let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
199            }
200            task_data = Box::into_raw(Box::new(None));
201            ffi::gdk_content_serializer_set_task_data(
202                serializer.to_glib_none().0,
203                task_data as *mut _,
204                Some(notify_func::<T>),
205            );
206        }
207
208        (*callback)(&serializer, &mut *task_data);
209    }
210    let serialize = Some(serialize_func::<T, P> as _);
211    unsafe extern "C" fn notify_func<
212        T: 'static,
213        P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
214    >(
215        data: glib::ffi::gpointer,
216    ) {
217        let _callback: Box<P> = Box::from_raw(data as *mut _);
218    }
219    let destroy_call4 = Some(notify_func::<T, P> as _);
220    let super_callback0: Box<P> = serialize_data;
221    unsafe {
222        ffi::gdk_content_register_serializer(
223            type_.into_glib(),
224            mime_type.to_glib_none().0,
225            serialize,
226            Box::into_raw(super_callback0) as *mut _,
227            destroy_call4,
228        );
229    }
230}
231
232#[doc(alias = "gdk_content_serialize_async")]
233pub fn content_serialize_async<R: FnOnce(Result<(), glib::Error>) + 'static>(
234    stream: &impl IsA<gio::OutputStream>,
235    mime_type: &str,
236    value: &glib::Value,
237    io_priority: glib::Priority,
238    cancellable: Option<&impl IsA<gio::Cancellable>>,
239    callback: R,
240) {
241    assert_initialized_main_thread!();
242    let main_context = glib::MainContext::ref_thread_default();
243    let is_main_context_owner = main_context.is_owner();
244    let has_acquired_main_context = (!is_main_context_owner)
245        .then(|| main_context.acquire().ok())
246        .flatten();
247    assert!(
248        is_main_context_owner || has_acquired_main_context.is_some(),
249        "Async operations only allowed if the thread is owning the MainContext"
250    );
251    let user_data: Box<glib::thread_guard::ThreadGuard<R>> =
252        Box::new(glib::thread_guard::ThreadGuard::new(callback));
253    unsafe extern "C" fn content_serialize_async_trampoline<
254        R: FnOnce(Result<(), glib::Error>) + 'static,
255    >(
256        _source_object: *mut glib::gobject_ffi::GObject,
257        res: *mut gio::ffi::GAsyncResult,
258        user_data: glib::ffi::gpointer,
259    ) {
260        let mut error = ptr::null_mut();
261        let _ = ffi::gdk_content_serialize_finish(res, &mut error);
262        let result = if error.is_null() {
263            Ok(())
264        } else {
265            Err(from_glib_full(error))
266        };
267        let callback: Box<glib::thread_guard::ThreadGuard<R>> = Box::from_raw(user_data as *mut _);
268        let callback = callback.into_inner();
269        callback(result);
270    }
271    let callback = content_serialize_async_trampoline::<R>;
272    unsafe {
273        ffi::gdk_content_serialize_async(
274            stream.as_ref().to_glib_none().0,
275            mime_type.to_glib_none().0,
276            value.to_glib_none().0,
277            io_priority.into_glib(),
278            cancellable.map(|p| p.as_ref()).to_glib_none().0,
279            Some(callback),
280            Box::into_raw(user_data) as *mut _,
281        );
282    }
283}
284
285pub fn content_serialize_future(
286    stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
287    mime_type: &str,
288    value: &glib::Value,
289    io_priority: glib::Priority,
290) -> Pin<Box<dyn future::Future<Output = Result<(), glib::Error>> + 'static>> {
291    assert_initialized_main_thread!();
292
293    let stream = stream.clone();
294    let mime_type = String::from(mime_type);
295    let value = value.clone();
296    Box::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
297        content_serialize_async(
298            &stream,
299            &mime_type,
300            &value,
301            io_priority,
302            Some(cancellable),
303            move |res| {
304                send.resolve(res);
305            },
306        );
307    }))
308}
309
310#[doc(alias = "gdk_pango_layout_line_get_clip_region")]
311pub fn pango_layout_line_get_clip_region(
312    line: &pango::LayoutLine,
313    x_origin: i32,
314    y_origin: i32,
315    index_ranges: &[GRange],
316) -> cairo::Region {
317    assert_initialized_main_thread!();
318
319    let ptr: *const i32 = index_ranges.as_ptr() as _;
320    unsafe {
321        from_glib_full(ffi::gdk_pango_layout_line_get_clip_region(
322            line.to_glib_none().0,
323            x_origin,
324            y_origin,
325            mut_override(ptr),
326            (index_ranges.len() / 2) as i32,
327        ))
328    }
329}