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