From ae31f9bf7df5489c12633c8c37ea17cccd0670af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Tue, 7 Oct 2025 20:02:09 +0200 Subject: [PATCH 1/4] Make DBusProxy subclassable --- gio/src/subclass/dbus_interface.rs | 17 +++++++++++++++++ gio/src/subclass/dbus_proxy.rs | 23 +++++++++++++++++++++++ gio/src/subclass/mod.rs | 4 ++++ 3 files changed, 44 insertions(+) create mode 100644 gio/src/subclass/dbus_interface.rs create mode 100644 gio/src/subclass/dbus_proxy.rs 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..aa2662efff02 --- /dev/null +++ b/gio/src/subclass/dbus_proxy.rs @@ -0,0 +1,23 @@ +// 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::subclass::prelude::DBusInterfaceImpl; +use crate::DBusProxy; + +pub trait DBusProxyImpl: + ObjectImpl + DBusInterfaceImpl + ObjectSubclass> +{ +} + +pub trait DBusProxyImplExt: DBusProxyImpl {} + +impl DBusProxyImplExt for T {} + +unsafe impl IsSubclassable for DBusProxy { + fn class_init(class: &mut glib::Class) { + Self::parent_class_init::(class); + } +} 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}, From 774667b9363dad20c46198ab7691abae63a9cbf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Tue, 7 Oct 2025 20:02:36 +0200 Subject: [PATCH 2/4] Make signal class handlers overwritable --- gio/src/subclass/dbus_proxy.rs | 89 ++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/gio/src/subclass/dbus_proxy.rs b/gio/src/subclass/dbus_proxy.rs index aa2662efff02..f8bb9bdc427b 100644 --- a/gio/src/subclass/dbus_proxy.rs +++ b/gio/src/subclass/dbus_proxy.rs @@ -2,22 +2,103 @@ #![deny(unsafe_op_in_unsafe_fn)] -use glib::{prelude::*, subclass::prelude::*}; +use glib::{prelude::*, subclass::prelude::*, translate::*, GString, StrVRef}; -use crate::subclass::prelude::DBusInterfaceImpl; -use crate::DBusProxy; +use crate::{ffi, subclass::prelude::DBusInterfaceImpl, DBusProxy}; pub trait DBusProxyImpl: ObjectImpl + DBusInterfaceImpl + 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 {} +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); +} From da2a0099dd4d1d9efe1a1194cf745539e212b365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Tue, 7 Oct 2025 20:19:50 +0200 Subject: [PATCH 3/4] Manually implement connect_g_properties_changed --- gio/Gir.toml | 4 ++-- gio/src/dbus_proxy.rs | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) 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< From 351609b3dccab62a21d76b6378ca9e80ade1319a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Tue, 7 Oct 2025 20:24:00 +0200 Subject: [PATCH 4/4] Add parent interfaces to DBusProxyImpl --- gio/src/subclass/dbus_proxy.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gio/src/subclass/dbus_proxy.rs b/gio/src/subclass/dbus_proxy.rs index f8bb9bdc427b..4eff3cfac2f7 100644 --- a/gio/src/subclass/dbus_proxy.rs +++ b/gio/src/subclass/dbus_proxy.rs @@ -4,10 +4,18 @@ use glib::{prelude::*, subclass::prelude::*, translate::*, GString, StrVRef}; -use crate::{ffi, subclass::prelude::DBusInterfaceImpl, DBusProxy}; +use crate::{ + ffi, + subclass::prelude::{AsyncInitableImpl, DBusInterfaceImpl, InitableImpl}, + DBusProxy, +}; pub trait DBusProxyImpl: - ObjectImpl + DBusInterfaceImpl + ObjectSubclass> + ObjectImpl + + AsyncInitableImpl + + DBusInterfaceImpl + + InitableImpl + + ObjectSubclass> { fn g_properties_changed( &self,