From 6a64a88693254cbcf9ab370522dbd861793bcd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 21 Nov 2024 11:11:48 +0200 Subject: [PATCH] glib: Remove `SignalClassHandlerToken` from default class handler It's only needed for overridden class handlers, not the default one. Also add a test for overriding a signal class handler. --- glib/src/subclass/object.rs | 64 ++++++++++++++++++++++++++++++++++++- glib/src/subclass/signal.rs | 19 +++-------- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/glib/src/subclass/object.rs b/glib/src/subclass/object.rs index 312a28b891a0..f3a81c5e4fd0 100644 --- a/glib/src/subclass/object.rs +++ b/glib/src/subclass/object.rs @@ -404,7 +404,7 @@ mod test { .param_types([String::static_type()]) .return_type::() .action() - .class_handler(|_, args| { + .class_handler(|args| { let obj = args[0] .get::() .expect("Failed to get Object from args[0]"); @@ -426,6 +426,16 @@ mod test { super::Signal::builder("create-child-object") .return_type::() .build(), + super::Signal::builder("return-string") + .return_type::() + .action() + .class_handler(|args| { + let _obj = args[0] + .get::() + .expect("Failed to get Object from args[0]"); + Some("base".to_value()) + }) + .build(), ] }) } @@ -487,6 +497,33 @@ mod test { } } + #[derive(Default)] + pub struct SimpleSubObject; + + #[glib::object_subclass] + impl ObjectSubclass for SimpleSubObject { + const NAME: &'static str = "SimpleSubObject"; + type Type = super::SimpleSubObject; + type ParentType = super::SimpleObject; + + fn class_init(class: &mut Self::Class) { + class.override_signal_class_handler("return-string", |token, args| { + let obj = args[0] + .get::() + .expect("Failed to get Object from args[0]"); + + let res = obj.imp().signal_chain_from_overridden(token, args); + assert_eq!(res.unwrap().get::<&str>().unwrap(), "base"); + + Some("sub".to_value()) + }); + } + } + + impl ObjectImpl for SimpleSubObject {} + + impl SimpleObjectImpl for SimpleSubObject {} + #[derive(Clone, Copy)] #[repr(C)] pub struct DummyInterface { @@ -514,6 +551,14 @@ mod test { pub struct SimpleObject(ObjectSubclass); } + pub trait SimpleObjectImpl: ObjectImpl {} + + unsafe impl IsSubclassable for SimpleObject {} + + wrapper! { + pub struct SimpleSubObject(ObjectSubclass) @extends SimpleObject; + } + wrapper! { pub struct Dummy(ObjectInterface); } @@ -543,6 +588,14 @@ mod test { assert!(weak.upgrade().is_none()); } + #[test] + fn test_sub_create() { + let obj = Object::builder::().build(); + assert!(obj.type_().is_a(SimpleObject::static_type())); + assert_eq!(obj.type_(), SimpleSubObject::static_type()); + assert!(obj.property::("constructed")); + } + #[test] fn test_properties() { let type_ = SimpleObject::static_type(); @@ -829,6 +882,8 @@ mod test { "old-name" ); assert!(name_changed_triggered.load(Ordering::Relaxed)); + + assert_eq!(obj.emit_by_name::("return-string", &[]), "base"); } #[test] @@ -845,6 +900,13 @@ mod test { assert_eq!(value, "return value"); } + #[test] + fn test_signal_override() { + let obj = Object::builder::().build(); + + assert_eq!(obj.emit_by_name::("return-string", &[]), "sub"); + } + #[test] fn test_callback_validity() { use std::sync::{ diff --git a/glib/src/subclass/signal.rs b/glib/src/subclass/signal.rs index 20dc09c288f1..bcaa18f4ff3d 100644 --- a/glib/src/subclass/signal.rs +++ b/glib/src/subclass/signal.rs @@ -16,9 +16,7 @@ pub struct SignalBuilder { flags: SignalFlags, param_types: Vec, return_type: SignalType, - class_handler: Option< - Box Option + Send + Sync + 'static>, - >, + class_handler: Option Option + Send + Sync + 'static>>, accumulator: Option< Box bool + Send + Sync + 'static>, >, @@ -352,11 +350,7 @@ impl IntoGlib for SignalType { #[allow(clippy::type_complexity)] enum SignalRegistration { Unregistered { - class_handler: Option< - Box< - dyn Fn(&SignalClassHandlerToken, &[Value]) -> Option + Send + Sync + 'static, - >, - >, + class_handler: Option Option + Send + Sync + 'static>>, accumulator: Option< Box bool + Send + Sync + 'static>, >, @@ -472,9 +466,7 @@ impl SignalBuilder { // rustdoc-stripper-ignore-next /// Class handler for this signal. - pub fn class_handler< - F: Fn(&SignalClassHandlerToken, &[Value]) -> Option + Send + Sync + 'static, - >( + pub fn class_handler Option + Send + Sync + 'static>( mut self, func: F, ) -> Self { @@ -610,9 +602,8 @@ impl Signal { let return_type = self.return_type; let class_handler = class_handler.map(|class_handler| { - Closure::new(move |values| unsafe { - let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0); - let res = class_handler(&SignalClassHandlerToken(instance as *mut _, return_type.into(), values.as_ptr()), values); + Closure::new(move |values| { + let res = class_handler(values); if return_type == Type::UNIT { if let Some(ref v) = res {