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(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")]
161pub fn content_register_deserializer<
162 T: 'static,
163 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
164>(
165 mime_type: &str,
166 type_: glib::types::Type,
167 deserialize: P,
168) {
169 assert_initialized_main_thread!();
170 let deserialize_data: Box<P> = Box::new(deserialize);
171 unsafe extern "C" fn deserialize_func<
172 T: 'static,
173 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
174 >(
175 deserializer: *mut ffi::GdkContentDeserializer,
176 ) {
177 let deserializer: ContentDeserializer = from_glib_full(deserializer);
178 let callback: &P =
179 &*(ffi::gdk_content_deserializer_get_user_data(deserializer.to_glib_none().0)
180 as *mut _);
181
182 let mut task_data: *mut Option<T> =
183 ffi::gdk_content_deserializer_get_task_data(deserializer.to_glib_none().0) as *mut _;
184 if task_data.is_null() {
185 unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
186 let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
187 }
188 task_data = Box::into_raw(Box::new(None));
189 ffi::gdk_content_deserializer_set_task_data(
190 deserializer.to_glib_none().0,
191 task_data as *mut _,
192 Some(notify_func::<T>),
193 );
194 }
195
196 (*callback)(&deserializer, &mut *task_data);
197 }
198 let deserialize = Some(deserialize_func::<T, P> as _);
199 unsafe extern "C" fn notify_func<
200 T: 'static,
201 P: Fn(&ContentDeserializer, &mut Option<T>) + 'static,
202 >(
203 data: glib::ffi::gpointer,
204 ) {
205 let _callback: Box<P> = Box::from_raw(data as *mut _);
206 }
207 let destroy_call4 = Some(notify_func::<T, P> as _);
208 let super_callback0: Box<P> = deserialize_data;
209 unsafe {
210 ffi::gdk_content_register_deserializer(
211 mime_type.to_glib_none().0,
212 type_.into_glib(),
213 deserialize,
214 Box::into_raw(super_callback0) as *mut _,
215 destroy_call4,
216 );
217 }
218}
219
220#[doc(alias = "gdk_content_register_serializer")]
230pub fn content_register_serializer<
231 T: 'static,
232 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
233>(
234 type_: glib::types::Type,
235 mime_type: &str,
236 serialize: P,
237) {
238 assert_initialized_main_thread!();
239 let serialize_data: Box<P> = Box::new(serialize);
240 unsafe extern "C" fn serialize_func<
241 T: 'static,
242 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
243 >(
244 serializer: *mut ffi::GdkContentSerializer,
245 ) {
246 let serializer: ContentSerializer = from_glib_full(serializer);
247 let callback: &P =
248 &*(ffi::gdk_content_serializer_get_user_data(serializer.to_glib_none().0) as *mut _);
249
250 let mut task_data: *mut Option<T> =
251 ffi::gdk_content_serializer_get_task_data(serializer.to_glib_none().0) as *mut _;
252 if task_data.is_null() {
253 unsafe extern "C" fn notify_func<T: 'static>(data: glib::ffi::gpointer) {
254 let _task_data: Box<Option<T>> = Box::from_raw(data as *mut _);
255 }
256 task_data = Box::into_raw(Box::new(None));
257 ffi::gdk_content_serializer_set_task_data(
258 serializer.to_glib_none().0,
259 task_data as *mut _,
260 Some(notify_func::<T>),
261 );
262 }
263
264 (*callback)(&serializer, &mut *task_data);
265 }
266 let serialize = Some(serialize_func::<T, P> as _);
267 unsafe extern "C" fn notify_func<
268 T: 'static,
269 P: Fn(&ContentSerializer, &mut Option<T>) + 'static,
270 >(
271 data: glib::ffi::gpointer,
272 ) {
273 let _callback: Box<P> = Box::from_raw(data as *mut _);
274 }
275 let destroy_call4 = Some(notify_func::<T, P> as _);
276 let super_callback0: Box<P> = serialize_data;
277 unsafe {
278 ffi::gdk_content_register_serializer(
279 type_.into_glib(),
280 mime_type.to_glib_none().0,
281 serialize,
282 Box::into_raw(super_callback0) as *mut _,
283 destroy_call4,
284 );
285 }
286}
287
288#[doc(alias = "gdk_content_serialize_async")]
305pub fn content_serialize_async<R: FnOnce(Result<(), glib::Error>) + 'static>(
306 stream: &impl IsA<gio::OutputStream>,
307 mime_type: &str,
308 value: &glib::Value,
309 io_priority: glib::Priority,
310 cancellable: Option<&impl IsA<gio::Cancellable>>,
311 callback: R,
312) {
313 assert_initialized_main_thread!();
314 let main_context = glib::MainContext::ref_thread_default();
315 let is_main_context_owner = main_context.is_owner();
316 let has_acquired_main_context = (!is_main_context_owner)
317 .then(|| main_context.acquire().ok())
318 .flatten();
319 assert!(
320 is_main_context_owner || has_acquired_main_context.is_some(),
321 "Async operations only allowed if the thread is owning the MainContext"
322 );
323 let user_data: Box<glib::thread_guard::ThreadGuard<R>> =
324 Box::new(glib::thread_guard::ThreadGuard::new(callback));
325 unsafe extern "C" fn content_serialize_async_trampoline<
326 R: FnOnce(Result<(), glib::Error>) + 'static,
327 >(
328 _source_object: *mut glib::gobject_ffi::GObject,
329 res: *mut gio::ffi::GAsyncResult,
330 user_data: glib::ffi::gpointer,
331 ) {
332 let mut error = ptr::null_mut();
333 let _ = ffi::gdk_content_serialize_finish(res, &mut error);
334 let result = if error.is_null() {
335 Ok(())
336 } else {
337 Err(from_glib_full(error))
338 };
339 let callback: Box<glib::thread_guard::ThreadGuard<R>> = Box::from_raw(user_data as *mut _);
340 let callback = callback.into_inner();
341 callback(result);
342 }
343 let callback = content_serialize_async_trampoline::<R>;
344 unsafe {
345 ffi::gdk_content_serialize_async(
346 stream.as_ref().to_glib_none().0,
347 mime_type.to_glib_none().0,
348 value.to_glib_none().0,
349 io_priority.into_glib(),
350 cancellable.map(|p| p.as_ref()).to_glib_none().0,
351 Some(callback),
352 Box::into_raw(user_data) as *mut _,
353 );
354 }
355}
356
357pub fn content_serialize_future(
358 stream: &(impl IsA<gio::OutputStream> + Clone + 'static),
359 mime_type: &str,
360 value: &glib::Value,
361 io_priority: glib::Priority,
362) -> Pin<Box<dyn future::Future<Output = Result<(), glib::Error>> + 'static>> {
363 assert_initialized_main_thread!();
364
365 let stream = stream.clone();
366 let mime_type = String::from(mime_type);
367 let value = value.clone();
368 Box::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
369 content_serialize_async(
370 &stream,
371 &mime_type,
372 &value,
373 io_priority,
374 Some(cancellable),
375 move |res| {
376 send.resolve(res);
377 },
378 );
379 }))
380}
381
382#[doc(alias = "gdk_pango_layout_line_get_clip_region")]
411pub fn pango_layout_line_get_clip_region(
412 line: &pango::LayoutLine,
413 x_origin: i32,
414 y_origin: i32,
415 index_ranges: &[GRange],
416) -> cairo::Region {
417 assert_initialized_main_thread!();
418
419 let ptr: *const i32 = index_ranges.as_ptr() as _;
420 unsafe {
421 from_glib_full(ffi::gdk_pango_layout_line_get_clip_region(
422 line.to_glib_none().0,
423 x_origin,
424 y_origin,
425 mut_override(ptr),
426 (index_ranges.len() / 2) as i32,
427 ))
428 }
429}