1use crate::{AsyncResult, Cancellable, ffi};
6use glib::{
7 prelude::*,
8 signal::{SignalHandlerId, connect_raw},
9 translate::*,
10};
11use std::{boxed::Box as Box_, pin::Pin};
12
13glib::wrapper! {
14 #[doc(alias = "GPermission")]
59 pub struct Permission(Object<ffi::GPermission, ffi::GPermissionClass>);
60
61 match fn {
62 type_ => || ffi::g_permission_get_type(),
63 }
64}
65
66impl Permission {
67 pub const NONE: Option<&'static Permission> = None;
68}
69
70pub trait PermissionExt: IsA<Permission> + 'static {
76 #[doc(alias = "g_permission_acquire")]
98 fn acquire(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
99 unsafe {
100 let mut error = std::ptr::null_mut();
101 let is_ok = ffi::g_permission_acquire(
102 self.as_ref().to_glib_none().0,
103 cancellable.map(|p| p.as_ref()).to_glib_none().0,
104 &mut error,
105 );
106 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
107 if error.is_null() {
108 Ok(())
109 } else {
110 Err(from_glib_full(error))
111 }
112 }
113 }
114
115 #[doc(alias = "g_permission_acquire_async")]
124 fn acquire_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
125 &self,
126 cancellable: Option<&impl IsA<Cancellable>>,
127 callback: P,
128 ) {
129 let main_context = glib::MainContext::ref_thread_default();
130 let is_main_context_owner = main_context.is_owner();
131 let has_acquired_main_context = (!is_main_context_owner)
132 .then(|| main_context.acquire().ok())
133 .flatten();
134 assert!(
135 is_main_context_owner || has_acquired_main_context.is_some(),
136 "Async operations only allowed if the thread is owning the MainContext"
137 );
138
139 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
140 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
141 unsafe extern "C" fn acquire_async_trampoline<
142 P: FnOnce(Result<(), glib::Error>) + 'static,
143 >(
144 _source_object: *mut glib::gobject_ffi::GObject,
145 res: *mut crate::ffi::GAsyncResult,
146 user_data: glib::ffi::gpointer,
147 ) {
148 unsafe {
149 let mut error = std::ptr::null_mut();
150 ffi::g_permission_acquire_finish(_source_object as *mut _, res, &mut error);
151 let result = if error.is_null() {
152 Ok(())
153 } else {
154 Err(from_glib_full(error))
155 };
156 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
157 Box_::from_raw(user_data as *mut _);
158 let callback: P = callback.into_inner();
159 callback(result);
160 }
161 }
162 let callback = acquire_async_trampoline::<P>;
163 unsafe {
164 ffi::g_permission_acquire_async(
165 self.as_ref().to_glib_none().0,
166 cancellable.map(|p| p.as_ref()).to_glib_none().0,
167 Some(callback),
168 Box_::into_raw(user_data) as *mut _,
169 );
170 }
171 }
172
173 fn acquire_future(
174 &self,
175 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
176 Box_::pin(crate::GioFuture::new(
177 self,
178 move |obj, cancellable, send| {
179 obj.acquire_async(Some(cancellable), move |res| {
180 send.resolve(res);
181 });
182 },
183 ))
184 }
185
186 #[doc(alias = "g_permission_get_allowed")]
194 #[doc(alias = "get_allowed")]
195 #[doc(alias = "allowed")]
196 fn is_allowed(&self) -> bool {
197 unsafe {
198 from_glib(ffi::g_permission_get_allowed(
199 self.as_ref().to_glib_none().0,
200 ))
201 }
202 }
203
204 #[doc(alias = "g_permission_get_can_acquire")]
212 #[doc(alias = "get_can_acquire")]
213 #[doc(alias = "can-acquire")]
214 fn can_acquire(&self) -> bool {
215 unsafe {
216 from_glib(ffi::g_permission_get_can_acquire(
217 self.as_ref().to_glib_none().0,
218 ))
219 }
220 }
221
222 #[doc(alias = "g_permission_get_can_release")]
230 #[doc(alias = "get_can_release")]
231 #[doc(alias = "can-release")]
232 fn can_release(&self) -> bool {
233 unsafe {
234 from_glib(ffi::g_permission_get_can_release(
235 self.as_ref().to_glib_none().0,
236 ))
237 }
238 }
239
240 #[doc(alias = "g_permission_impl_update")]
252 fn impl_update(&self, allowed: bool, can_acquire: bool, can_release: bool) {
253 unsafe {
254 ffi::g_permission_impl_update(
255 self.as_ref().to_glib_none().0,
256 allowed.into_glib(),
257 can_acquire.into_glib(),
258 can_release.into_glib(),
259 );
260 }
261 }
262
263 #[doc(alias = "g_permission_release")]
285 fn release(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
286 unsafe {
287 let mut error = std::ptr::null_mut();
288 let is_ok = ffi::g_permission_release(
289 self.as_ref().to_glib_none().0,
290 cancellable.map(|p| p.as_ref()).to_glib_none().0,
291 &mut error,
292 );
293 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
294 if error.is_null() {
295 Ok(())
296 } else {
297 Err(from_glib_full(error))
298 }
299 }
300 }
301
302 #[doc(alias = "g_permission_release_async")]
311 fn release_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
312 &self,
313 cancellable: Option<&impl IsA<Cancellable>>,
314 callback: P,
315 ) {
316 let main_context = glib::MainContext::ref_thread_default();
317 let is_main_context_owner = main_context.is_owner();
318 let has_acquired_main_context = (!is_main_context_owner)
319 .then(|| main_context.acquire().ok())
320 .flatten();
321 assert!(
322 is_main_context_owner || has_acquired_main_context.is_some(),
323 "Async operations only allowed if the thread is owning the MainContext"
324 );
325
326 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
327 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
328 unsafe extern "C" fn release_async_trampoline<
329 P: FnOnce(Result<(), glib::Error>) + 'static,
330 >(
331 _source_object: *mut glib::gobject_ffi::GObject,
332 res: *mut crate::ffi::GAsyncResult,
333 user_data: glib::ffi::gpointer,
334 ) {
335 unsafe {
336 let mut error = std::ptr::null_mut();
337 ffi::g_permission_release_finish(_source_object as *mut _, res, &mut error);
338 let result = if error.is_null() {
339 Ok(())
340 } else {
341 Err(from_glib_full(error))
342 };
343 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
344 Box_::from_raw(user_data as *mut _);
345 let callback: P = callback.into_inner();
346 callback(result);
347 }
348 }
349 let callback = release_async_trampoline::<P>;
350 unsafe {
351 ffi::g_permission_release_async(
352 self.as_ref().to_glib_none().0,
353 cancellable.map(|p| p.as_ref()).to_glib_none().0,
354 Some(callback),
355 Box_::into_raw(user_data) as *mut _,
356 );
357 }
358 }
359
360 fn release_future(
361 &self,
362 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
363 Box_::pin(crate::GioFuture::new(
364 self,
365 move |obj, cancellable, send| {
366 obj.release_async(Some(cancellable), move |res| {
367 send.resolve(res);
368 });
369 },
370 ))
371 }
372
373 #[doc(alias = "allowed")]
374 fn connect_allowed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
375 unsafe extern "C" fn notify_allowed_trampoline<P: IsA<Permission>, F: Fn(&P) + 'static>(
376 this: *mut ffi::GPermission,
377 _param_spec: glib::ffi::gpointer,
378 f: glib::ffi::gpointer,
379 ) {
380 unsafe {
381 let f: &F = &*(f as *const F);
382 f(Permission::from_glib_borrow(this).unsafe_cast_ref())
383 }
384 }
385 unsafe {
386 let f: Box_<F> = Box_::new(f);
387 connect_raw(
388 self.as_ptr() as *mut _,
389 c"notify::allowed".as_ptr() as *const _,
390 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
391 notify_allowed_trampoline::<Self, F> as *const (),
392 )),
393 Box_::into_raw(f),
394 )
395 }
396 }
397
398 #[doc(alias = "can-acquire")]
399 fn connect_can_acquire_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
400 unsafe extern "C" fn notify_can_acquire_trampoline<
401 P: IsA<Permission>,
402 F: Fn(&P) + 'static,
403 >(
404 this: *mut ffi::GPermission,
405 _param_spec: glib::ffi::gpointer,
406 f: glib::ffi::gpointer,
407 ) {
408 unsafe {
409 let f: &F = &*(f as *const F);
410 f(Permission::from_glib_borrow(this).unsafe_cast_ref())
411 }
412 }
413 unsafe {
414 let f: Box_<F> = Box_::new(f);
415 connect_raw(
416 self.as_ptr() as *mut _,
417 c"notify::can-acquire".as_ptr() as *const _,
418 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
419 notify_can_acquire_trampoline::<Self, F> as *const (),
420 )),
421 Box_::into_raw(f),
422 )
423 }
424 }
425
426 #[doc(alias = "can-release")]
427 fn connect_can_release_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
428 unsafe extern "C" fn notify_can_release_trampoline<
429 P: IsA<Permission>,
430 F: Fn(&P) + 'static,
431 >(
432 this: *mut ffi::GPermission,
433 _param_spec: glib::ffi::gpointer,
434 f: glib::ffi::gpointer,
435 ) {
436 unsafe {
437 let f: &F = &*(f as *const F);
438 f(Permission::from_glib_borrow(this).unsafe_cast_ref())
439 }
440 }
441 unsafe {
442 let f: Box_<F> = Box_::new(f);
443 connect_raw(
444 self.as_ptr() as *mut _,
445 c"notify::can-release".as_ptr() as *const _,
446 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
447 notify_can_release_trampoline::<Self, F> as *const (),
448 )),
449 Box_::into_raw(f),
450 )
451 }
452 }
453}
454
455impl<O: IsA<Permission>> PermissionExt for O {}