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")]
15 pub struct Permission(Object<ffi::GPermission, ffi::GPermissionClass>);
16
17 match fn {
18 type_ => || ffi::g_permission_get_type(),
19 }
20}
21
22impl Permission {
23 pub const NONE: Option<&'static Permission> = None;
24}
25
26pub trait PermissionExt: IsA<Permission> + 'static {
27 #[doc(alias = "g_permission_acquire")]
28 fn acquire(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
29 unsafe {
30 let mut error = std::ptr::null_mut();
31 let is_ok = ffi::g_permission_acquire(
32 self.as_ref().to_glib_none().0,
33 cancellable.map(|p| p.as_ref()).to_glib_none().0,
34 &mut error,
35 );
36 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
37 if error.is_null() {
38 Ok(())
39 } else {
40 Err(from_glib_full(error))
41 }
42 }
43 }
44
45 #[doc(alias = "g_permission_acquire_async")]
46 fn acquire_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
47 &self,
48 cancellable: Option<&impl IsA<Cancellable>>,
49 callback: P,
50 ) {
51 let main_context = glib::MainContext::ref_thread_default();
52 let is_main_context_owner = main_context.is_owner();
53 let has_acquired_main_context = (!is_main_context_owner)
54 .then(|| main_context.acquire().ok())
55 .flatten();
56 assert!(
57 is_main_context_owner || has_acquired_main_context.is_some(),
58 "Async operations only allowed if the thread is owning the MainContext"
59 );
60
61 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
62 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
63 unsafe extern "C" fn acquire_async_trampoline<
64 P: FnOnce(Result<(), glib::Error>) + 'static,
65 >(
66 _source_object: *mut glib::gobject_ffi::GObject,
67 res: *mut crate::ffi::GAsyncResult,
68 user_data: glib::ffi::gpointer,
69 ) {
70 let mut error = std::ptr::null_mut();
71 ffi::g_permission_acquire_finish(_source_object as *mut _, res, &mut error);
72 let result = if error.is_null() {
73 Ok(())
74 } else {
75 Err(from_glib_full(error))
76 };
77 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
78 Box_::from_raw(user_data as *mut _);
79 let callback: P = callback.into_inner();
80 callback(result);
81 }
82 let callback = acquire_async_trampoline::<P>;
83 unsafe {
84 ffi::g_permission_acquire_async(
85 self.as_ref().to_glib_none().0,
86 cancellable.map(|p| p.as_ref()).to_glib_none().0,
87 Some(callback),
88 Box_::into_raw(user_data) as *mut _,
89 );
90 }
91 }
92
93 fn acquire_future(
94 &self,
95 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
96 Box_::pin(crate::GioFuture::new(
97 self,
98 move |obj, cancellable, send| {
99 obj.acquire_async(Some(cancellable), move |res| {
100 send.resolve(res);
101 });
102 },
103 ))
104 }
105
106 #[doc(alias = "g_permission_get_allowed")]
107 #[doc(alias = "get_allowed")]
108 #[doc(alias = "allowed")]
109 fn is_allowed(&self) -> bool {
110 unsafe {
111 from_glib(ffi::g_permission_get_allowed(
112 self.as_ref().to_glib_none().0,
113 ))
114 }
115 }
116
117 #[doc(alias = "g_permission_get_can_acquire")]
118 #[doc(alias = "get_can_acquire")]
119 #[doc(alias = "can-acquire")]
120 fn can_acquire(&self) -> bool {
121 unsafe {
122 from_glib(ffi::g_permission_get_can_acquire(
123 self.as_ref().to_glib_none().0,
124 ))
125 }
126 }
127
128 #[doc(alias = "g_permission_get_can_release")]
129 #[doc(alias = "get_can_release")]
130 #[doc(alias = "can-release")]
131 fn can_release(&self) -> bool {
132 unsafe {
133 from_glib(ffi::g_permission_get_can_release(
134 self.as_ref().to_glib_none().0,
135 ))
136 }
137 }
138
139 #[doc(alias = "g_permission_impl_update")]
140 fn impl_update(&self, allowed: bool, can_acquire: bool, can_release: bool) {
141 unsafe {
142 ffi::g_permission_impl_update(
143 self.as_ref().to_glib_none().0,
144 allowed.into_glib(),
145 can_acquire.into_glib(),
146 can_release.into_glib(),
147 );
148 }
149 }
150
151 #[doc(alias = "g_permission_release")]
152 fn release(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
153 unsafe {
154 let mut error = std::ptr::null_mut();
155 let is_ok = ffi::g_permission_release(
156 self.as_ref().to_glib_none().0,
157 cancellable.map(|p| p.as_ref()).to_glib_none().0,
158 &mut error,
159 );
160 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
161 if error.is_null() {
162 Ok(())
163 } else {
164 Err(from_glib_full(error))
165 }
166 }
167 }
168
169 #[doc(alias = "g_permission_release_async")]
170 fn release_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
171 &self,
172 cancellable: Option<&impl IsA<Cancellable>>,
173 callback: P,
174 ) {
175 let main_context = glib::MainContext::ref_thread_default();
176 let is_main_context_owner = main_context.is_owner();
177 let has_acquired_main_context = (!is_main_context_owner)
178 .then(|| main_context.acquire().ok())
179 .flatten();
180 assert!(
181 is_main_context_owner || has_acquired_main_context.is_some(),
182 "Async operations only allowed if the thread is owning the MainContext"
183 );
184
185 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
186 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
187 unsafe extern "C" fn release_async_trampoline<
188 P: FnOnce(Result<(), glib::Error>) + 'static,
189 >(
190 _source_object: *mut glib::gobject_ffi::GObject,
191 res: *mut crate::ffi::GAsyncResult,
192 user_data: glib::ffi::gpointer,
193 ) {
194 let mut error = std::ptr::null_mut();
195 ffi::g_permission_release_finish(_source_object as *mut _, res, &mut error);
196 let result = if error.is_null() {
197 Ok(())
198 } else {
199 Err(from_glib_full(error))
200 };
201 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
202 Box_::from_raw(user_data as *mut _);
203 let callback: P = callback.into_inner();
204 callback(result);
205 }
206 let callback = release_async_trampoline::<P>;
207 unsafe {
208 ffi::g_permission_release_async(
209 self.as_ref().to_glib_none().0,
210 cancellable.map(|p| p.as_ref()).to_glib_none().0,
211 Some(callback),
212 Box_::into_raw(user_data) as *mut _,
213 );
214 }
215 }
216
217 fn release_future(
218 &self,
219 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
220 Box_::pin(crate::GioFuture::new(
221 self,
222 move |obj, cancellable, send| {
223 obj.release_async(Some(cancellable), move |res| {
224 send.resolve(res);
225 });
226 },
227 ))
228 }
229
230 #[doc(alias = "allowed")]
231 fn connect_allowed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
232 unsafe extern "C" fn notify_allowed_trampoline<P: IsA<Permission>, F: Fn(&P) + 'static>(
233 this: *mut ffi::GPermission,
234 _param_spec: glib::ffi::gpointer,
235 f: glib::ffi::gpointer,
236 ) {
237 let f: &F = &*(f as *const F);
238 f(Permission::from_glib_borrow(this).unsafe_cast_ref())
239 }
240 unsafe {
241 let f: Box_<F> = Box_::new(f);
242 connect_raw(
243 self.as_ptr() as *mut _,
244 c"notify::allowed".as_ptr() as *const _,
245 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
246 notify_allowed_trampoline::<Self, F> as *const (),
247 )),
248 Box_::into_raw(f),
249 )
250 }
251 }
252
253 #[doc(alias = "can-acquire")]
254 fn connect_can_acquire_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
255 unsafe extern "C" fn notify_can_acquire_trampoline<
256 P: IsA<Permission>,
257 F: Fn(&P) + 'static,
258 >(
259 this: *mut ffi::GPermission,
260 _param_spec: glib::ffi::gpointer,
261 f: glib::ffi::gpointer,
262 ) {
263 let f: &F = &*(f as *const F);
264 f(Permission::from_glib_borrow(this).unsafe_cast_ref())
265 }
266 unsafe {
267 let f: Box_<F> = Box_::new(f);
268 connect_raw(
269 self.as_ptr() as *mut _,
270 c"notify::can-acquire".as_ptr() as *const _,
271 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
272 notify_can_acquire_trampoline::<Self, F> as *const (),
273 )),
274 Box_::into_raw(f),
275 )
276 }
277 }
278
279 #[doc(alias = "can-release")]
280 fn connect_can_release_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
281 unsafe extern "C" fn notify_can_release_trampoline<
282 P: IsA<Permission>,
283 F: Fn(&P) + 'static,
284 >(
285 this: *mut ffi::GPermission,
286 _param_spec: glib::ffi::gpointer,
287 f: glib::ffi::gpointer,
288 ) {
289 let f: &F = &*(f as *const F);
290 f(Permission::from_glib_borrow(this).unsafe_cast_ref())
291 }
292 unsafe {
293 let f: Box_<F> = Box_::new(f);
294 connect_raw(
295 self.as_ptr() as *mut _,
296 c"notify::can-release".as_ptr() as *const _,
297 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
298 notify_can_release_trampoline::<Self, F> as *const (),
299 )),
300 Box_::into_raw(f),
301 )
302 }
303 }
304}
305
306impl<O: IsA<Permission>> PermissionExt for O {}