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")]
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}