1use std::{any::Any, collections::BTreeMap, marker, mem, ptr};
7
8use super::{SignalId, interface::ObjectInterface};
9use crate::{
10 Closure, InterfaceInfo, Object, Type, TypeFlags, TypeInfo, Value, ffi, gobject_ffi,
11 object::{IsClass, IsInterface, ObjectSubclassIs, ParentClassIs},
12 prelude::*,
13 translate::*,
14};
15
16#[derive(Debug, PartialEq, Eq)]
21pub struct InitializingType<T>(pub(crate) Type, pub(crate) marker::PhantomData<*const T>);
22
23impl<T> IntoGlib for InitializingType<T> {
24 type GlibType = ffi::GType;
25
26 #[inline]
27 fn into_glib(self) -> ffi::GType {
28 self.0.into_glib()
29 }
30}
31
32struct PrivateStruct<T: ObjectSubclass> {
35 imp: T,
36 instance_data: Option<BTreeMap<Type, Box<dyn Any + Send + Sync>>>,
37}
38
39pub unsafe trait InstanceStruct: Sized + 'static {
51 type Type: ObjectSubclass;
54
55 #[inline]
61 fn instance_init(&mut self) {
62 unsafe {
63 let obj = from_glib_borrow::<_, Object>(self as *mut _ as *mut gobject_ffi::GObject);
64 let obj = Borrowed::new(obj.into_inner().unsafe_cast());
65 let mut obj = InitializingObject(obj);
66
67 <<Self::Type as ObjectSubclass>::ParentType as IsSubclassable<Self::Type>>::instance_init(
68 &mut obj,
69 );
70 }
71 }
72}
73
74pub unsafe trait InstanceStructExt: InstanceStruct {
77 #[doc(alias = "get_impl")]
83 fn imp(&self) -> &Self::Type;
84
85 #[doc(alias = "get_class")]
88 fn class(&self) -> &<Self::Type as ObjectSubclass>::Class;
89}
90
91#[inline]
101fn offset_ptr_by_bytes<T, U>(ptr: *const T, offset: isize) -> *const U {
102 let ptr = ptr as usize;
104 let ptr = if offset < 0 {
105 ptr - (-offset) as usize
106 } else {
107 ptr + offset as usize
108 };
109 let ptr = ptr as *const U;
110 debug_assert!(ptr.is_aligned());
111 ptr
112}
113
114#[inline]
124fn offset_ptr_by_bytes_mut<T, U>(ptr: *mut T, offset: isize) -> *mut U {
125 let ptr = ptr as usize;
127 let ptr = if offset < 0 {
128 ptr - (-offset) as usize
129 } else {
130 ptr + offset as usize
131 };
132 let ptr = ptr as *mut U;
133 debug_assert!(ptr.is_aligned());
134 ptr
135}
136
137unsafe impl<T: InstanceStruct> InstanceStructExt for T {
138 #[inline]
139 fn imp(&self) -> &Self::Type {
140 unsafe {
141 let data = Self::Type::type_data();
142 let private_offset = data.as_ref().impl_offset();
143 let imp = offset_ptr_by_bytes::<T, Self::Type>(self, private_offset);
144 &*imp
145 }
146 }
147
148 #[inline]
149 fn class(&self) -> &<Self::Type as ObjectSubclass>::Class {
150 unsafe { &**(self as *const _ as *const *const <Self::Type as ObjectSubclass>::Class) }
151 }
152}
153
154pub trait ObjectSubclassIsExt: ObjectSubclassIs {
157 fn imp(&self) -> &Self::Subclass;
160}
161
162impl<T: ObjectSubclassIs<Subclass = S>, S: ObjectSubclass<Type = Self>> ObjectSubclassIsExt for T {
163 #[inline]
164 fn imp(&self) -> &T::Subclass {
165 T::Subclass::from_obj(self)
166 }
167}
168
169pub unsafe trait ClassStruct: Sized + 'static {
181 type Type: ObjectSubclass;
184
185 #[inline]
190 fn class_init(&mut self) {
191 unsafe {
192 let base = &mut *(self as *mut _
193 as *mut crate::Class<<Self::Type as ObjectSubclass>::ParentType>);
194 <<Self::Type as ObjectSubclass>::ParentType as IsSubclassable<Self::Type>>::class_init(
195 base,
196 );
197 }
198 }
199}
200
201pub unsafe trait IsSubclassable<T: ObjectSubclass>: IsSubclassableDefault<T> {
204 #[inline]
211 fn class_init(class: &mut crate::Class<Self>) {
212 Self::default_class_init(class);
213 }
214
215 #[inline]
221 fn instance_init(instance: &mut InitializingObject<T>) {
222 Self::default_instance_init(instance);
223 }
224}
225
226#[doc(hidden)]
229pub trait IsSubclassableDefault<T: ObjectSubclass>: IsClass {
230 fn default_class_init(class: &mut crate::Class<Self>);
231 fn default_instance_init(instance: &mut InitializingObject<T>);
232}
233
234impl<T: ObjectSubclass, U: IsSubclassable<T> + ParentClassIs> IsSubclassableDefault<T> for U
235where
236 U::Parent: IsSubclassable<T>,
237{
238 #[inline]
239 fn default_class_init(class: &mut crate::Class<Self>) {
240 U::Parent::class_init(class);
241 }
242
243 #[inline]
244 fn default_instance_init(instance: &mut InitializingObject<T>) {
245 U::Parent::instance_init(instance);
246 }
247}
248
249impl<T: ObjectSubclass> IsSubclassableDefault<T> for Object {
250 #[inline]
251 fn default_class_init(_class: &mut crate::Class<Self>) {}
252
253 #[inline]
254 fn default_instance_init(_instance: &mut InitializingObject<T>) {}
255}
256
257pub trait IsSubclassableExt: IsClass + ParentClassIs {
258 fn parent_class_init<T: ObjectSubclass>(class: &mut crate::Class<Self>)
259 where
260 Self::Parent: IsSubclassable<T>;
261 fn parent_instance_init<T: ObjectSubclass>(instance: &mut InitializingObject<T>)
262 where
263 Self::Parent: IsSubclassable<T>;
264}
265
266impl<U: IsClass + ParentClassIs> IsSubclassableExt for U {
267 #[inline]
268 fn parent_class_init<T: ObjectSubclass>(class: &mut crate::Class<Self>)
269 where
270 U::Parent: IsSubclassable<T>,
271 {
272 Self::Parent::class_init(class);
273 }
274
275 #[inline]
276 fn parent_instance_init<T: ObjectSubclass>(instance: &mut InitializingObject<T>)
277 where
278 U::Parent: IsSubclassable<T>,
279 {
280 Self::Parent::instance_init(instance);
281 }
282}
283
284pub unsafe trait InterfaceStruct: Sized + 'static
290where
291 Self: Copy,
292{
293 type Type: ObjectInterface;
296
297 #[inline]
302 fn interface_init(&mut self) {}
303}
304
305pub unsafe trait IsImplementable<T: ObjectSubclass>: IsInterface {
308 fn interface_init(_iface: &mut crate::Interface<Self>) {}
314
315 fn instance_init(_instance: &mut InitializingObject<T>) {}
320}
321
322unsafe extern "C" fn interface_init<T: ObjectSubclass, A: IsImplementable<T>>(
323 iface: ffi::gpointer,
324 _iface_data: ffi::gpointer,
325) where
326 <A as ObjectType>::GlibClassType: Copy,
327{
328 unsafe {
329 let iface = &mut *(iface as *mut crate::Interface<A>);
330
331 let mut data = T::type_data();
332 if data.as_ref().parent_ifaces.is_none() {
333 data.as_mut().parent_ifaces = Some(BTreeMap::default());
334 }
335 {
336 let copy = Box::new(*iface.as_ref());
337 data.as_mut()
338 .parent_ifaces
339 .as_mut()
340 .unwrap()
341 .insert(A::static_type(), Box::into_raw(copy) as ffi::gpointer);
342 }
343
344 A::interface_init(iface);
345 }
346}
347
348pub trait InterfaceList<T: ObjectSubclass> {
351 fn iface_infos() -> Vec<(Type, InterfaceInfo)>;
354
355 fn instance_init(_instance: &mut InitializingObject<T>);
358}
359
360impl<T: ObjectSubclass> InterfaceList<T> for () {
361 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
362 vec![]
363 }
364
365 #[inline]
366 fn instance_init(_instance: &mut InitializingObject<T>) {}
367}
368
369impl<T: ObjectSubclass, A: IsImplementable<T>> InterfaceList<T> for (A,)
370where
371 <A as ObjectType>::GlibClassType: Copy,
372{
373 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
374 vec![(
375 A::static_type(),
376 InterfaceInfo(gobject_ffi::GInterfaceInfo {
377 interface_init: Some(interface_init::<T, A>),
378 ..InterfaceInfo::default().0
379 }),
380 )]
381 }
382
383 #[inline]
384 fn instance_init(instance: &mut InitializingObject<T>) {
385 A::instance_init(instance);
386 }
387}
388
389macro_rules! interface_list_trait(
392 ($name1:ident, $name2: ident, $($name:ident),*) => (
393 interface_list_trait!(__impl $name1, $name2; $($name),*);
394 );
395 (__impl $($name:ident),+; $name1:ident, $($name2:ident),*) => (
396 interface_list_trait_impl!($($name),+);
397 interface_list_trait!(__impl $($name),+ , $name1; $($name2),*);
398 );
399 (__impl $($name:ident),+; $name1:ident) => (
400 interface_list_trait_impl!($($name),+);
401 interface_list_trait_impl!($($name),+, $name1);
402 );
403);
404
405macro_rules! interface_list_trait_impl(
409 ($($name:ident),+) => (
410 impl<T: ObjectSubclass, $($name: IsImplementable<T>),+> InterfaceList<T> for ( $($name),+ )
411 where
412 $(<$name as ObjectType>::GlibClassType: Copy),+
413 {
414 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
415 vec![
416 $(
417 (
418 $name::static_type(),
419 InterfaceInfo(gobject_ffi::GInterfaceInfo {
420 interface_init: Some(interface_init::<T, $name>),
421 interface_finalize: None,
422 interface_data: ptr::null_mut(),
423 }),
424 )
425 ),+
426 ]
427 }
428
429 #[inline]
430 fn instance_init(instance: &mut InitializingObject<T>) {
431 $(
432 $name::instance_init(instance);
433 )+
434 }
435 }
436 );
437);
438
439interface_list_trait!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
440
441pub struct TypeData {
443 type_: Type,
444 parent_class: ffi::gpointer,
445 parent_ifaces: Option<BTreeMap<Type, ffi::gpointer>>,
446 class_data: Option<BTreeMap<Type, Box<dyn Any + Send + Sync>>>,
447 private_offset: isize,
448 private_imp_offset: isize,
449}
450
451unsafe impl Send for TypeData {}
452unsafe impl Sync for TypeData {}
453
454impl TypeData {
455 pub const fn new() -> Self {
456 Self {
457 type_: Type::INVALID,
458 parent_class: ::std::ptr::null_mut(),
459 parent_ifaces: None,
460 class_data: None,
461 private_offset: 0,
462 private_imp_offset: 0,
463 }
464 }
465
466 #[inline]
469 #[doc(alias = "get_type")]
470 pub fn type_(&self) -> Type {
471 self.type_
472 }
473
474 #[doc(alias = "get_parent_class")]
480 #[inline]
481 pub fn parent_class(&self) -> ffi::gpointer {
482 debug_assert!(!self.parent_class.is_null());
483 self.parent_class
484 }
485
486 #[doc(alias = "get_parent_interface")]
497 pub fn parent_interface<I: crate::object::IsInterface>(&self) -> ffi::gpointer {
498 match self.parent_ifaces {
499 None => unreachable!("No parent interfaces"),
500 Some(ref parent_ifaces) => *parent_ifaces
501 .get(&I::static_type())
502 .expect("Parent interface not found"),
503 }
504 }
505
506 #[doc(alias = "get_class_data")]
511 pub fn class_data<T: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&T> {
512 match self.class_data {
513 None => None,
514 Some(ref data) => data.get(&type_).and_then(|ptr| ptr.downcast_ref()),
515 }
516 }
517
518 #[doc(alias = "get_class_data_mut")]
525 pub unsafe fn class_data_mut<T: Any + Send + Sync + 'static>(
526 &mut self,
527 type_: Type,
528 ) -> Option<&mut T> {
529 match self.class_data {
530 None => None,
531 Some(ref mut data) => data.get_mut(&type_).and_then(|v| v.downcast_mut()),
532 }
533 }
534
535 pub unsafe fn set_class_data<T: Any + Send + Sync + 'static>(&mut self, type_: Type, data: T) {
546 if self.class_data.is_none() {
547 self.class_data = Some(BTreeMap::default());
548 }
549
550 if let Some(ref mut class_data) = self.class_data {
551 assert!(
552 class_data.get(&type_).is_none(),
553 "The class_data already contains a key for {type_}",
554 );
555
556 class_data.insert(type_, Box::new(data));
557 }
558 }
559
560 #[doc(alias = "get_impl_offset")]
564 #[inline]
565 pub fn impl_offset(&self) -> isize {
566 self.private_offset + self.private_imp_offset
567 }
568}
569
570impl Default for TypeData {
571 fn default() -> Self {
572 Self::new()
573 }
574}
575
576pub unsafe trait ObjectSubclassType {
581 fn type_data() -> ptr::NonNull<TypeData>;
584
585 #[doc(alias = "get_type")]
590 fn type_() -> Type;
591}
592
593pub trait ObjectSubclass: ObjectSubclassType + Sized + 'static {
605 const NAME: &'static str;
610
611 const ABSTRACT: bool = false;
621
622 const ALLOW_NAME_CONFLICT: bool = false;
639
640 type Type: ObjectType
643 + ObjectSubclassIs<Subclass = Self>
644 + FromGlibPtrFull<*mut <Self::Type as ObjectType>::GlibType>
645 + FromGlibPtrBorrow<*mut <Self::Type as ObjectType>::GlibType>
646 + FromGlibPtrNone<*mut <Self::Type as ObjectType>::GlibType>;
647
648 type ParentType: IsSubclassable<Self>
651 + FromGlibPtrFull<*mut <Self::ParentType as ObjectType>::GlibType>
652 + FromGlibPtrBorrow<*mut <Self::ParentType as ObjectType>::GlibType>
653 + FromGlibPtrNone<*mut <Self::ParentType as ObjectType>::GlibType>;
654
655 type Interfaces: InterfaceList<Self>;
658
659 type Instance: InstanceStruct<Type = Self>;
669
670 type Class: ClassStruct<Type = Self>;
680
681 #[inline]
690 fn type_init(_type_: &mut InitializingType<Self>) {}
691
692 #[inline]
702 fn class_init(_klass: &mut Self::Class) {}
703
704 fn new() -> Self {
713 unimplemented!();
714 }
715
716 #[inline]
728 fn with_class(_klass: &Self::Class) -> Self {
729 Self::new()
730 }
731
732 #[inline]
738 fn instance_init(_obj: &InitializingObject<Self>) {}
739}
740
741pub trait ObjectSubclassExt: ObjectSubclass {
744 #[doc(alias = "get_instance")]
749 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type>;
750
751 fn from_obj(obj: &Self::Type) -> &Self;
756
757 fn ref_counted(&self) -> super::ObjectImplRef<Self>;
760
761 #[doc(alias = "get_instance_data")]
766 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U>;
767}
768
769impl<T: ObjectSubclass> ObjectSubclassExt for T {
770 #[inline]
771 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type> {
772 unsafe {
773 let data = Self::type_data();
774 let type_ = data.as_ref().type_();
775 debug_assert!(type_.is_valid());
776
777 let offset = -data.as_ref().impl_offset();
778 let ptr =
779 offset_ptr_by_bytes::<Self, <Self::Type as ObjectType>::GlibType>(self, offset);
780
781 debug_assert_ne!((*(ptr as *const gobject_ffi::GObject)).ref_count, 0);
785
786 crate::BorrowedObject::new(mut_override(ptr))
787 }
788 }
789
790 #[inline]
791 fn from_obj(obj: &Self::Type) -> &Self {
792 unsafe {
793 let ptr = obj.as_ptr() as *const Self::Instance;
794 (*ptr).imp()
795 }
796 }
797
798 #[inline]
799 fn ref_counted(&self) -> super::ObjectImplRef<Self> {
800 super::ObjectImplRef::new(self)
801 }
802
803 #[inline]
804 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U> {
805 unsafe {
806 let type_data = Self::type_data();
807 let self_type_ = type_data.as_ref().type_();
808 debug_assert!(self_type_.is_valid());
809
810 let offset = -type_data.as_ref().private_imp_offset;
811 let ptr = offset_ptr_by_bytes::<Self, PrivateStruct<Self>>(self, offset);
812 let priv_ = &*ptr;
813
814 match priv_.instance_data {
815 None => None,
816 Some(ref data) => data.get(&type_).and_then(|ptr| ptr.downcast_ref()),
817 }
818 }
819 }
820}
821
822pub trait FromObject {
825 type FromObjectType;
826 fn from_object(obj: &Self::FromObjectType) -> &Self;
827}
828
829pub struct InitializingObject<T: ObjectSubclass>(Borrowed<T::Type>);
835
836impl<T: ObjectSubclass> InitializingObject<T> {
837 #[inline]
846 pub unsafe fn as_ref(&self) -> &T::Type {
847 &self.0
848 }
849
850 #[inline]
859 pub fn as_ptr(&self) -> *mut T::Type {
860 self.0.as_ptr() as *const T::Type as *mut T::Type
861 }
862
863 pub fn set_instance_data<U: Any + Send + Sync + 'static>(&mut self, type_: Type, data: U) {
870 unsafe {
871 let type_data = T::type_data();
872 let self_type_ = type_data.as_ref().type_();
873 debug_assert!(self_type_.is_valid());
874
875 let offset = type_data.as_ref().private_offset;
876
877 let ptr = offset_ptr_by_bytes_mut::<
878 <<T as ObjectSubclass>::Type as ObjectType>::GlibType,
879 PrivateStruct<T>,
880 >(self.0.as_ptr(), offset);
881 let priv_ = &mut *ptr;
882
883 if priv_.instance_data.is_none() {
884 priv_.instance_data = Some(BTreeMap::default());
885 }
886
887 if let Some(ref mut instance_data) = priv_.instance_data {
888 assert!(
889 instance_data.get(&type_).is_none(),
890 "The class_data already contains a key for {type_}",
891 );
892
893 instance_data.insert(type_, Box::new(data));
894 }
895 }
896 }
897}
898
899unsafe extern "C" fn class_init<T: ObjectSubclass>(
900 klass: ffi::gpointer,
901 _klass_data: ffi::gpointer,
902) {
903 unsafe {
904 let mut data = T::type_data();
905
906 let mut private_offset = data.as_ref().private_offset as i32;
909 gobject_ffi::g_type_class_adjust_private_offset(klass, &mut private_offset);
910 data.as_mut().private_offset = private_offset as isize;
911
912 {
914 let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
915
916 gobject_klass.finalize = Some(finalize::<T>);
917 }
918
919 {
923 let klass = &mut *(klass as *mut T::Class);
924 let parent_class =
925 gobject_ffi::g_type_class_peek_parent(klass as *mut _ as ffi::gpointer)
926 as *mut <T::ParentType as ObjectType>::GlibClassType;
927 debug_assert!(!parent_class.is_null());
928
929 data.as_mut().parent_class = parent_class as ffi::gpointer;
930
931 klass.class_init();
932 T::class_init(klass);
933 }
934 }
935}
936
937unsafe extern "C" fn instance_init<T: ObjectSubclass>(
938 obj: *mut gobject_ffi::GTypeInstance,
939 klass: ffi::gpointer,
940) {
941 unsafe {
942 let mut data = T::type_data();
945 let private_offset = data.as_mut().private_offset;
946 let priv_ptr = offset_ptr_by_bytes_mut::<gobject_ffi::GTypeInstance, PrivateStruct<T>>(
947 obj,
948 private_offset,
949 );
950
951 assert!(
952 (priv_ptr as *const PrivateStruct<T>).is_aligned(),
953 "Private instance data has higher alignment requirements ({}) than \
954 the allocation from GLib. If alignment of more than {} bytes \
955 is required, store the corresponding data separately on the heap.",
956 mem::align_of::<PrivateStruct<T>>(),
957 2 * mem::size_of::<usize>(),
958 );
959
960 let klass = &*(klass as *const T::Class);
961
962 let imp = T::with_class(klass);
963 ptr::write(
964 priv_ptr,
965 PrivateStruct {
966 imp,
967 instance_data: None,
968 },
969 );
970
971 T::Instance::instance_init(&mut *(obj as *mut _));
973
974 let obj = from_glib_borrow::<_, Object>(obj.cast());
975 let obj = Borrowed::new(obj.into_inner().unsafe_cast());
976 let mut obj = InitializingObject(obj);
977
978 T::Interfaces::instance_init(&mut obj);
979 T::instance_init(&obj);
980 }
981}
982
983unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
984 unsafe {
985 let mut data = T::type_data();
987 let private_offset = data.as_mut().private_offset;
988 let priv_ptr =
989 offset_ptr_by_bytes_mut::<gobject_ffi::GObject, PrivateStruct<T>>(obj, private_offset);
990 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).imp));
991 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).instance_data));
992
993 let parent_class = &*(data.as_ref().parent_class() as *const gobject_ffi::GObjectClass);
995 if let Some(ref func) = parent_class.finalize {
996 func(obj);
997 }
998 }
999}
1000
1001pub fn register_type<T: ObjectSubclass>() -> Type {
1011 assert!(
1014 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1015 "Alignment {} of type not supported, bigger than {}",
1016 mem::align_of::<T>(),
1017 2 * mem::size_of::<usize>(),
1018 );
1019
1020 unsafe {
1021 use std::ffi::CString;
1022
1023 let type_name = if T::ALLOW_NAME_CONFLICT {
1024 let mut i = 0;
1025 loop {
1026 let type_name = CString::new(if i == 0 {
1027 T::NAME.to_string()
1028 } else {
1029 format!("{}-{}", T::NAME, i)
1030 })
1031 .unwrap();
1032 if gobject_ffi::g_type_from_name(type_name.as_ptr()) == gobject_ffi::G_TYPE_INVALID
1033 {
1034 break type_name;
1035 }
1036 i += 1;
1037 }
1038 } else {
1039 let type_name = CString::new(T::NAME).unwrap();
1040 assert_eq!(
1041 gobject_ffi::g_type_from_name(type_name.as_ptr()),
1042 gobject_ffi::G_TYPE_INVALID,
1043 "Type {} has already been registered",
1044 type_name.to_str().unwrap()
1045 );
1046
1047 type_name
1048 };
1049
1050 let type_ = Type::from_glib(gobject_ffi::g_type_register_static_simple(
1051 <T::ParentType as StaticType>::static_type().into_glib(),
1052 type_name.as_ptr(),
1053 mem::size_of::<T::Class>() as u32,
1054 Some(class_init::<T>),
1055 mem::size_of::<T::Instance>() as u32,
1056 Some(instance_init::<T>),
1057 if T::ABSTRACT {
1058 gobject_ffi::G_TYPE_FLAG_ABSTRACT
1059 } else {
1060 0
1061 },
1062 ));
1063 assert!(type_.is_valid());
1064
1065 let mut data = T::type_data();
1066 data.as_mut().type_ = type_;
1067
1068 let private_offset = gobject_ffi::g_type_add_instance_private(
1069 type_.into_glib(),
1070 mem::size_of::<PrivateStruct<T>>(),
1071 );
1072 data.as_mut().private_offset = private_offset as isize;
1073
1074 data.as_mut().private_imp_offset = {
1077 let priv_ = mem::MaybeUninit::<PrivateStruct<T>>::uninit();
1079 let ptr = priv_.as_ptr();
1080 let imp_ptr = ptr::addr_of!((*ptr).imp);
1081 (imp_ptr as isize) - (ptr as isize)
1082 };
1083
1084 let iface_types = T::Interfaces::iface_infos();
1085 for (iface_type, iface_info) in iface_types {
1086 gobject_ffi::g_type_add_interface_static(
1087 type_.into_glib(),
1088 iface_type.into_glib(),
1089 iface_info.as_ptr(),
1090 );
1091 }
1092
1093 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1094
1095 type_
1096 }
1097}
1098
1099pub fn register_dynamic_type<P: DynamicObjectRegisterExt, T: ObjectSubclass>(
1116 type_plugin: &P,
1117) -> Type {
1118 assert!(
1121 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1122 "Alignment {} of type not supported, bigger than {}",
1123 mem::align_of::<T>(),
1124 2 * mem::size_of::<usize>(),
1125 );
1126
1127 unsafe {
1128 use std::ffi::CString;
1129
1130 let type_name = CString::new(T::NAME).unwrap();
1131
1132 let already_registered =
1133 gobject_ffi::g_type_from_name(type_name.as_ptr()) != gobject_ffi::G_TYPE_INVALID;
1134
1135 let type_info = TypeInfo(gobject_ffi::GTypeInfo {
1136 class_size: mem::size_of::<T::Class>() as u16,
1137 class_init: Some(class_init::<T>),
1138 instance_size: mem::size_of::<T::Instance>() as u16,
1139 instance_init: Some(instance_init::<T>),
1140 ..TypeInfo::default().0
1141 });
1142
1143 let type_ = type_plugin.register_dynamic_type(
1145 <T::ParentType as StaticType>::static_type(),
1146 type_name.to_str().unwrap(),
1147 &type_info,
1148 if T::ABSTRACT {
1149 TypeFlags::ABSTRACT
1150 } else {
1151 TypeFlags::NONE
1152 },
1153 );
1154 assert!(type_.is_valid());
1155
1156 let mut data = T::type_data();
1157 data.as_mut().type_ = type_;
1158
1159 let private_offset = mem::size_of::<PrivateStruct<T>>();
1160 data.as_mut().private_offset = private_offset as isize;
1161
1162 data.as_mut().private_imp_offset = {
1165 let priv_ = mem::MaybeUninit::<PrivateStruct<T>>::uninit();
1167 let ptr = priv_.as_ptr();
1168 let imp_ptr = ptr::addr_of!((*ptr).imp);
1169 (imp_ptr as isize) - (ptr as isize)
1170 };
1171
1172 let plugin_ptr = type_plugin.as_ref().to_glib_none().0;
1173 let iface_types = T::Interfaces::iface_infos();
1174 for (iface_type, iface_info) in iface_types {
1175 match gobject_ffi::g_type_get_plugin(iface_type.into_glib()) {
1176 iface_plugin if iface_plugin != plugin_ptr => {
1179 if !already_registered {
1181 gobject_ffi::g_type_add_interface_static(
1182 type_.into_glib(),
1183 iface_type.into_glib(),
1184 iface_info.as_ptr(),
1185 );
1186 }
1187 }
1188 _ => type_plugin.add_dynamic_interface(type_, iface_type, &iface_info),
1190 }
1191 }
1192
1193 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1194
1195 type_
1196 }
1197}
1198
1199pub(crate) unsafe fn signal_override_class_handler<F>(
1200 name: &str,
1201 type_: ffi::GType,
1202 class_handler: F,
1203) where
1204 F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
1205{
1206 unsafe {
1207 let (signal_id, _) = SignalId::parse_name(name, from_glib(type_), false)
1208 .unwrap_or_else(|| panic!("Signal '{name}' not found"));
1209
1210 let query = signal_id.query();
1211 let return_type = query.return_type();
1212
1213 let class_handler = Closure::new(move |values| {
1214 let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
1215 let res = class_handler(
1216 &super::SignalClassHandlerToken(
1217 instance as *mut _,
1218 return_type.into(),
1219 values.as_ptr(),
1220 ),
1221 values,
1222 );
1223
1224 if return_type == Type::UNIT {
1225 if let Some(ref v) = res {
1226 panic!(
1227 "Signal has no return value but class handler returned a value of type {}",
1228 v.type_()
1229 );
1230 }
1231 } else {
1232 match res {
1233 None => {
1234 panic!("Signal has a return value but class handler returned none");
1235 }
1236 Some(ref v) => {
1237 assert!(
1238 v.type_().is_a(return_type.into()),
1239 "Signal has a return type of {} but class handler returned {}",
1240 Type::from(return_type),
1241 v.type_()
1242 );
1243 }
1244 }
1245 }
1246
1247 res
1248 });
1249
1250 gobject_ffi::g_signal_override_class_closure(
1251 signal_id.into_glib(),
1252 type_,
1253 class_handler.to_glib_none().0,
1254 );
1255 }
1256}
1257
1258pub(crate) unsafe fn signal_chain_from_overridden(
1259 instance: *mut gobject_ffi::GTypeInstance,
1260 token: &super::SignalClassHandlerToken,
1261 values: &[Value],
1262) -> Option<Value> {
1263 unsafe {
1264 assert_eq!(instance, token.0);
1265 assert_eq!(
1266 values.as_ptr(),
1267 token.2,
1268 "Arguments must be forwarded without changes when chaining up"
1269 );
1270
1271 let mut result = Value::from_type_unchecked(token.1);
1272 gobject_ffi::g_signal_chain_from_overridden(
1273 values.as_ptr() as *mut Value as *mut gobject_ffi::GValue,
1274 result.to_glib_none_mut().0,
1275 );
1276 Some(result).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
1277 }
1278}