1use 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")]
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 let mut error = ptr::null_mut();
102 let mut value = glib::Value::uninitialized();
103 let _ = ffi::gdk_content_deserialize_finish(res, value.to_glib_none_mut().0, &mut error);
104 let result = if error.is_null() {
105 Ok(value)
106 } else {
107 Err(from_glib_full(error))
108 };
109 let callback: Box<glib::thread_guard::ThreadGuard<R>> = Box::from_raw(user_data as *mut _);
110 let callback = callback.into_inner();
111 callback(result);
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 let deserializer: ContentDeserializer = from_glib_full(deserializer);
182 let callback: &P =
183 &*(ffi::gdk_content_deserializer_get_user_data(deserializer.to_glib_none().0)
184 as *mut _);
185
186 let mut task_data: *mut Option<T> =
187 ffi::gdk_content_deserializer_get_task_data(deserializer.to_glib_none().0) as *mut _;
188 if task_data.is_null() {
189 unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
190 let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
191 }
192 task_data = Box::into_raw(Box::new(None));
193 ffi::gdk_content_deserializer_set_task_data(
194 deserializer.to_glib_none().0,
195 task_data as *mut _,
196 Some(notify_func::<T>),
197 );
198 }
199
200 (*callback)(&deserializer, &mut *task_data);
201 }
202 let deserialize = Some(deserialize_func::<T, P> as _);
203 unsafe extern "C" fn notify_func<
204 T: 'static,
205 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
206 >(
207 data: glib::ffi::gpointer,
208 ) {
209 let _callback: Box<P> = Box::from_raw(data as *mut _);
210 }
211 let destroy_call4 = Some(notify_func::<T, P> as _);
212 let super_callback0: Box<P> = deserialize_data;
213 unsafe {
214 ffi::gdk_content_register_deserializer(
215 mime_type.to_glib_none().0,
216 type_.into_glib(),
217 deserialize,
218 Box::into_raw(super_callback0) as *mut _,
219 destroy_call4,
220 );
221 }
222}
223
224#[doc(alias = "gdk_content_register_serializer")]
238pub fn content_register_serializer<
239 T: 'static,
240 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
241>(
242 type_: glib::types::Type,
243 mime_type: &str,
244 serialize: P,
245) {
246 assert_initialized_main_thread!();
247 let serialize_data: Box<P> = Box::new(serialize);
248 unsafe extern "C" fn serialize_func<
249 T: 'static,
250 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
251 >(
252 serializer: *mut ffi::GdkContentSerializer,
253 ) {
254 let serializer: ContentSerializer = from_glib_full(serializer);
255 let callback: &P =
256 &*(ffi::gdk_content_serializer_get_user_data(serializer.to_glib_none().0) as *mut _);
257
258 let mut task_data: *mut Option<T> =
259 ffi::gdk_content_serializer_get_task_data(serializer.to_glib_none().0) as *mut _;
260 if task_data.is_null() {
261 unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
262 let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
263 }
264 task_data = Box::into_raw(Box::new(None));
265 ffi::gdk_content_serializer_set_task_data(
266 serializer.to_glib_none().0,
267 task_data as *mut _,
268 Some(notify_func::<T>),
269 );
270 }
271
272 (*callback)(&serializer, &mut *task_data);
273 }
274 let serialize = Some(serialize_func::<T, P> as _);
275 unsafe extern "C" fn notify_func<
276 T: 'static,
277 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
278 >(
279 data: glib::ffi::gpointer,
280 ) {
281 let _callback: Box<P> = Box::from_raw(data as *mut _);
282 }
283 let destroy_call4 = Some(notify_func::<T, P> as _);
284 let super_callback0: Box<P> = serialize_data;
285 unsafe {
286 ffi::gdk_content_register_serializer(
287 type_.into_glib(),
288 mime_type.to_glib_none().0,
289 serialize,
290 Box::into_raw(super_callback0) as *mut _,
291 destroy_call4,
292 );
293 }
294}
295
296#[doc(alias = "gdk_content_serialize_async")]
313pub fn content_serialize_async<R: FnOnce(Result<(), glib::Error>) + 'static>(
314 stream: &impl IsA<gio::OutputStream>,
315 mime_type: &str,
316 value: &glib::Value,
317 io_priority: glib::Priority,
318 cancellable: Option<&impl IsA<gio::Cancellable>>,
319 callback: R,
320) {
321 assert_initialized_main_thread!();
322 let main_context = glib::MainContext::ref_thread_default();
323 let is_main_context_owner = main_context.is_owner();
324 let has_acquired_main_context = (!is_main_context_owner)
325 .then(|| main_context.acquire().ok())
326 .flatten();
327 assert!(
328 is_main_context_owner || has_acquired_main_context.is_some(),
329 "Async operations only allowed if the thread is owning the MainContext"
330 );
331 let user_data: Box<glib::thread_guard::ThreadGuard<R>> =
332 Box::new(glib::thread_guard::ThreadGuard::new(callback));
333 unsafe extern "C" fn content_serialize_async_trampoline<
334 R: FnOnce(Result<(), glib::Error>) + 'static,
335 >(
336 _source_object: *mut glib::gobject_ffi::GObject,
337 res: *mut gio::ffi::GAsyncResult,
338 user_data: glib::ffi::gpointer,
339 ) {
340 let mut error = ptr::null_mut();
341 let _ = ffi::gdk_content_serialize_finish(res, &mut error);
342 let result = if error.is_null() {
343 Ok(())
344 } else {
345 Err(from_glib_full(error))
346 };
347 let callback: Box<glib::thread_guard::ThreadGuard<R>> = Box::from_raw(user_data as *mut _);
348 let callback = callback.into_inner();
349 callback(result);
350 }
351 let callback = content_serialize_async_trampoline::<R>;
352 unsafe {
353 ffi::gdk_content_serialize_async(
354 stream.as_ref().to_glib_none().0,
355 mime_type.to_glib_none().0,
356 value.to_glib_none().0,
357 io_priority.into_glib(),
358 cancellable.map(|p| p.as_ref()).to_glib_none().0,
359 Some(callback),
360 Box::into_raw(user_data) as *mut _,
361 );
362 }
363}
364
365pub fn content_serialize_future(
366 stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
367 mime_type: &str,
368 value: &glib::Value,
369 io_priority: glib::Priority,
370) -> Pin<Box<dyn future::Future<Output = Result<(), glib::Error>> + 'static>> {
371 assert_initialized_main_thread!();
372
373 let stream = stream.clone();
374 let mime_type = String::from(mime_type);
375 let value = value.clone();
376 Box::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
377 content_serialize_async(
378 &stream,
379 &mime_type,
380 &value,
381 io_priority,
382 Some(cancellable),
383 move |res| {
384 send.resolve(res);
385 },
386 );
387 }))
388}
389
390#[doc(alias = "gdk_pango_layout_line_get_clip_region")]
419pub fn pango_layout_line_get_clip_region(
420 line: &pango::LayoutLine,
421 x_origin: i32,
422 y_origin: i32,
423 index_ranges: &[GRange],
424) -> cairo::Region {
425 assert_initialized_main_thread!();
426
427 let ptr: *const i32 = index_ranges.as_ptr() as _;
428 unsafe {
429 from_glib_full(ffi::gdk_pango_layout_line_get_clip_region(
430 line.to_glib_none().0,
431 x_origin,
432 y_origin,
433 mut_override(ptr),
434 (index_ranges.len() / 2) as i32,
435 ))
436 }
437}