1use std::{future, pin::Pin, ptr};
4
5use glib::translate::*;
6
7pub use crate::auto::functions::*;
8use crate::{ContentDeserializer, ContentSerializer, ffi, prelude::*};
9
10#[repr(C, packed)]
11pub struct GRange(pub i32, pub i32);
12
13#[doc(alias = "gdk_pango_layout_get_clip_region")]
32pub fn pango_layout_get_clip_region(
33 layout: &pango::Layout,
34 x_origin: i32,
35 y_origin: i32,
36 index_ranges: &[GRange],
37) -> cairo::Region {
38 assert_initialized_main_thread!();
39
40 let ptr: *const i32 = index_ranges.as_ptr() as _;
41 unsafe {
42 from_glib_full(ffi::gdk_pango_layout_get_clip_region(
43 layout.to_glib_none().0,
44 x_origin,
45 y_origin,
46 ptr,
47 (index_ranges.len() / 2) as i32,
48 ))
49 }
50}
51
52#[doc(alias = "gdk_content_deserialize_async")]
69pub fn content_deserialize_async<R: FnOnce(Result<glib::Value, glib::Error>) + 'static>(
70 stream: &impl IsA<gio::InputStream>,
71 mime_type: &str,
72 type_: glib::types::Type,
73 io_priority: glib::Priority,
74 cancellable: Option<&impl IsA<gio::Cancellable>>,
75 callback: R,
76) {
77 assert_initialized_main_thread!();
78 let main_context = glib::MainContext::ref_thread_default();
79 let is_main_context_owner = main_context.is_owner();
80 let has_acquired_main_context = (!is_main_context_owner)
81 .then(|| main_context.acquire().ok())
82 .flatten();
83 assert!(
84 is_main_context_owner || has_acquired_main_context.is_some(),
85 "Async operations only allowed if the thread is owning the MainContext"
86 );
87
88 let user_data: Box<glib::thread_guard::ThreadGuard<R>> =
89 Box::new(glib::thread_guard::ThreadGuard::new(callback));
90 unsafe extern "C" fn content_deserialize_async_trampoline<
91 R: FnOnce(Result<glib::Value, glib::Error>) + 'static,
92 >(
93 _source_object: *mut glib::gobject_ffi::GObject,
94 res: *mut gio::ffi::GAsyncResult,
95 user_data: glib::ffi::gpointer,
96 ) {
97 unsafe {
98 let mut error = ptr::null_mut();
99 let mut value = glib::Value::uninitialized();
100 let _ =
101 ffi::gdk_content_deserialize_finish(res, value.to_glib_none_mut().0, &mut error);
102 let result = if error.is_null() {
103 Ok(value)
104 } else {
105 Err(from_glib_full(error))
106 };
107 let callback: Box<glib::thread_guard::ThreadGuard<R>> =
108 Box::from_raw(user_data as *mut _);
109 let callback = callback.into_inner();
110 callback(result);
111 }
112 }
113 let callback = content_deserialize_async_trampoline::<R>;
114 unsafe {
115 ffi::gdk_content_deserialize_async(
116 stream.as_ref().to_glib_none().0,
117 mime_type.to_glib_none().0,
118 type_.into_glib(),
119 io_priority.into_glib(),
120 cancellable.map(|p| p.as_ref()).to_glib_none().0,
121 Some(callback),
122 Box::into_raw(user_data) as *mut _,
123 );
124 }
125}
126
127pub fn content_deserialize_future(
128 stream: &(impl IsA<gio::InputStream> + Clone + 'static),
129 mime_type: &str,
130 type_: glib::types::Type,
131 io_priority: glib::Priority,
132) -> Pin<Box<dyn future::Future<Output = Result<glib::Value, glib::Error>> + 'static>> {
133 assert_initialized_main_thread!();
134
135 let stream = stream.clone();
136 let mime_type = String::from(mime_type);
137 Box::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
138 content_deserialize_async(
139 &stream,
140 &mime_type,
141 type_,
142 io_priority,
143 Some(cancellable),
144 move |res| {
145 send.resolve(res);
146 },
147 );
148 }))
149}
150
151#[doc(alias = "gdk_content_register_deserializer")]
165pub fn content_register_deserializer<
166 T: 'static,
167 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
168>(
169 mime_type: &str,
170 type_: glib::types::Type,
171 deserialize: P,
172) {
173 assert_initialized_main_thread!();
174 let deserialize_data: Box<P> = Box::new(deserialize);
175 unsafe extern "C" fn deserialize_func<
176 T: 'static,
177 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
178 >(
179 deserializer: *mut ffi::GdkContentDeserializer,
180 ) {
181 unsafe {
182 let deserializer: ContentDeserializer = from_glib_full(deserializer);
183 let callback: &P =
184 &*(ffi::gdk_content_deserializer_get_user_data(deserializer.to_glib_none().0)
185 as *mut _);
186
187 let mut task_data: *mut Option<T> =
188 ffi::gdk_content_deserializer_get_task_data(deserializer.to_glib_none().0)
189 as *mut _;
190 if task_data.is_null() {
191 unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
192 unsafe {
193 let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
194 }
195 }
196 task_data = Box::into_raw(Box::new(None));
197 ffi::gdk_content_deserializer_set_task_data(
198 deserializer.to_glib_none().0,
199 task_data as *mut _,
200 Some(notify_func::<T>),
201 );
202 }
203
204 (*callback)(&deserializer, &mut *task_data);
205 }
206 }
207 let deserialize = Some(deserialize_func::<T, P> as _);
208 unsafe extern "C" fn notify_func<
209 T: 'static,
210 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
211 >(
212 data: glib::ffi::gpointer,
213 ) {
214 unsafe {
215 let _callback: Box<P> = Box::from_raw(data as *mut _);
216 }
217 }
218 let destroy_call4 = Some(notify_func::<T, P> as _);
219 let super_callback0: Box<P> = deserialize_data;
220 unsafe {
221 ffi::gdk_content_register_deserializer(
222 mime_type.to_glib_none().0,
223 type_.into_glib(),
224 deserialize,
225 Box::into_raw(super_callback0) as *mut _,
226 destroy_call4,
227 );
228 }
229}
230
231#[doc(alias = "gdk_content_register_serializer")]
245pub fn content_register_serializer<
246 T: 'static,
247 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
248>(
249 type_: glib::types::Type,
250 mime_type: &str,
251 serialize: P,
252) {
253 assert_initialized_main_thread!();
254 let serialize_data: Box<P> = Box::new(serialize);
255 unsafe extern "C" fn serialize_func<
256 T: 'static,
257 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
258 >(
259 serializer: *mut ffi::GdkContentSerializer,
260 ) {
261 unsafe {
262 let serializer: ContentSerializer = from_glib_full(serializer);
263 let callback: &P =
264 &*(ffi::gdk_content_serializer_get_user_data(serializer.to_glib_none().0)
265 as *mut _);
266
267 let mut task_data: *mut Option<T> =
268 ffi::gdk_content_serializer_get_task_data(serializer.to_glib_none().0) as *mut _;
269 if task_data.is_null() {
270 unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
271 unsafe {
272 let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
273 }
274 }
275 task_data = Box::into_raw(Box::new(None));
276 ffi::gdk_content_serializer_set_task_data(
277 serializer.to_glib_none().0,
278 task_data as *mut _,
279 Some(notify_func::<T>),
280 );
281 }
282
283 (*callback)(&serializer, &mut *task_data);
284 }
285 }
286 let serialize = Some(serialize_func::<T, P> as _);
287 unsafe extern "C" fn notify_func<
288 T: 'static,
289 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
290 >(
291 data: glib::ffi::gpointer,
292 ) {
293 unsafe {
294 let _callback: Box<P> = Box::from_raw(data as *mut _);
295 }
296 }
297 let destroy_call4 = Some(notify_func::<T, P> as _);
298 let super_callback0: Box<P> = serialize_data;
299 unsafe {
300 ffi::gdk_content_register_serializer(
301 type_.into_glib(),
302 mime_type.to_glib_none().0,
303 serialize,
304 Box::into_raw(super_callback0) as *mut _,
305 destroy_call4,
306 );
307 }
308}
309
310#[doc(alias = "gdk_content_serialize_async")]
327pub fn content_serialize_async<R: FnOnce(Result<(), glib::Error>) + 'static>(
328 stream: &impl IsA<gio::OutputStream>,
329 mime_type: &str,
330 value: &glib::Value,
331 io_priority: glib::Priority,
332 cancellable: Option<&impl IsA<gio::Cancellable>>,
333 callback: R,
334) {
335 assert_initialized_main_thread!();
336 let main_context = glib::MainContext::ref_thread_default();
337 let is_main_context_owner = main_context.is_owner();
338 let has_acquired_main_context = (!is_main_context_owner)
339 .then(|| main_context.acquire().ok())
340 .flatten();
341 assert!(
342 is_main_context_owner || has_acquired_main_context.is_some(),
343 "Async operations only allowed if the thread is owning the MainContext"
344 );
345 let user_data: Box<glib::thread_guard::ThreadGuard<R>> =
346 Box::new(glib::thread_guard::ThreadGuard::new(callback));
347 unsafe extern "C" fn content_serialize_async_trampoline<
348 R: FnOnce(Result<(), glib::Error>) + 'static,
349 >(
350 _source_object: *mut glib::gobject_ffi::GObject,
351 res: *mut gio::ffi::GAsyncResult,
352 user_data: glib::ffi::gpointer,
353 ) {
354 unsafe {
355 let mut error = ptr::null_mut();
356 let _ = ffi::gdk_content_serialize_finish(res, &mut error);
357 let result = if error.is_null() {
358 Ok(())
359 } else {
360 Err(from_glib_full(error))
361 };
362 let callback: Box<glib::thread_guard::ThreadGuard<R>> =
363 Box::from_raw(user_data as *mut _);
364 let callback = callback.into_inner();
365 callback(result);
366 }
367 }
368 let callback = content_serialize_async_trampoline::<R>;
369 unsafe {
370 ffi::gdk_content_serialize_async(
371 stream.as_ref().to_glib_none().0,
372 mime_type.to_glib_none().0,
373 value.to_glib_none().0,
374 io_priority.into_glib(),
375 cancellable.map(|p| p.as_ref()).to_glib_none().0,
376 Some(callback),
377 Box::into_raw(user_data) as *mut _,
378 );
379 }
380}
381
382pub fn content_serialize_future(
383 stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
384 mime_type: &str,
385 value: &glib::Value,
386 io_priority: glib::Priority,
387) -> Pin<Box<dyn future::Future<Output = Result<(), glib::Error>> + 'static>> {
388 assert_initialized_main_thread!();
389
390 let stream = stream.clone();
391 let mime_type = String::from(mime_type);
392 let value = value.clone();
393 Box::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
394 content_serialize_async(
395 &stream,
396 &mime_type,
397 &value,
398 io_priority,
399 Some(cancellable),
400 move |res| {
401 send.resolve(res);
402 },
403 );
404 }))
405}
406
407#[doc(alias = "gdk_pango_layout_line_get_clip_region")]
432pub fn pango_layout_line_get_clip_region(
433 line: &pango::LayoutLine,
434 x_origin: i32,
435 y_origin: i32,
436 index_ranges: &[GRange],
437) -> cairo::Region {
438 assert_initialized_main_thread!();
439
440 let ptr: *const i32 = index_ranges.as_ptr() as _;
441 unsafe {
442 from_glib_full(ffi::gdk_pango_layout_line_get_clip_region(
443 line.to_glib_none().0,
444 x_origin,
445 y_origin,
446 mut_override(ptr),
447 (index_ranges.len() / 2) as i32,
448 ))
449 }
450}