1use crate::{
4 BusType, Cancellable, DBusConnection, DBusObjectManagerClient, DBusObjectManagerClientFlags,
5 DBusObjectProxy, DBusProxy, GioFuture, ffi,
6};
7use glib::object::{Cast as _, IsA};
8use glib::signal::connect_raw;
9use glib::translate::{
10 Borrowed, FromGlibPtrBorrow as _, IntoGlib as _, ToGlibPtr as _, from_glib_borrow,
11 from_glib_full,
12};
13use glib::{SignalHandlerId, StrVRef};
14use std::future::Future;
15use std::pin::Pin;
16
17type DBusProxyTypeFn = Box<
18 dyn Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
19 + Send
20 + Sync
21 + 'static,
22>;
23
24impl DBusObjectManagerClient {
25 #[doc(alias = "g_dbus_object_manager_client_new_sync")]
26 pub fn new_sync(
27 connection: &DBusConnection,
28 flags: DBusObjectManagerClientFlags,
29 name: Option<&str>,
30 object_path: &str,
31 cancellable: Option<&impl IsA<Cancellable>>,
32 ) -> Result<DBusObjectManagerClient, glib::Error> {
33 Self::new_sync_impl(connection, flags, name, object_path, None, cancellable)
34 }
35
36 #[doc(alias = "g_dbus_object_manager_client_new_sync")]
37 pub fn new_sync_with_fn<
38 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
39 + Send
40 + Sync
41 + 'static,
42 >(
43 connection: &DBusConnection,
44 flags: DBusObjectManagerClientFlags,
45 name: Option<&str>,
46 object_path: &str,
47 get_proxy_type_func: F,
48 cancellable: Option<&impl IsA<Cancellable>>,
49 ) -> Result<DBusObjectManagerClient, glib::Error> {
50 Self::new_sync_impl(
51 connection,
52 flags,
53 name,
54 object_path,
55 Some(Box::new(get_proxy_type_func)),
56 cancellable,
57 )
58 }
59
60 #[doc(alias = "g_dbus_object_manager_client_new_for_bus_sync")]
61 pub fn for_bus_sync(
62 bus_type: BusType,
63 flags: DBusObjectManagerClientFlags,
64 name: &str,
65 object_path: &str,
66 cancellable: Option<&impl IsA<Cancellable>>,
67 ) -> Result<DBusObjectManagerClient, glib::Error> {
68 Self::for_bus_sync_impl(bus_type, flags, name, object_path, None, cancellable)
69 }
70
71 #[doc(alias = "g_dbus_object_manager_client_new_for_bus_sync")]
72 pub fn for_bus_sync_with_fn<
73 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
74 + Send
75 + Sync
76 + 'static,
77 >(
78 bus_type: BusType,
79 flags: DBusObjectManagerClientFlags,
80 name: &str,
81 object_path: &str,
82 get_proxy_type_func: F,
83 cancellable: Option<&impl IsA<Cancellable>>,
84 ) -> Result<DBusObjectManagerClient, glib::Error> {
85 Self::for_bus_sync_impl(
86 bus_type,
87 flags,
88 name,
89 object_path,
90 Some(Box::new(get_proxy_type_func)),
91 cancellable,
92 )
93 }
94
95 #[allow(clippy::new_ret_no_self)]
96 #[doc(alias = "g_dbus_object_manager_client_new")]
97 pub fn new<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
98 connection: &DBusConnection,
99 flags: DBusObjectManagerClientFlags,
100 name: &str,
101 object_path: &str,
102 cancellable: Option<&impl IsA<Cancellable>>,
103 callback: P,
104 ) {
105 Self::new_impl(
106 connection,
107 flags,
108 name,
109 object_path,
110 None,
111 cancellable,
112 callback,
113 )
114 }
115
116 #[allow(clippy::new_ret_no_self)]
117 #[doc(alias = "g_dbus_object_manager_client_new")]
118 pub fn new_with_fn<
119 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
120 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
121 + Send
122 + Sync
123 + 'static,
124 >(
125 connection: &DBusConnection,
126 flags: DBusObjectManagerClientFlags,
127 name: &str,
128 object_path: &str,
129 get_proxy_type_func: F,
130 cancellable: Option<&impl IsA<Cancellable>>,
131 callback: P,
132 ) {
133 Self::new_impl(
134 connection,
135 flags,
136 name,
137 object_path,
138 Some(Box::new(get_proxy_type_func)),
139 cancellable,
140 callback,
141 )
142 }
143
144 #[allow(clippy::new_ret_no_self)]
145 fn new_impl<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
146 connection: &DBusConnection,
147 flags: DBusObjectManagerClientFlags,
148 name: &str,
149 object_path: &str,
150 get_proxy_type_func: Option<DBusProxyTypeFn>,
151 cancellable: Option<&impl IsA<Cancellable>>,
152 callback: P,
153 ) {
154 let main_context = glib::MainContext::ref_thread_default();
155 let is_main_context_owner = main_context.is_owner();
156 let has_acquired_main_context = (!is_main_context_owner)
157 .then(|| main_context.acquire().ok())
158 .flatten();
159 assert!(
160 is_main_context_owner || has_acquired_main_context.is_some(),
161 "Async operations only allowed if the thread is owning the MainContext"
162 );
163
164 unsafe extern "C" fn get_proxy_type_func_func(
165 manager: *mut ffi::GDBusObjectManagerClient,
166 object_path: *const std::ffi::c_char,
167 interface_name: *const std::ffi::c_char,
168 data: glib::ffi::gpointer,
169 ) -> glib::ffi::GType {
170 unsafe {
171 let manager = from_glib_borrow(manager);
172 let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
173 let interface_name: Borrowed<Option<glib::GString>> =
174 from_glib_borrow(interface_name);
175 let callback = &*(data as *mut Option<DBusProxyTypeFn>);
176 if let Some(ref callback) = *callback {
177 callback(
178 &manager,
179 object_path.as_str(),
180 (*interface_name).as_ref().map(|s| s.as_str()),
181 )
182 } else {
183 panic!("cannot get closure...")
184 }
185 .into_glib()
186 }
187 }
188
189 unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
190 unsafe {
191 let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
192 }
193 }
194
195 unsafe extern "C" fn new_trampoline<
196 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
197 >(
198 _source_object: *mut glib::gobject_ffi::GObject,
199 res: *mut crate::ffi::GAsyncResult,
200 user_data: glib::ffi::gpointer,
201 ) {
202 unsafe {
203 let mut error = std::ptr::null_mut();
204 let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
205 let result = if error.is_null() {
206 Ok(from_glib_full(ret))
207 } else {
208 Err(from_glib_full(error))
209 };
210 let callback: Box<glib::thread_guard::ThreadGuard<P>> =
211 Box::from_raw(user_data as *mut _);
212 let callback: P = callback.into_inner();
213 callback(result);
214 }
215 }
216
217 let get_proxy_type_user_data = Box::new(get_proxy_type_func);
218 let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
219 Some(get_proxy_type_func_func as _)
220 } else {
221 None
222 };
223 let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
224 Some(get_proxy_type_destroy_notify_func as _)
225 } else {
226 None
227 };
228
229 let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
230 Box::new(glib::thread_guard::ThreadGuard::new(callback));
231 let callback = new_trampoline::<P>;
232
233 unsafe {
234 ffi::g_dbus_object_manager_client_new(
235 connection.to_glib_none().0,
236 flags.into_glib(),
237 name.to_glib_none().0,
238 object_path.to_glib_none().0,
239 get_proxy_type_func,
240 Box::into_raw(get_proxy_type_user_data) as *mut _,
241 get_proxy_type_destroy_notify,
242 cancellable.map(|p| p.as_ref()).to_glib_none().0,
243 Some(callback),
244 Box::into_raw(user_data) as *mut _,
245 );
246 }
247 }
248
249 pub fn new_future(
250 connection: &DBusConnection,
251 flags: DBusObjectManagerClientFlags,
252 name: &str,
253 object_path: &str,
254 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
255 Self::new_future_impl(connection, flags, name, object_path, None)
256 }
257
258 pub fn new_future_with_fn<
259 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
260 + Send
261 + Sync
262 + 'static,
263 >(
264 connection: &DBusConnection,
265 flags: DBusObjectManagerClientFlags,
266 name: &str,
267 object_path: &str,
268 get_proxy_type_func: F,
269 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
270 Self::new_future_impl(
271 connection,
272 flags,
273 name,
274 object_path,
275 Some(Box::new(get_proxy_type_func)),
276 )
277 }
278
279 fn new_future_impl(
280 connection: &DBusConnection,
281 flags: DBusObjectManagerClientFlags,
282 name: &str,
283 object_path: &str,
284 get_proxy_type_func: Option<DBusProxyTypeFn>,
285 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
286 let connection = connection.clone();
287 let name = String::from(name);
288 let object_path = String::from(object_path);
289 Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
290 Self::new_impl(
291 &connection,
292 flags,
293 &name,
294 &object_path,
295 get_proxy_type_func,
296 Some(cancellable),
297 move |res| {
298 send.resolve(res);
299 },
300 );
301 }))
302 }
303
304 #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
305 #[allow(clippy::new_ret_no_self)]
306 pub fn new_for_bus<
307 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
308 >(
309 bus_type: BusType,
310 flags: DBusObjectManagerClientFlags,
311 name: &str,
312 object_path: &str,
313 cancellable: Option<&impl IsA<Cancellable>>,
314 callback: P,
315 ) {
316 Self::new_for_bus_impl(
317 bus_type,
318 flags,
319 name,
320 object_path,
321 None,
322 cancellable,
323 callback,
324 );
325 }
326
327 #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
328 #[allow(clippy::new_ret_no_self)]
329 pub fn new_for_bus_with_fn<
330 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
331 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
332 + Send
333 + Sync
334 + 'static,
335 >(
336 bus_type: BusType,
337 flags: DBusObjectManagerClientFlags,
338 name: &str,
339 object_path: &str,
340 get_proxy_type_func: F,
341 cancellable: Option<&impl IsA<Cancellable>>,
342 callback: P,
343 ) {
344 Self::new_for_bus_impl(
345 bus_type,
346 flags,
347 name,
348 object_path,
349 Some(Box::new(get_proxy_type_func)),
350 cancellable,
351 callback,
352 );
353 }
354
355 #[allow(clippy::new_ret_no_self)]
356 fn new_for_bus_impl<
357 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
358 >(
359 bus_type: BusType,
360 flags: DBusObjectManagerClientFlags,
361 name: &str,
362 object_path: &str,
363 get_proxy_type_func: Option<DBusProxyTypeFn>,
364 cancellable: Option<&impl IsA<Cancellable>>,
365 callback: P,
366 ) {
367 let main_context = glib::MainContext::ref_thread_default();
368 let is_main_context_owner = main_context.is_owner();
369 let has_acquired_main_context = (!is_main_context_owner)
370 .then(|| main_context.acquire().ok())
371 .flatten();
372 assert!(
373 is_main_context_owner || has_acquired_main_context.is_some(),
374 "Async operations only allowed if the thread is owning the MainContext"
375 );
376
377 unsafe extern "C" fn get_proxy_type_func_func(
378 manager: *mut ffi::GDBusObjectManagerClient,
379 object_path: *const std::ffi::c_char,
380 interface_name: *const std::ffi::c_char,
381 data: glib::ffi::gpointer,
382 ) -> glib::ffi::GType {
383 unsafe {
384 let manager = from_glib_borrow(manager);
385 let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
386 let interface_name: Borrowed<Option<glib::GString>> =
387 from_glib_borrow(interface_name);
388 let callback = &*(data as *mut Option<DBusProxyTypeFn>);
389 if let Some(ref callback) = *callback {
390 callback(
391 &manager,
392 object_path.as_str(),
393 (*interface_name).as_ref().map(|s| s.as_str()),
394 )
395 } else {
396 panic!("cannot get closure...")
397 }
398 .into_glib()
399 }
400 }
401
402 unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
403 unsafe {
404 let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
405 }
406 }
407
408 unsafe extern "C" fn new_for_bus_trampoline<
409 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
410 >(
411 _source_object: *mut glib::gobject_ffi::GObject,
412 res: *mut crate::ffi::GAsyncResult,
413 user_data: glib::ffi::gpointer,
414 ) {
415 unsafe {
416 let mut error = std::ptr::null_mut();
417 let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
418 let result = if error.is_null() {
419 Ok(from_glib_full(ret))
420 } else {
421 Err(from_glib_full(error))
422 };
423 let callback: Box<glib::thread_guard::ThreadGuard<P>> =
424 Box::from_raw(user_data as *mut _);
425 let callback: P = callback.into_inner();
426 callback(result);
427 }
428 }
429
430 let get_proxy_type_user_data = Box::new(get_proxy_type_func);
431 let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
432 Some(get_proxy_type_func_func as _)
433 } else {
434 None
435 };
436 let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
437 Some(get_proxy_type_destroy_notify_func as _)
438 } else {
439 None
440 };
441
442 let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
443 Box::new(glib::thread_guard::ThreadGuard::new(callback));
444 let callback = new_for_bus_trampoline::<P>;
445
446 unsafe {
447 ffi::g_dbus_object_manager_client_new_for_bus(
448 bus_type.into_glib(),
449 flags.into_glib(),
450 name.to_glib_none().0,
451 object_path.to_glib_none().0,
452 get_proxy_type_func,
453 Box::into_raw(get_proxy_type_user_data) as *mut _,
454 get_proxy_type_destroy_notify,
455 cancellable.map(|p| p.as_ref()).to_glib_none().0,
456 Some(callback),
457 Box::into_raw(user_data) as *mut _,
458 );
459 }
460 }
461
462 pub fn new_for_bus_future(
463 bus_type: BusType,
464 flags: DBusObjectManagerClientFlags,
465 name: &str,
466 object_path: &str,
467 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
468 Self::new_for_bus_future_impl(bus_type, flags, name, object_path, None)
469 }
470
471 pub fn new_for_bus_future_with_fn<
472 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
473 + Send
474 + Sync
475 + 'static,
476 >(
477 bus_type: BusType,
478 flags: DBusObjectManagerClientFlags,
479 name: &str,
480 object_path: &str,
481 get_proxy_type_func: F,
482 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
483 Self::new_for_bus_future_impl(
484 bus_type,
485 flags,
486 name,
487 object_path,
488 Some(Box::new(get_proxy_type_func)),
489 )
490 }
491
492 fn new_for_bus_future_impl(
493 bus_type: BusType,
494 flags: DBusObjectManagerClientFlags,
495 name: &str,
496 object_path: &str,
497 get_proxy_type_func: Option<DBusProxyTypeFn>,
498 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
499 let name = String::from(name);
500 let object_path = String::from(object_path);
501 Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
502 Self::new_for_bus_impl(
503 bus_type,
504 flags,
505 &name,
506 &object_path,
507 get_proxy_type_func,
508 Some(cancellable),
509 move |res| {
510 send.resolve(res);
511 },
512 );
513 }))
514 }
515}
516
517pub trait DBusObjectManagerClientExtManual: IsA<DBusObjectManagerClient> + 'static {
518 #[doc(alias = "interface-proxy-properties-changed")]
519 fn connect_interface_proxy_properties_changed<
520 F: Fn(&Self, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
521 >(
522 &self,
523 f: F,
524 ) -> SignalHandlerId {
525 unsafe extern "C" fn interface_proxy_properties_changed_trampoline<
526 P: IsA<DBusObjectManagerClient>,
527 F: Fn(&P, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
528 >(
529 this: *mut ffi::GDBusObjectManagerClient,
530 object_proxy: *mut ffi::GDBusObjectProxy,
531 interface_proxy: *mut ffi::GDBusProxy,
532 changed_properties: *mut glib::ffi::GVariant,
533 invalidated_properties: *const *const std::ffi::c_char,
534 f: glib::ffi::gpointer,
535 ) {
536 unsafe {
537 let f: &F = &*(f as *const F);
538 f(
539 DBusObjectManagerClient::from_glib_borrow(this).unsafe_cast_ref(),
540 &from_glib_borrow(object_proxy),
541 &from_glib_borrow(interface_proxy),
542 &from_glib_borrow(changed_properties),
543 StrVRef::from_glib_borrow(invalidated_properties),
544 )
545 }
546 }
547 unsafe {
548 let f: Box<F> = Box::new(f);
549 connect_raw(
550 self.as_ptr() as *mut _,
551 c"interface-proxy-properties-changed".as_ptr() as *const _,
552 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
553 interface_proxy_properties_changed_trampoline::<Self, F> as *const (),
554 )),
555 Box::into_raw(f),
556 )
557 }
558 }
559}
560
561impl<O: IsA<DBusObjectManagerClient>> DBusObjectManagerClientExtManual for O {}