1 // Copyright 2017-2018, The Gtk-rs Project Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution.
3 // Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4 
5 //! Module that contains the basic infrastructure for subclassing `GObject`.
6 
7 use super::object::ObjectImpl;
8 use glib_sys;
9 use gobject_sys;
10 use object::{ObjectExt, ObjectType};
11 use std::fmt;
12 use std::marker;
13 use std::mem;
14 use std::ptr;
15 use translate::*;
16 use {Closure, IsA, IsClassFor, SignalFlags, StaticType, Type, Value};
17 
18 /// A newly registered `glib::Type` that is currently still being initialized.
19 ///
20 /// This allows running additional type-setup functions, e.g. for implementing
21 /// interfaces on the type.
22 #[derive(Debug, PartialEq, Eq)]
23 pub struct InitializingType<T>(pub(crate) Type, pub(crate) marker::PhantomData<T>);
24 
25 impl<T: ObjectSubclass> InitializingType<T> {
26     /// Adds an interface implementation for `I` to the type.
add_interface<I: IsImplementable<T>>(&mut self)27     pub fn add_interface<I: IsImplementable<T>>(&mut self) {
28         unsafe {
29             let iface_info = gobject_sys::GInterfaceInfo {
30                 interface_init: Some(I::interface_init),
31                 interface_finalize: None,
32                 interface_data: ptr::null_mut(),
33             };
34             gobject_sys::g_type_add_interface_static(
35                 self.0.to_glib(),
36                 I::static_type().to_glib(),
37                 &iface_info,
38             );
39         }
40     }
41 }
42 
43 impl<T> ToGlib for InitializingType<T> {
44     type GlibType = glib_sys::GType;
45 
to_glib(&self) -> glib_sys::GType46     fn to_glib(&self) -> glib_sys::GType {
47         self.0.to_glib()
48     }
49 }
50 
51 /// Trait implemented by structs that implement a `GObject` C instance struct.
52 ///
53 /// The struct must be `#[repr(C)]` and have the parent type's instance struct
54 /// as the first field.
55 ///
56 /// See [`simple::InstanceStruct`] for a basic implementation of this that can
57 /// be used most of the time and should only not be used if additional fields are
58 /// required in the instance struct.
59 ///
60 /// [`simple::InstanceStruct`]: ../simple/struct.InstanceStruct.html
61 pub unsafe trait InstanceStruct: Sized + 'static {
62     /// Corresponding object subclass type for this instance struct.
63     type Type: ObjectSubclass;
64 
65     /// Returns the implementation for from this instance struct, that
66     /// is the implementor of [`ObjectImpl`] or subtraits.
67     ///
68     /// [`ObjectImpl`]: ../object/trait.ObjectImpl.html
get_impl(&self) -> &Self::Type69     fn get_impl(&self) -> &Self::Type {
70         unsafe {
71             let data = Self::Type::type_data();
72             let private_offset = data.as_ref().private_offset;
73             let ptr: *const u8 = self as *const _ as *const u8;
74             let priv_ptr = ptr.offset(private_offset);
75             let imp = priv_ptr as *const Option<Self::Type>;
76 
77             (*imp).as_ref().expect("No private struct")
78         }
79     }
80 
81     /// Returns the class struct for this specific instance.
get_class(&self) -> &<Self::Type as ObjectSubclass>::Class82     fn get_class(&self) -> &<Self::Type as ObjectSubclass>::Class {
83         unsafe { &**(self as *const _ as *const *const <Self::Type as ObjectSubclass>::Class) }
84     }
85 }
86 
87 /// Trait implemented by structs that implement a `GObject` C class struct.
88 ///
89 /// The struct must be `#[repr(C)]` and have the parent type's class struct
90 /// as the first field.
91 ///
92 /// See [`simple::ClassStruct`] for a basic implementation of this that can
93 /// be used most of the time and should only not be used if additional fields are
94 /// required in the class struct, e.g. for declaring new virtual methods.
95 ///
96 /// [`simple::ClassStruct`]: ../simple/struct.ClassStruct.html
97 pub unsafe trait ClassStruct: Sized + 'static {
98     /// Corresponding object subclass type for this class struct.
99     type Type: ObjectSubclass;
100 
101     /// Override the vfuncs of all parent types.
102     ///
103     /// This is automatically called during type initialization.
override_vfuncs(&mut self) where <<Self::Type as ObjectSubclass>::ParentType as ObjectType>::RustClassType: IsSubclassable<Self::Type>,104     fn override_vfuncs(&mut self)
105     where
106         <<Self::Type as ObjectSubclass>::ParentType as ObjectType>::RustClassType:
107             IsSubclassable<Self::Type>,
108     {
109         unsafe {
110             let base = &mut *(self as *mut _
111                 as *mut <<Self::Type as ObjectSubclass>::ParentType as ObjectType>::RustClassType);
112             base.override_vfuncs();
113         }
114     }
115 }
116 
117 /// Trait for subclassable class structs.
118 pub unsafe trait IsSubclassable<T: ObjectSubclass>: IsClassFor {
119     /// Override the virtual methods of this class for the given subclass.
120     ///
121     /// This is automatically called during type initialization.
override_vfuncs(&mut self)122     fn override_vfuncs(&mut self);
123 }
124 
125 /// Trait for implementable interfaces.
126 pub unsafe trait IsImplementable<T: ObjectSubclass>: StaticType {
127     /// Initializes the interface's virtual methods.
interface_init(iface: glib_sys::gpointer, _iface_data: glib_sys::gpointer)128     unsafe extern "C" fn interface_init(iface: glib_sys::gpointer, _iface_data: glib_sys::gpointer);
129 }
130 
131 /// Type-specific data that is filled in during type creation.
132 pub struct TypeData {
133     #[doc(hidden)]
134     pub type_: Type,
135     #[doc(hidden)]
136     pub parent_class: glib_sys::gpointer,
137     #[doc(hidden)]
138     pub interface_data: *const Vec<(glib_sys::GType, glib_sys::gpointer)>,
139     #[doc(hidden)]
140     pub private_offset: isize,
141 }
142 
143 unsafe impl Send for TypeData {}
144 unsafe impl Sync for TypeData {}
145 
146 impl TypeData {
147     /// Returns the type ID.
get_type(&self) -> Type148     pub fn get_type(&self) -> Type {
149         self.type_
150     }
151 
152     /// Returns a pointer to the native parent class.
153     ///
154     /// This is used for chaining up to the parent class' implementation
155     /// of virtual methods.
get_parent_class(&self) -> glib_sys::gpointer156     pub fn get_parent_class(&self) -> glib_sys::gpointer {
157         self.parent_class
158     }
159 
160     /// Returns a pointer to the interface implementation specific data.
161     ///
162     /// This is used for interface implementations to store additional data.
get_interface_data(&self, type_: glib_sys::GType) -> glib_sys::gpointer163     pub fn get_interface_data(&self, type_: glib_sys::GType) -> glib_sys::gpointer {
164         unsafe {
165             if self.interface_data.is_null() {
166                 return ptr::null_mut();
167             }
168 
169             for &(t, p) in &(*self.interface_data) {
170                 if t == type_ {
171                     return p;
172                 }
173             }
174 
175             ptr::null_mut()
176         }
177     }
178 
179     /// Returns the offset of the private struct in bytes relative to the
180     /// beginning of the instance struct.
get_private_offset(&self) -> isize181     pub fn get_private_offset(&self) -> isize {
182         self.private_offset
183     }
184 }
185 
186 #[macro_export]
187 /// Macro for boilerplate of [`ObjectSubclass`] implementations.
188 ///
189 /// [`ObjectSubclass`]: subclass/types/trait.ObjectSubclass.html
190 macro_rules! glib_object_subclass {
191     () => {
192         fn type_data() -> ::std::ptr::NonNull<$crate::subclass::TypeData> {
193             static mut DATA: $crate::subclass::TypeData = $crate::subclass::TypeData {
194                 type_: $crate::Type::Invalid,
195                 parent_class: ::std::ptr::null_mut(),
196                 interface_data: ::std::ptr::null_mut(),
197                 private_offset: 0,
198             };
199 
200             unsafe { ::std::ptr::NonNull::new_unchecked(&mut DATA) }
201         }
202 
203         fn get_type() -> $crate::Type {
204             static ONCE: ::std::sync::Once = ::std::sync::Once::new();
205 
206             ONCE.call_once(|| {
207                 $crate::subclass::register_type::<Self>();
208             });
209 
210             unsafe {
211                 let data = Self::type_data();
212                 let type_ = data.as_ref().get_type();
213                 assert_ne!(type_, $crate::Type::Invalid);
214 
215                 type_
216             }
217         }
218     };
219 }
220 
221 /// The central trait for subclassing a `GObject` type.
222 ///
223 /// Links together the type name, parent type and the instance and
224 /// class structs for type registration and allows subclasses to
225 /// hook into various steps of the type registration and initialization.
226 ///
227 /// See [`register_type`] for registering an implementation of this trait
228 /// with the type system.
229 ///
230 /// [`register_type`]: fn.register_type.html
231 pub trait ObjectSubclass: ObjectImpl + Sized + 'static {
232     /// `GObject` type name.
233     ///
234     /// This must be unique in the whole process.
235     const NAME: &'static str;
236 
237     /// If this subclass is an abstract class or not.
238     ///
239     /// By default all subclasses are non-abstract types but setting this to `true` will create an
240     /// abstract class instead.
241     ///
242     /// Abstract classes can't be instantiated and require a non-abstract subclass.
243     ///
244     /// Optional.
245     const ABSTRACT: bool = false;
246 
247     /// Parent Rust type to inherit from.
248     type ParentType: ObjectType
249         + FromGlibPtrBorrow<*mut <Self::ParentType as ObjectType>::GlibType>
250         + FromGlibPtrNone<*mut <Self::ParentType as ObjectType>::GlibType>;
251 
252     /// The C instance struct.
253     ///
254     /// See [`simple::InstanceStruct`] for an basic instance struct that should be
255     /// used in most cases.
256     ///
257     /// [`simple::InstanceStruct`]: ../simple/struct.InstanceStruct.html
258     // TODO: Should default to simple::InstanceStruct<Self> once associated
259     // type defaults are stabilized https://github.com/rust-lang/rust/issues/29661
260     type Instance: InstanceStruct<Type = Self>;
261 
262     /// The C class struct.
263     ///
264     /// See [`simple::ClassStruct`] for an basic instance struct that should be
265     /// used in most cases.
266     ///
267     /// [`simple::ClassStruct`]: ../simple/struct.ClassStruct.html
268     // TODO: Should default to simple::ClassStruct<Self> once associated
269     // type defaults are stabilized https://github.com/rust-lang/rust/issues/29661
270     type Class: ClassStruct<Type = Self>;
271 
272     /// Storage for the type-specific data used during registration.
273     ///
274     /// This is usually generated by the [`glib_object_subclass!`] macro.
275     ///
276     /// [`glib_object_subclass!`]: ../../macro.glib_object_subclass.html
type_data() -> ptr::NonNull<TypeData>277     fn type_data() -> ptr::NonNull<TypeData>;
278 
279     /// Returns the `glib::Type` ID of the subclass.
280     ///
281     /// This will register the type with the type system on the first call and is usually generated
282     /// by the [`glib_object_subclass!`] macro.
283     ///
284     /// [`glib_object_subclass!`]: ../../macro.glib_object_subclass.html
get_type() -> Type285     fn get_type() -> Type;
286 
287     /// Returns the corresponding object instance.
get_instance(&self) -> Self::ParentType288     fn get_instance(&self) -> Self::ParentType {
289         unsafe {
290             let data = Self::type_data();
291             let type_ = data.as_ref().get_type();
292             assert_ne!(type_, Type::Invalid);
293 
294             let offset = -data.as_ref().private_offset;
295             assert_ne!(offset, 0);
296 
297             let ptr = self as *const Self as *const u8;
298             let ptr = ptr.offset(offset);
299             let ptr = ptr as *mut u8 as *mut <Self::ParentType as ObjectType>::GlibType;
300 
301             from_glib_none(ptr)
302         }
303     }
304 
305     /// Returns the implementation from an instance.
306     ///
307     /// Panics if called on an object of the wrong type.
from_instance<T: IsA<Self::ParentType>>(obj: &T) -> &Self308     fn from_instance<T: IsA<Self::ParentType>>(obj: &T) -> &Self {
309         unsafe {
310             let data = Self::type_data();
311             let type_ = data.as_ref().get_type();
312             assert_ne!(type_, Type::Invalid);
313 
314             assert!(obj.get_type().is_a(&type_));
315 
316             let ptr = obj.as_ptr() as *const Self::Instance;
317             (*ptr).get_impl()
318         }
319     }
320 
321     /// Additional type initialization.
322     ///
323     /// This is called right after the type was registered and allows
324     /// subclasses to do additional type-specific initialization, e.g.
325     /// for implementing `GObject` interfaces.
326     ///
327     /// Optional
type_init(_type_: &mut InitializingType<Self>)328     fn type_init(_type_: &mut InitializingType<Self>) {}
329 
330     /// Class initialization.
331     ///
332     /// This is called after `type_init` and before the first instance
333     /// of the subclass is created. Subclasses can use this to do class-
334     /// specific initialization, e.g. for installing properties or signals
335     /// on the class or calling class methods.
336     ///
337     /// Optional
class_init(_klass: &mut Self::Class)338     fn class_init(_klass: &mut Self::Class) {}
339 
340     /// Constructor.
341     ///
342     /// This is called during object instantiation before further subclasses
343     /// are initialized, and should return a new instance of the subclass
344     /// private struct.
345     ///
346     /// Optional, either implement this or `new_with_class()`.
new() -> Self347     fn new() -> Self {
348         unimplemented!();
349     }
350 
351     /// Constructor.
352     ///
353     /// This is called during object instantiation before further subclasses
354     /// are initialized, and should return a new instance of the subclass
355     /// private struct.
356     ///
357     /// Different to `new()` above it also gets the class of this type passed
358     /// to itself for providing additional context.
359     ///
360     /// Optional, either implement this or `new()`.
new_with_class(_klass: &Self::Class) -> Self361     fn new_with_class(_klass: &Self::Class) -> Self {
362         Self::new()
363     }
364 }
365 
class_init<T: ObjectSubclass>( klass: glib_sys::gpointer, _klass_data: glib_sys::gpointer, ) where <<T as ObjectSubclass>::ParentType as ObjectType>::RustClassType: IsSubclassable<T>,366 unsafe extern "C" fn class_init<T: ObjectSubclass>(
367     klass: glib_sys::gpointer,
368     _klass_data: glib_sys::gpointer,
369 ) where
370     <<T as ObjectSubclass>::ParentType as ObjectType>::RustClassType: IsSubclassable<T>,
371 {
372     let mut data = T::type_data();
373 
374     // We have to update the private struct offset once the class is actually
375     // being initialized.
376     {
377         let mut private_offset = data.as_ref().private_offset as i32;
378         gobject_sys::g_type_class_adjust_private_offset(klass, &mut private_offset);
379         (*data.as_mut()).private_offset = private_offset as isize;
380     }
381 
382     // Set trampolines for the basic GObject virtual methods.
383     {
384         let gobject_klass = &mut *(klass as *mut gobject_sys::GObjectClass);
385 
386         gobject_klass.finalize = Some(finalize::<T>);
387     }
388 
389     // And finally peek the parent class struct (containing the parent class'
390     // implementations of virtual methods for chaining up), and call the subclass'
391     // class initialization function.
392     {
393         let klass = &mut *(klass as *mut T::Class);
394         let parent_class =
395             gobject_sys::g_type_class_peek_parent(klass as *mut _ as glib_sys::gpointer)
396                 as *mut <T::ParentType as ObjectType>::GlibClassType;
397         assert!(!parent_class.is_null());
398 
399         (*data.as_mut()).parent_class = parent_class as glib_sys::gpointer;
400 
401         klass.override_vfuncs();
402         T::class_init(klass);
403     }
404 }
405 
instance_init<T: ObjectSubclass>( obj: *mut gobject_sys::GTypeInstance, klass: glib_sys::gpointer, )406 unsafe extern "C" fn instance_init<T: ObjectSubclass>(
407     obj: *mut gobject_sys::GTypeInstance,
408     klass: glib_sys::gpointer,
409 ) {
410     glib_floating_reference_guard!(obj);
411 
412     // Get offset to the storage of our private struct, create it
413     // and actually store it in that place.
414     let mut data = T::type_data();
415     let private_offset = (*data.as_mut()).private_offset;
416     let ptr: *mut u8 = obj as *mut _ as *mut u8;
417     let priv_ptr = ptr.offset(private_offset);
418     let imp_storage = priv_ptr as *mut Option<T>;
419 
420     let klass = &*(klass as *const T::Class);
421 
422     let imp = T::new_with_class(klass);
423 
424     ptr::write(imp_storage, Some(imp));
425 }
426 
finalize<T: ObjectSubclass>(obj: *mut gobject_sys::GObject)427 unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_sys::GObject) {
428     // Retrieve the private struct, take it out of its storage and
429     // drop it for freeing all associated memory.
430     let mut data = T::type_data();
431     let private_offset = (*data.as_mut()).private_offset;
432     let ptr: *mut u8 = obj as *mut _ as *mut u8;
433     let priv_ptr = ptr.offset(private_offset);
434     let imp_storage = priv_ptr as *mut Option<T>;
435 
436     let imp = (*imp_storage).take().expect("No private struct");
437     drop(imp);
438 
439     // Chain up to the parent class' finalize implementation, if any.
440     let parent_class = &*(data.as_ref().get_parent_class() as *const gobject_sys::GObjectClass);
441     if let Some(ref func) = parent_class.finalize {
442         func(obj);
443     }
444 }
445 
446 /// Register a `glib::Type` ID for `T`.
447 ///
448 /// This must be called only once and will panic on a second call.
449 ///
450 /// The [`glib_object_subclass!`] macro will create a `get_type()` function around this, which will
451 /// ensure that it's only ever called once.
452 ///
453 /// [`glib_object_subclass!`]: ../../macro.glib_object_subclass.html
register_type<T: ObjectSubclass>() -> Type where <<T as ObjectSubclass>::ParentType as ObjectType>::RustClassType: IsSubclassable<T>,454 pub fn register_type<T: ObjectSubclass>() -> Type
455 where
456     <<T as ObjectSubclass>::ParentType as ObjectType>::RustClassType: IsSubclassable<T>,
457 {
458     unsafe {
459         use std::ffi::CString;
460 
461         let type_info = gobject_sys::GTypeInfo {
462             class_size: mem::size_of::<T::Class>() as u16,
463             base_init: None,
464             base_finalize: None,
465             class_init: Some(class_init::<T>),
466             class_finalize: None,
467             class_data: ptr::null_mut(),
468             instance_size: mem::size_of::<T::Instance>() as u16,
469             n_preallocs: 0,
470             instance_init: Some(instance_init::<T>),
471             value_table: ptr::null(),
472         };
473 
474         let type_name = CString::new(T::NAME).unwrap();
475         if gobject_sys::g_type_from_name(type_name.as_ptr()) != gobject_sys::G_TYPE_INVALID {
476             panic!(
477                 "Type {} has already been registered",
478                 type_name.to_str().unwrap()
479             );
480         }
481 
482         let type_ = from_glib(gobject_sys::g_type_register_static(
483             <T::ParentType as StaticType>::static_type().to_glib(),
484             type_name.as_ptr(),
485             &type_info,
486             if T::ABSTRACT {
487                 gobject_sys::G_TYPE_FLAG_ABSTRACT
488             } else {
489                 0
490             },
491         ));
492 
493         let mut data = T::type_data();
494         (*data.as_mut()).type_ = type_;
495         let private_offset =
496             gobject_sys::g_type_add_instance_private(type_.to_glib(), mem::size_of::<Option<T>>());
497         (*data.as_mut()).private_offset = private_offset as isize;
498 
499         T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
500 
501         type_
502     }
503 }
504 
add_signal( type_: glib_sys::GType, name: &str, flags: SignalFlags, arg_types: &[Type], ret_type: Type, )505 pub(crate) unsafe fn add_signal(
506     type_: glib_sys::GType,
507     name: &str,
508     flags: SignalFlags,
509     arg_types: &[Type],
510     ret_type: Type,
511 ) {
512     let arg_types = arg_types.iter().map(ToGlib::to_glib).collect::<Vec<_>>();
513 
514     gobject_sys::g_signal_newv(
515         name.to_glib_none().0,
516         type_,
517         flags.to_glib(),
518         ptr::null_mut(),
519         None,
520         ptr::null_mut(),
521         None,
522         ret_type.to_glib(),
523         arg_types.len() as u32,
524         arg_types.as_ptr() as *mut _,
525     );
526 }
527 
528 #[repr(C)]
529 pub struct SignalInvocationHint(gobject_sys::GSignalInvocationHint);
530 
531 impl SignalInvocationHint {
detail(&self) -> ::Quark532     pub fn detail(&self) -> ::Quark {
533         from_glib(self.0.detail)
534     }
535 
run_type(&self) -> SignalFlags536     pub fn run_type(&self) -> SignalFlags {
537         from_glib(self.0.run_type)
538     }
539 }
540 
541 impl fmt::Debug for SignalInvocationHint {
fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>542     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
543         f.debug_struct("SignalInvocationHint")
544             .field("detail", &self.detail())
545             .field("run_type", &self.run_type())
546             .finish()
547     }
548 }
549 
add_signal_with_accumulator<F>( type_: glib_sys::GType, name: &str, flags: SignalFlags, arg_types: &[Type], ret_type: Type, accumulator: F, ) where F: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,550 pub(crate) unsafe fn add_signal_with_accumulator<F>(
551     type_: glib_sys::GType,
552     name: &str,
553     flags: SignalFlags,
554     arg_types: &[Type],
555     ret_type: Type,
556     accumulator: F,
557 ) where
558     F: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
559 {
560     let arg_types = arg_types.iter().map(ToGlib::to_glib).collect::<Vec<_>>();
561 
562     let accumulator: Box<F> = Box::new(accumulator);
563 
564     unsafe extern "C" fn accumulator_trampoline<
565         F: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
566     >(
567         ihint: *mut gobject_sys::GSignalInvocationHint,
568         return_accu: *mut gobject_sys::GValue,
569         handler_return: *const gobject_sys::GValue,
570         data: glib_sys::gpointer,
571     ) -> glib_sys::gboolean {
572         let accumulator: &F = &*(data as *const &F);
573         accumulator(
574             &SignalInvocationHint(*ihint),
575             &mut *(return_accu as *mut Value),
576             &*(handler_return as *const Value),
577         )
578         .to_glib()
579     }
580 
581     gobject_sys::g_signal_newv(
582         name.to_glib_none().0,
583         type_,
584         flags.to_glib(),
585         ptr::null_mut(),
586         Some(accumulator_trampoline::<F>),
587         Box::into_raw(accumulator) as glib_sys::gpointer,
588         None,
589         ret_type.to_glib(),
590         arg_types.len() as u32,
591         arg_types.as_ptr() as *mut _,
592     );
593 }
594 
595 pub struct SignalClassHandlerToken(*mut gobject_sys::GTypeInstance);
596 
597 impl fmt::Debug for SignalClassHandlerToken {
fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>598     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
599         f.debug_tuple("SignalClassHandlerToken")
600             .field(&unsafe { ::Object::from_glib_borrow(self.0 as *mut gobject_sys::GObject) })
601             .finish()
602     }
603 }
604 
add_signal_with_class_handler<F>( type_: glib_sys::GType, name: &str, flags: SignalFlags, arg_types: &[Type], ret_type: Type, class_handler: F, ) where F: Fn(&SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,605 pub(crate) unsafe fn add_signal_with_class_handler<F>(
606     type_: glib_sys::GType,
607     name: &str,
608     flags: SignalFlags,
609     arg_types: &[Type],
610     ret_type: Type,
611     class_handler: F,
612 ) where
613     F: Fn(&SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
614 {
615     let arg_types = arg_types.iter().map(ToGlib::to_glib).collect::<Vec<_>>();
616     let class_handler = Closure::new(move |values| {
617         let instance = gobject_sys::g_value_get_object(values[0].to_glib_none().0);
618         class_handler(&SignalClassHandlerToken(instance as *mut _), values)
619     });
620 
621     gobject_sys::g_signal_newv(
622         name.to_glib_none().0,
623         type_,
624         flags.to_glib(),
625         class_handler.to_glib_none().0,
626         None,
627         ptr::null_mut(),
628         None,
629         ret_type.to_glib(),
630         arg_types.len() as u32,
631         arg_types.as_ptr() as *mut _,
632     );
633 }
634 
add_signal_with_class_handler_and_accumulator<F, G>( type_: glib_sys::GType, name: &str, flags: SignalFlags, arg_types: &[Type], ret_type: Type, class_handler: F, accumulator: G, ) where F: Fn(&SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static, G: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,635 pub(crate) unsafe fn add_signal_with_class_handler_and_accumulator<F, G>(
636     type_: glib_sys::GType,
637     name: &str,
638     flags: SignalFlags,
639     arg_types: &[Type],
640     ret_type: Type,
641     class_handler: F,
642     accumulator: G,
643 ) where
644     F: Fn(&SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
645     G: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
646 {
647     let arg_types = arg_types.iter().map(ToGlib::to_glib).collect::<Vec<_>>();
648 
649     let class_handler = Closure::new(move |values| {
650         let instance = gobject_sys::g_value_get_object(values[0].to_glib_none().0);
651         class_handler(&SignalClassHandlerToken(instance as *mut _), values)
652     });
653     let accumulator: Box<G> = Box::new(accumulator);
654 
655     unsafe extern "C" fn accumulator_trampoline<
656         G: Fn(&SignalInvocationHint, &mut Value, &Value) -> bool + Send + Sync + 'static,
657     >(
658         ihint: *mut gobject_sys::GSignalInvocationHint,
659         return_accu: *mut gobject_sys::GValue,
660         handler_return: *const gobject_sys::GValue,
661         data: glib_sys::gpointer,
662     ) -> glib_sys::gboolean {
663         let accumulator: &G = &*(data as *const &G);
664         accumulator(
665             &SignalInvocationHint(*ihint),
666             &mut *(return_accu as *mut Value),
667             &*(handler_return as *const Value),
668         )
669         .to_glib()
670     }
671 
672     gobject_sys::g_signal_newv(
673         name.to_glib_none().0,
674         type_,
675         flags.to_glib(),
676         class_handler.to_glib_none().0,
677         Some(accumulator_trampoline::<G>),
678         Box::into_raw(accumulator) as glib_sys::gpointer,
679         None,
680         ret_type.to_glib(),
681         arg_types.len() as u32,
682         arg_types.as_ptr() as *mut _,
683     );
684 }
685 
signal_override_class_handler<F>( name: &str, type_: glib_sys::GType, class_handler: F, ) where F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,686 pub(crate) unsafe fn signal_override_class_handler<F>(
687     name: &str,
688     type_: glib_sys::GType,
689     class_handler: F,
690 ) where
691     F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
692 {
693     let class_handler = Closure::new(move |values| {
694         let instance = gobject_sys::g_value_get_object(values[0].to_glib_none().0);
695         class_handler(&SignalClassHandlerToken(instance as *mut _), values)
696     });
697 
698     let mut signal_id = 0;
699     let found: bool = from_glib(gobject_sys::g_signal_parse_name(
700         name.to_glib_none().0,
701         type_,
702         &mut signal_id,
703         ptr::null_mut(),
704         false.to_glib(),
705     ));
706 
707     if !found {
708         panic!("Signal '{}' not found", name);
709     }
710 
711     gobject_sys::g_signal_override_class_closure(signal_id, type_, class_handler.to_glib_none().0);
712 }
713 
signal_chain_from_overridden( instance: *mut gobject_sys::GTypeInstance, token: &SignalClassHandlerToken, values: &[Value], ) -> Option<Value>714 pub(crate) unsafe fn signal_chain_from_overridden(
715     instance: *mut gobject_sys::GTypeInstance,
716     token: &SignalClassHandlerToken,
717     values: &[Value],
718 ) -> Option<Value> {
719     assert_eq!(instance, token.0);
720     let mut result = Value::uninitialized();
721     gobject_sys::g_signal_chain_from_overridden(
722         values.as_ptr() as *mut Value as *mut gobject_sys::GValue,
723         result.to_glib_none_mut().0,
724     );
725     if result.type_() != Type::Unit && result.type_() != Type::Invalid {
726         Some(result)
727     } else {
728         None
729     }
730 }
731