Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gio/Gir.toml
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,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"
Expand Down
38 changes: 37 additions & 1 deletion gio/src/dbus_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DBusProxy> + '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<DBusProxy>,
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_<F> = 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::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}

#[cfg(feature = "v2_72")]
#[doc(alias = "g-signal")]
fn connect_g_signal<
Expand Down
17 changes: 17 additions & 0 deletions gio/src/subclass/dbus_interface.rs
Original file line number Diff line number Diff line change
@@ -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<Type: IsA<DBusInterface>> {}

pub trait DBusInterfaceImplExt: DBusInterfaceImpl {}

impl<T: DBusInterfaceImpl> DBusInterfaceImplExt for T {}

unsafe impl<T: DBusInterfaceImpl> IsImplementable<T> for DBusInterface {
fn interface_init(_iface: &mut glib::Interface<Self>) {}
}
112 changes: 112 additions & 0 deletions gio/src/subclass/dbus_proxy.rs
Original file line number Diff line number Diff line change
@@ -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<Type: IsA<DBusProxy>>
{
fn g_properties_changed(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the g_ prefix

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's how it's called though. The signal is g-properties-changed for whatever reason :)

&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::<DBusProxy>().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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sender_name: Option<&str>,
signal_name: &str,
sender_name: Option<&glib::GStr>,
signal_name: &glib::GStr,

maybe so we don't have to do heap allocations for all the NUL-termination?

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::<DBusProxy>().to_glib_none().0,
sender_name.to_glib_none().0,
signal_name.to_glib_none().0,
parameters.to_glib_none().0,
);
}
}
}
}

impl<T: DBusProxyImpl> DBusProxyImplExt for T {}

unsafe impl<T: DBusProxyImpl> IsSubclassable<T> for DBusProxy {
fn class_init(class: &mut glib::Class<Self>) {
Self::parent_class_init::<T>(class);
let class = class.as_mut();
class.g_properties_changed = Some(g_properties_changed::<T>);
class.g_signal = Some(g_signal::<T>);
}
}

unsafe extern "C" fn g_properties_changed<T: DBusProxyImpl>(
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<T: DBusProxyImpl>(
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::<GString>::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, &parameters);
}
4 changes: 4 additions & 0 deletions gio/src/subclass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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},
Expand Down
Loading