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