diff --git a/gio/Gir.toml b/gio/Gir.toml index 578d7610b502..1f4d0476369a 100644 --- a/gio/Gir.toml +++ b/gio/Gir.toml @@ -706,8 +706,8 @@ concurrency = "send+sync" manual_traits = ["DBusProxyExtManual"] [[object.signal]] name = "g-properties-changed" - # libc::c_char vs str - ignore = true + # **libc::c_char not handled by generator + manual = true [[object.function]] pattern = ".+_unix_fd.+" cfg_condition = "unix" diff --git a/gio/src/dbus_proxy.rs b/gio/src/dbus_proxy.rs index 7f243dba8e01..a8f5b2cc0ed4 100644 --- a/gio/src/dbus_proxy.rs +++ b/gio/src/dbus_proxy.rs @@ -2,11 +2,47 @@ use std::{boxed::Box as Box_, mem::transmute}; -use glib::{prelude::*, signal::connect_raw, translate::*, SignalHandlerId}; +use glib::{prelude::*, signal::connect_raw, translate::*, SignalHandlerId, StrVRef}; use crate::{ffi, DBusProxy}; pub trait DBusProxyExtManual: IsA + 'static { + #[doc(alias = "g-properties-changed")] + fn connect_g_properties_changed< + F: Fn(&Self, &glib::Variant, &StrVRef) + Send + Sync + 'static, + >( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn g_properties_changed_trampoline< + P: IsA, + F: Fn(&P, &glib::Variant, &StrVRef) + Send + Sync + 'static, + >( + this: *mut ffi::GDBusProxy, + changed_properties: *mut glib::ffi::GVariant, + invalidated_properties: *const *const libc::c_char, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f( + DBusProxy::from_glib_borrow(this).unsafe_cast_ref(), + &from_glib_borrow(changed_properties), + StrVRef::from_glib_borrow(invalidated_properties), + ) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + c"g-properties-changed".as_ptr() as *const _, + Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>( + g_properties_changed_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + #[cfg(feature = "v2_72")] #[doc(alias = "g-signal")] fn connect_g_signal< diff --git a/gio/src/subclass/dbus_interface.rs b/gio/src/subclass/dbus_interface.rs new file mode 100644 index 000000000000..37bb439e60d2 --- /dev/null +++ b/gio/src/subclass/dbus_interface.rs @@ -0,0 +1,17 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#![deny(unsafe_op_in_unsafe_fn)] + +use glib::{prelude::*, subclass::prelude::*}; + +use crate::DBusInterface; + +pub trait DBusInterfaceImpl: ObjectImpl + ObjectSubclass> {} + +pub trait DBusInterfaceImplExt: DBusInterfaceImpl {} + +impl DBusInterfaceImplExt for T {} + +unsafe impl IsImplementable for DBusInterface { + fn interface_init(_iface: &mut glib::Interface) {} +} diff --git a/gio/src/subclass/dbus_proxy.rs b/gio/src/subclass/dbus_proxy.rs new file mode 100644 index 000000000000..4eff3cfac2f7 --- /dev/null +++ b/gio/src/subclass/dbus_proxy.rs @@ -0,0 +1,112 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#![deny(unsafe_op_in_unsafe_fn)] + +use glib::{prelude::*, subclass::prelude::*, translate::*, GString, StrVRef}; + +use crate::{ + ffi, + subclass::prelude::{AsyncInitableImpl, DBusInterfaceImpl, InitableImpl}, + DBusProxy, +}; + +pub trait DBusProxyImpl: + ObjectImpl + + AsyncInitableImpl + + DBusInterfaceImpl + + InitableImpl + + ObjectSubclass> +{ + fn g_properties_changed( + &self, + changed_properties: &glib::Variant, + invalidated_properties: &StrVRef, + ) { + self.parent_g_properties_changed(changed_properties, invalidated_properties); + } + + fn g_signal(&self, sender_name: Option<&str>, signal_name: &str, parameters: &glib::Variant) { + self.parent_g_signal(sender_name, signal_name, parameters); + } +} + +pub trait DBusProxyImplExt: DBusProxyImpl { + fn parent_g_properties_changed( + &self, + changed_properties: &glib::Variant, + invalidated_properties: &StrVRef, + ) { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *const ffi::GDBusProxyClass; + + if let Some(f) = (*parent_class).g_properties_changed { + f( + self.obj().unsafe_cast_ref::().to_glib_none().0, + changed_properties.to_glib_none().0, + invalidated_properties.to_glib_none().0, + ); + } + } + } + + fn parent_g_signal( + &self, + sender_name: Option<&str>, + signal_name: &str, + parameters: &glib::Variant, + ) { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *const ffi::GDBusProxyClass; + + if let Some(f) = (*parent_class).g_signal { + f( + self.obj().unsafe_cast_ref::().to_glib_none().0, + sender_name.to_glib_none().0, + signal_name.to_glib_none().0, + parameters.to_glib_none().0, + ); + } + } + } +} + +impl DBusProxyImplExt for T {} + +unsafe impl IsSubclassable for DBusProxy { + fn class_init(class: &mut glib::Class) { + Self::parent_class_init::(class); + let class = class.as_mut(); + class.g_properties_changed = Some(g_properties_changed::); + class.g_signal = Some(g_signal::); + } +} + +unsafe extern "C" fn g_properties_changed( + proxy: *mut ffi::GDBusProxy, + changed_properties: *mut glib::ffi::GVariant, + invalidated_properties: *const *const libc::c_char, +) { + let instance = unsafe { &*(proxy as *mut T::Instance) }; + let imp = instance.imp(); + + let changed_properties = unsafe { from_glib_borrow(changed_properties) }; + let invalidated_properties = unsafe { StrVRef::from_glib_borrow(invalidated_properties) }; + imp.g_properties_changed(&changed_properties, invalidated_properties); +} + +unsafe extern "C" fn g_signal( + proxy: *mut ffi::GDBusProxy, + sender_name: *const libc::c_char, + signal_name: *const libc::c_char, + parameters: *mut glib::ffi::GVariant, +) { + let instance = unsafe { &*(proxy as *mut T::Instance) }; + let imp = instance.imp(); + + let sender_name = unsafe { Option::::from_glib_borrow(sender_name) }; + let signal_name = unsafe { GString::from_glib_borrow(signal_name) }; + let parameters = unsafe { from_glib_borrow(parameters) }; + imp.g_signal(sender_name.as_ref().as_deref(), &signal_name, ¶meters); +} diff --git a/gio/src/subclass/mod.rs b/gio/src/subclass/mod.rs index e2626fa35c65..7bdbe29268a5 100644 --- a/gio/src/subclass/mod.rs +++ b/gio/src/subclass/mod.rs @@ -4,6 +4,8 @@ mod action_group; mod action_map; mod application; mod async_initable; +mod dbus_interface; +mod dbus_proxy; mod file_enumerator; mod file_monitor; mod initable; @@ -26,6 +28,8 @@ pub mod prelude { action_map::{ActionMapImpl, ActionMapImplExt}, application::{ApplicationImpl, ApplicationImplExt}, async_initable::{AsyncInitableImpl, AsyncInitableImplExt}, + dbus_interface::{DBusInterfaceImpl, DBusInterfaceImplExt}, + dbus_proxy::{DBusProxyImpl, DBusProxyImplExt}, file_enumerator::{FileEnumeratorImpl, FileEnumeratorImplExt}, file_monitor::{FileMonitorImpl, FileMonitorImplExt}, initable::{InitableImpl, InitableImplExt},