Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 57d26c4

Browse files
committed
Add support for overriding signal class handlers and chaining up
1 parent 137eedd commit 57d26c4

File tree

4 files changed

+98
-11
lines changed

4 files changed

+98
-11
lines changed

src/subclass/interface.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub trait ObjectInterfaceExt: ObjectInterface {
165165
ret_type: Type,
166166
class_handler: F,
167167
) where
168-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
168+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
169169
{
170170
unsafe {
171171
super::types::add_signal_with_class_handler(
@@ -230,7 +230,7 @@ pub trait ObjectInterfaceExt: ObjectInterface {
230230
class_handler: F,
231231
accumulator: G,
232232
) where
233-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
233+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
234234
G: Fn(&super::SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
235235
{
236236
unsafe {

src/subclass/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,6 @@ pub mod prelude {
195195
pub use self::boxed::register_boxed_type;
196196
pub use self::interface::register_interface;
197197
pub use self::object::Property;
198-
pub use self::types::{register_type, InitializingType, SignalInvocationHint, TypeData};
198+
pub use self::types::{
199+
register_type, InitializingType, SignalClassHandlerToken, SignalInvocationHint, TypeData,
200+
};

src/subclass/object.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::mem;
1212
use std::ptr;
1313

1414
use translate::*;
15-
use {Object, ObjectClass, SignalFlags, Type, Value};
15+
use {Object, ObjectClass, ObjectType, SignalFlags, Type, Value};
1616

1717
use super::prelude::*;
1818
use super::types;
@@ -202,7 +202,7 @@ pub unsafe trait ObjectClassSubclassExt: Sized + 'static {
202202
ret_type: Type,
203203
class_handler: F,
204204
) where
205-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
205+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
206206
{
207207
unsafe {
208208
super::types::add_signal_with_class_handler(
@@ -267,7 +267,7 @@ pub unsafe trait ObjectClassSubclassExt: Sized + 'static {
267267
class_handler: F,
268268
accumulator: G,
269269
) where
270-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
270+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
271271
G: Fn(&super::SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
272272
{
273273
unsafe {
@@ -282,6 +282,19 @@ pub unsafe trait ObjectClassSubclassExt: Sized + 'static {
282282
);
283283
}
284284
}
285+
286+
fn override_signal_class_handler<F>(&mut self, name: &str, class_handler: F)
287+
where
288+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
289+
{
290+
unsafe {
291+
super::types::signal_override_class_handler(
292+
name,
293+
*(self as *mut _ as *mut ffi::GType),
294+
class_handler,
295+
);
296+
}
297+
}
285298
}
286299

287300
unsafe impl ObjectClassSubclassExt for ObjectClass {}
@@ -297,6 +310,24 @@ unsafe impl<T: ObjectSubclass> IsSubclassable<T> for ObjectClass {
297310
}
298311
}
299312

313+
pub trait ObjectImplExt: ObjectImpl + ObjectSubclass {
314+
fn signal_chain_from_overridden(
315+
&self,
316+
token: &super::SignalClassHandlerToken,
317+
values: &[Value],
318+
) -> Option<Value> {
319+
unsafe {
320+
super::types::signal_chain_from_overridden(
321+
self.get_instance().as_ptr() as *mut _,
322+
token,
323+
values,
324+
)
325+
}
326+
}
327+
}
328+
329+
impl<T: ObjectImpl + ObjectSubclass> ObjectImplExt for T {}
330+
300331
#[cfg(test)]
301332
mod test {
302333
use super::super::super::object::ObjectExt;
@@ -360,7 +391,7 @@ mod test {
360391
SignalFlags::RUN_LAST | SignalFlags::ACTION,
361392
&[String::static_type()],
362393
String::static_type(),
363-
|args| {
394+
|_, args| {
364395
let obj = args[0].get::<Object>().unwrap();
365396
let new_name = args[1].get::<String>().unwrap();
366397
let imp = Self::from_instance(&obj);

src/subclass/types.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,8 @@ pub(crate) unsafe fn add_signal_with_accumulator<F>(
580580
);
581581
}
582582

583+
pub struct SignalClassHandlerToken(*mut gobject_ffi::GTypeInstance);
584+
583585
pub(crate) unsafe fn add_signal_with_class_handler<F>(
584586
type_: ffi::GType,
585587
name: &str,
@@ -588,10 +590,13 @@ pub(crate) unsafe fn add_signal_with_class_handler<F>(
588590
ret_type: Type,
589591
class_handler: F,
590592
) where
591-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
593+
F: Fn(&SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
592594
{
593595
let arg_types = arg_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
594-
let class_handler = Closure::new(class_handler);
596+
let class_handler = Closure::new(move |values| {
597+
let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
598+
class_handler(&SignalClassHandlerToken(instance as *mut _), values)
599+
});
595600

596601
gobject_ffi::g_signal_newv(
597602
name.to_glib_none().0,
@@ -616,12 +621,15 @@ pub(crate) unsafe fn add_signal_with_class_handler_and_accumulator<F, G>(
616621
class_handler: F,
617622
accumulator: G,
618623
) where
619-
F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
624+
F: Fn(&SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
620625
G: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
621626
{
622627
let arg_types = arg_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
623628

624-
let class_handler = Closure::new(class_handler);
629+
let class_handler = Closure::new(move |values| {
630+
let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
631+
class_handler(&SignalClassHandlerToken(instance as *mut _), values)
632+
});
625633
let accumulator: Box<G> = Box::new(accumulator);
626634

627635
unsafe extern "C" fn accumulator_trampoline<
@@ -654,3 +662,49 @@ pub(crate) unsafe fn add_signal_with_class_handler_and_accumulator<F, G>(
654662
arg_types.as_ptr() as *mut _,
655663
);
656664
}
665+
666+
pub(crate) unsafe fn signal_override_class_handler<F>(
667+
name: &str,
668+
type_: ffi::GType,
669+
class_handler: F,
670+
) where
671+
F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
672+
{
673+
let class_handler = Closure::new(move |values| {
674+
let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
675+
class_handler(&SignalClassHandlerToken(instance as *mut _), values)
676+
});
677+
678+
let mut signal_id = 0;
679+
let found: bool = from_glib(gobject_ffi::g_signal_parse_name(
680+
name.to_glib_none().0,
681+
type_,
682+
&mut signal_id,
683+
ptr::null_mut(),
684+
false.to_glib(),
685+
));
686+
687+
if !found {
688+
panic!("Signal '{}' not found", name);
689+
}
690+
691+
gobject_ffi::g_signal_override_class_closure(signal_id, type_, class_handler.to_glib_none().0);
692+
}
693+
694+
pub(crate) unsafe fn signal_chain_from_overridden(
695+
instance: *mut gobject_ffi::GTypeInstance,
696+
token: &SignalClassHandlerToken,
697+
values: &[Value],
698+
) -> Option<Value> {
699+
assert_eq!(instance, token.0);
700+
let mut result = Value::uninitialized();
701+
gobject_ffi::g_signal_chain_from_overridden(
702+
values.as_ptr() as *mut Value as *mut gobject_ffi::GValue,
703+
result.to_glib_none_mut().0,
704+
);
705+
if result.type_() != Type::Unit && result.type_() != Type::Invalid {
706+
Some(result)
707+
} else {
708+
None
709+
}
710+
}

0 commit comments

Comments
 (0)