1use std::{any::Any, collections::BTreeMap, marker, mem, ptr};
7
8use super::{interface::ObjectInterface, SignalId};
9use crate::{
10 ffi, gobject_ffi,
11 object::{IsClass, IsInterface, ObjectSubclassIs, ParentClassIs},
12 prelude::*,
13 translate::*,
14 Closure, InterfaceInfo, Object, Type, TypeFlags, TypeInfo, Value,
15};
16
17#[derive(Debug, PartialEq, Eq)]
22pub struct InitializingType<T>(pub(crate) Type, pub(crate) marker::PhantomData<*const T>);
23
24impl<T> IntoGlib for InitializingType<T> {
25 type GlibType = ffi::GType;
26
27 #[inline]
28 fn into_glib(self) -> ffi::GType {
29 self.0.into_glib()
30 }
31}
32
33struct PrivateStruct<T: ObjectSubclass> {
36 imp: T,
37 instance_data: Option<BTreeMap<Type, Box<dyn Any + Send + Sync>>>,
38}
39
40pub unsafe trait InstanceStruct: Sized + 'static {
52 type Type: ObjectSubclass;
55
56 #[inline]
62 fn instance_init(&mut self) {
63 unsafe {
64 let obj = from_glib_borrow::<_, Object>(self as *mut _ as *mut gobject_ffi::GObject);
65 let obj = Borrowed::new(obj.into_inner().unsafe_cast());
66 let mut obj = InitializingObject(obj);
67
68 <<Self::Type as ObjectSubclass>::ParentType as IsSubclassable<Self::Type>>::instance_init(
69 &mut obj,
70 );
71 }
72 }
73}
74
75pub unsafe trait InstanceStructExt: InstanceStruct {
78 #[doc(alias = "get_impl")]
84 fn imp(&self) -> &Self::Type;
85
86 #[doc(alias = "get_class")]
89 fn class(&self) -> &<Self::Type as ObjectSubclass>::Class;
90}
91
92#[inline]
102fn offset_ptr_by_bytes<T, U>(ptr: *const T, offset: isize) -> *const U {
103 let ptr = ptr as usize;
105 let ptr = if offset < 0 {
106 ptr - (-offset) as usize
107 } else {
108 ptr + offset as usize
109 };
110 debug_assert_eq!(ptr & (mem::align_of::<U>() - 1), 0);
111 ptr as *const U
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 debug_assert_eq!(ptr & (mem::align_of::<U>() - 1), 0);
133 ptr as *mut U
134}
135
136unsafe impl<T: InstanceStruct> InstanceStructExt for T {
137 #[inline]
138 fn imp(&self) -> &Self::Type {
139 unsafe {
140 let data = Self::Type::type_data();
141 let private_offset = data.as_ref().impl_offset();
142 let imp = offset_ptr_by_bytes::<T, Self::Type>(self, private_offset);
143 &*imp
144 }
145 }
146
147 #[inline]
148 fn class(&self) -> &<Self::Type as ObjectSubclass>::Class {
149 unsafe { &**(self as *const _ as *const *const <Self::Type as ObjectSubclass>::Class) }
150 }
151}
152
153pub trait ObjectSubclassIsExt: ObjectSubclassIs {
156 fn imp(&self) -> &Self::Subclass;
159}
160
161impl<T: ObjectSubclassIs<Subclass = S>, S: ObjectSubclass<Type = Self>> ObjectSubclassIsExt for T {
162 #[inline]
163 fn imp(&self) -> &T::Subclass {
164 T::Subclass::from_obj(self)
165 }
166}
167
168pub unsafe trait ClassStruct: Sized + 'static {
180 type Type: ObjectSubclass;
183
184 #[inline]
189 fn class_init(&mut self) {
190 unsafe {
191 let base = &mut *(self as *mut _
192 as *mut crate::Class<<Self::Type as ObjectSubclass>::ParentType>);
193 <<Self::Type as ObjectSubclass>::ParentType as IsSubclassable<Self::Type>>::class_init(
194 base,
195 );
196 }
197 }
198}
199
200pub unsafe trait IsSubclassable<T: ObjectSubclass>: IsSubclassableDefault<T> {
203 #[inline]
210 fn class_init(class: &mut crate::Class<Self>) {
211 Self::default_class_init(class);
212 }
213
214 #[inline]
220 fn instance_init(instance: &mut InitializingObject<T>) {
221 Self::default_instance_init(instance);
222 }
223}
224
225#[doc(hidden)]
228pub trait IsSubclassableDefault<T: ObjectSubclass>: IsClass {
229 fn default_class_init(class: &mut crate::Class<Self>);
230 fn default_instance_init(instance: &mut InitializingObject<T>);
231}
232
233impl<T: ObjectSubclass, U: IsSubclassable<T> + ParentClassIs> IsSubclassableDefault<T> for U
234where
235 U::Parent: IsSubclassable<T>,
236{
237 #[inline]
238 fn default_class_init(class: &mut crate::Class<Self>) {
239 U::Parent::class_init(class);
240 }
241
242 #[inline]
243 fn default_instance_init(instance: &mut InitializingObject<T>) {
244 U::Parent::instance_init(instance);
245 }
246}
247
248impl<T: ObjectSubclass> IsSubclassableDefault<T> for Object {
249 #[inline]
250 fn default_class_init(_class: &mut crate::Class<Self>) {}
251
252 #[inline]
253 fn default_instance_init(_instance: &mut InitializingObject<T>) {}
254}
255
256pub trait IsSubclassableExt: IsClass + ParentClassIs {
257 fn parent_class_init<T: ObjectSubclass>(class: &mut crate::Class<Self>)
258 where
259 Self::Parent: IsSubclassable<T>;
260 fn parent_instance_init<T: ObjectSubclass>(instance: &mut InitializingObject<T>)
261 where
262 Self::Parent: IsSubclassable<T>;
263}
264
265impl<U: IsClass + ParentClassIs> IsSubclassableExt for U {
266 #[inline]
267 fn parent_class_init<T: ObjectSubclass>(class: &mut crate::Class<Self>)
268 where
269 U::Parent: IsSubclassable<T>,
270 {
271 Self::Parent::class_init(class);
272 }
273
274 #[inline]
275 fn parent_instance_init<T: ObjectSubclass>(instance: &mut InitializingObject<T>)
276 where
277 U::Parent: IsSubclassable<T>,
278 {
279 Self::Parent::instance_init(instance);
280 }
281}
282
283pub unsafe trait InterfaceStruct: Sized + 'static
289where
290 Self: Copy,
291{
292 type Type: ObjectInterface;
295
296 #[inline]
301 fn interface_init(&mut self) {}
302}
303
304pub unsafe trait IsImplementable<T: ObjectSubclass>: IsInterface {
307 fn interface_init(_iface: &mut crate::Interface<Self>) {}
313
314 fn instance_init(_instance: &mut InitializingObject<T>) {}
319}
320
321unsafe extern "C" fn interface_init<T: ObjectSubclass, A: IsImplementable<T>>(
322 iface: ffi::gpointer,
323 _iface_data: ffi::gpointer,
324) where
325 <A as ObjectType>::GlibClassType: Copy,
326{
327 let iface = &mut *(iface as *mut crate::Interface<A>);
328
329 let mut data = T::type_data();
330 if data.as_ref().parent_ifaces.is_none() {
331 data.as_mut().parent_ifaces = Some(BTreeMap::default());
332 }
333 {
334 let copy = Box::new(*iface.as_ref());
335 data.as_mut()
336 .parent_ifaces
337 .as_mut()
338 .unwrap()
339 .insert(A::static_type(), Box::into_raw(copy) as ffi::gpointer);
340 }
341
342 A::interface_init(iface);
343}
344
345pub trait InterfaceList<T: ObjectSubclass> {
348 fn iface_infos() -> Vec<(Type, InterfaceInfo)>;
351
352 fn instance_init(_instance: &mut InitializingObject<T>);
355}
356
357impl<T: ObjectSubclass> InterfaceList<T> for () {
358 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
359 vec![]
360 }
361
362 #[inline]
363 fn instance_init(_instance: &mut InitializingObject<T>) {}
364}
365
366impl<T: ObjectSubclass, A: IsImplementable<T>> InterfaceList<T> for (A,)
367where
368 <A as ObjectType>::GlibClassType: Copy,
369{
370 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
371 vec![(
372 A::static_type(),
373 InterfaceInfo(gobject_ffi::GInterfaceInfo {
374 interface_init: Some(interface_init::<T, A>),
375 ..InterfaceInfo::default().0
376 }),
377 )]
378 }
379
380 #[inline]
381 fn instance_init(instance: &mut InitializingObject<T>) {
382 A::instance_init(instance);
383 }
384}
385
386macro_rules! interface_list_trait(
389 ($name1:ident, $name2: ident, $($name:ident),*) => (
390 interface_list_trait!(__impl $name1, $name2; $($name),*);
391 );
392 (__impl $($name:ident),+; $name1:ident, $($name2:ident),*) => (
393 interface_list_trait_impl!($($name),+);
394 interface_list_trait!(__impl $($name),+ , $name1; $($name2),*);
395 );
396 (__impl $($name:ident),+; $name1:ident) => (
397 interface_list_trait_impl!($($name),+);
398 interface_list_trait_impl!($($name),+, $name1);
399 );
400);
401
402macro_rules! interface_list_trait_impl(
406 ($($name:ident),+) => (
407 impl<T: ObjectSubclass, $($name: IsImplementable<T>),+> InterfaceList<T> for ( $($name),+ )
408 where
409 $(<$name as ObjectType>::GlibClassType: Copy),+
410 {
411 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
412 vec![
413 $(
414 (
415 $name::static_type(),
416 InterfaceInfo(gobject_ffi::GInterfaceInfo {
417 interface_init: Some(interface_init::<T, $name>),
418 interface_finalize: None,
419 interface_data: ptr::null_mut(),
420 }),
421 )
422 ),+
423 ]
424 }
425
426 #[inline]
427 fn instance_init(instance: &mut InitializingObject<T>) {
428 $(
429 $name::instance_init(instance);
430 )+
431 }
432 }
433 );
434);
435
436interface_list_trait!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
437
438pub struct TypeData {
440 type_: Type,
441 parent_class: ffi::gpointer,
442 parent_ifaces: Option<BTreeMap<Type, ffi::gpointer>>,
443 class_data: Option<BTreeMap<Type, Box<dyn Any + Send + Sync>>>,
444 private_offset: isize,
445 private_imp_offset: isize,
446}
447
448unsafe impl Send for TypeData {}
449unsafe impl Sync for TypeData {}
450
451impl TypeData {
452 pub const fn new() -> Self {
453 Self {
454 type_: Type::INVALID,
455 parent_class: ::std::ptr::null_mut(),
456 parent_ifaces: None,
457 class_data: None,
458 private_offset: 0,
459 private_imp_offset: 0,
460 }
461 }
462
463 #[inline]
466 #[doc(alias = "get_type")]
467 pub fn type_(&self) -> Type {
468 self.type_
469 }
470
471 #[doc(alias = "get_parent_class")]
477 #[inline]
478 pub fn parent_class(&self) -> ffi::gpointer {
479 debug_assert!(!self.parent_class.is_null());
480 self.parent_class
481 }
482
483 #[doc(alias = "get_parent_interface")]
494 pub fn parent_interface<I: crate::object::IsInterface>(&self) -> ffi::gpointer {
495 match self.parent_ifaces {
496 None => unreachable!("No parent interfaces"),
497 Some(ref parent_ifaces) => *parent_ifaces
498 .get(&I::static_type())
499 .expect("Parent interface not found"),
500 }
501 }
502
503 #[doc(alias = "get_class_data")]
508 pub fn class_data<T: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&T> {
509 match self.class_data {
510 None => None,
511 Some(ref data) => data.get(&type_).and_then(|ptr| ptr.downcast_ref()),
512 }
513 }
514
515 #[doc(alias = "get_class_data_mut")]
522 pub unsafe fn class_data_mut<T: Any + Send + Sync + 'static>(
523 &mut self,
524 type_: Type,
525 ) -> Option<&mut T> {
526 match self.class_data {
527 None => None,
528 Some(ref mut data) => data.get_mut(&type_).and_then(|v| v.downcast_mut()),
529 }
530 }
531
532 pub unsafe fn set_class_data<T: Any + Send + Sync + 'static>(&mut self, type_: Type, data: T) {
543 if self.class_data.is_none() {
544 self.class_data = Some(BTreeMap::default());
545 }
546
547 if let Some(ref mut class_data) = self.class_data {
548 assert!(
549 class_data.get(&type_).is_none(),
550 "The class_data already contains a key for {type_}",
551 );
552
553 class_data.insert(type_, Box::new(data));
554 }
555 }
556
557 #[doc(alias = "get_impl_offset")]
561 #[inline]
562 pub fn impl_offset(&self) -> isize {
563 self.private_offset + self.private_imp_offset
564 }
565}
566
567impl Default for TypeData {
568 fn default() -> Self {
569 Self::new()
570 }
571}
572
573pub unsafe trait ObjectSubclassType {
578 fn type_data() -> ptr::NonNull<TypeData>;
581
582 #[doc(alias = "get_type")]
587 fn type_() -> Type;
588}
589
590pub trait ObjectSubclass: ObjectSubclassType + Sized + 'static {
602 const NAME: &'static str;
607
608 const ABSTRACT: bool = false;
618
619 const ALLOW_NAME_CONFLICT: bool = false;
636
637 type Type: ObjectType
640 + ObjectSubclassIs<Subclass = Self>
641 + FromGlibPtrFull<*mut <Self::Type as ObjectType>::GlibType>
642 + FromGlibPtrBorrow<*mut <Self::Type as ObjectType>::GlibType>
643 + FromGlibPtrNone<*mut <Self::Type as ObjectType>::GlibType>;
644
645 type ParentType: IsSubclassable<Self>
648 + FromGlibPtrFull<*mut <Self::ParentType as ObjectType>::GlibType>
649 + FromGlibPtrBorrow<*mut <Self::ParentType as ObjectType>::GlibType>
650 + FromGlibPtrNone<*mut <Self::ParentType as ObjectType>::GlibType>;
651
652 type Interfaces: InterfaceList<Self>;
655
656 type Instance: InstanceStruct<Type = Self>;
666
667 type Class: ClassStruct<Type = Self>;
677
678 #[inline]
687 fn type_init(_type_: &mut InitializingType<Self>) {}
688
689 #[inline]
699 fn class_init(_klass: &mut Self::Class) {}
700
701 fn new() -> Self {
710 unimplemented!();
711 }
712
713 #[inline]
725 fn with_class(_klass: &Self::Class) -> Self {
726 Self::new()
727 }
728
729 #[inline]
735 fn instance_init(_obj: &InitializingObject<Self>) {}
736}
737
738pub trait ObjectSubclassExt: ObjectSubclass {
741 #[doc(alias = "get_instance")]
744 #[deprecated = "Use obj() instead"]
745 fn instance(&self) -> crate::BorrowedObject<Self::Type>;
746
747 #[deprecated = "Use from_obj() instead"]
750 fn from_instance(obj: &Self::Type) -> &Self;
751
752 #[doc(alias = "get_instance")]
757 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type>;
758
759 fn from_obj(obj: &Self::Type) -> &Self;
764
765 fn ref_counted(&self) -> super::ObjectImplRef<Self>;
768
769 #[doc(alias = "get_instance_data")]
774 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U>;
775}
776
777impl<T: ObjectSubclass> ObjectSubclassExt for T {
778 #[inline]
779 fn instance(&self) -> crate::BorrowedObject<Self::Type> {
780 self.obj()
781 }
782
783 #[inline]
784 fn from_instance(obj: &Self::Type) -> &Self {
785 Self::from_obj(obj)
786 }
787
788 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type> {
789 unsafe {
790 let data = Self::type_data();
791 let type_ = data.as_ref().type_();
792 debug_assert!(type_.is_valid());
793
794 let offset = -data.as_ref().impl_offset();
795 let ptr =
796 offset_ptr_by_bytes::<Self, <Self::Type as ObjectType>::GlibType>(self, offset);
797
798 debug_assert_ne!((*(ptr as *const gobject_ffi::GObject)).ref_count, 0);
802
803 crate::BorrowedObject::new(mut_override(ptr))
804 }
805 }
806
807 #[inline]
808 fn from_obj(obj: &Self::Type) -> &Self {
809 unsafe {
810 let ptr = obj.as_ptr() as *const Self::Instance;
811 (*ptr).imp()
812 }
813 }
814
815 #[inline]
816 fn ref_counted(&self) -> super::ObjectImplRef<Self> {
817 super::ObjectImplRef::new(self)
818 }
819
820 #[inline]
821 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U> {
822 unsafe {
823 let type_data = Self::type_data();
824 let self_type_ = type_data.as_ref().type_();
825 debug_assert!(self_type_.is_valid());
826
827 let offset = -type_data.as_ref().private_imp_offset;
828 let ptr = offset_ptr_by_bytes::<Self, PrivateStruct<Self>>(self, offset);
829 let priv_ = &*ptr;
830
831 match priv_.instance_data {
832 None => None,
833 Some(ref data) => data.get(&type_).and_then(|ptr| ptr.downcast_ref()),
834 }
835 }
836 }
837}
838
839pub trait FromObject {
842 type FromObjectType;
843 fn from_object(obj: &Self::FromObjectType) -> &Self;
844}
845
846pub struct InitializingObject<T: ObjectSubclass>(Borrowed<T::Type>);
852
853impl<T: ObjectSubclass> InitializingObject<T> {
854 #[inline]
863 pub unsafe fn as_ref(&self) -> &T::Type {
864 &self.0
865 }
866
867 #[inline]
876 pub fn as_ptr(&self) -> *mut T::Type {
877 self.0.as_ptr() as *const T::Type as *mut T::Type
878 }
879
880 pub fn set_instance_data<U: Any + Send + Sync + 'static>(&mut self, type_: Type, data: U) {
887 unsafe {
888 let type_data = T::type_data();
889 let self_type_ = type_data.as_ref().type_();
890 debug_assert!(self_type_.is_valid());
891
892 let offset = type_data.as_ref().private_offset;
893
894 let ptr = offset_ptr_by_bytes_mut::<
895 <<T as ObjectSubclass>::Type as ObjectType>::GlibType,
896 PrivateStruct<T>,
897 >(self.0.as_ptr(), offset);
898 let priv_ = &mut *ptr;
899
900 if priv_.instance_data.is_none() {
901 priv_.instance_data = Some(BTreeMap::default());
902 }
903
904 if let Some(ref mut instance_data) = priv_.instance_data {
905 assert!(
906 instance_data.get(&type_).is_none(),
907 "The class_data already contains a key for {type_}",
908 );
909
910 instance_data.insert(type_, Box::new(data));
911 }
912 }
913 }
914}
915
916unsafe extern "C" fn class_init<T: ObjectSubclass>(
917 klass: ffi::gpointer,
918 _klass_data: ffi::gpointer,
919) {
920 let mut data = T::type_data();
921
922 let mut private_offset = data.as_ref().private_offset as i32;
925 gobject_ffi::g_type_class_adjust_private_offset(klass, &mut private_offset);
926 data.as_mut().private_offset = private_offset as isize;
927
928 {
930 let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
931
932 gobject_klass.finalize = Some(finalize::<T>);
933 }
934
935 {
939 let klass = &mut *(klass as *mut T::Class);
940 let parent_class = gobject_ffi::g_type_class_peek_parent(klass as *mut _ as ffi::gpointer)
941 as *mut <T::ParentType as ObjectType>::GlibClassType;
942 debug_assert!(!parent_class.is_null());
943
944 data.as_mut().parent_class = parent_class as ffi::gpointer;
945
946 klass.class_init();
947 T::class_init(klass);
948 }
949}
950
951unsafe extern "C" fn instance_init<T: ObjectSubclass>(
952 obj: *mut gobject_ffi::GTypeInstance,
953 klass: ffi::gpointer,
954) {
955 let mut data = T::type_data();
958 let private_offset = data.as_mut().private_offset;
959 let priv_ptr = offset_ptr_by_bytes_mut::<gobject_ffi::GTypeInstance, PrivateStruct<T>>(
960 obj,
961 private_offset,
962 );
963
964 assert!(
965 priv_ptr as usize & (mem::align_of::<PrivateStruct<T>>() - 1) == 0,
966 "Private instance data has higher alignment requirements ({}) than \
967 the allocation from GLib. If alignment of more than {} bytes \
968 is required, store the corresponding data separately on the heap.",
969 mem::align_of::<PrivateStruct<T>>(),
970 2 * mem::size_of::<usize>(),
971 );
972
973 let klass = &*(klass as *const T::Class);
974
975 let imp = T::with_class(klass);
976 ptr::write(
977 priv_ptr,
978 PrivateStruct {
979 imp,
980 instance_data: None,
981 },
982 );
983
984 T::Instance::instance_init(&mut *(obj as *mut _));
986
987 let obj = from_glib_borrow::<_, Object>(obj.cast());
988 let obj = Borrowed::new(obj.into_inner().unsafe_cast());
989 let mut obj = InitializingObject(obj);
990
991 T::Interfaces::instance_init(&mut obj);
992 T::instance_init(&obj);
993}
994
995unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
996 let mut data = T::type_data();
998 let private_offset = data.as_mut().private_offset;
999 let priv_ptr =
1000 offset_ptr_by_bytes_mut::<gobject_ffi::GObject, PrivateStruct<T>>(obj, private_offset);
1001 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).imp));
1002 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).instance_data));
1003
1004 let parent_class = &*(data.as_ref().parent_class() as *const gobject_ffi::GObjectClass);
1006 if let Some(ref func) = parent_class.finalize {
1007 func(obj);
1008 }
1009}
1010
1011pub fn register_type<T: ObjectSubclass>() -> Type {
1021 assert!(
1024 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1025 "Alignment {} of type not supported, bigger than {}",
1026 mem::align_of::<T>(),
1027 2 * mem::size_of::<usize>(),
1028 );
1029
1030 unsafe {
1031 use std::ffi::CString;
1032
1033 let type_name = if T::ALLOW_NAME_CONFLICT {
1034 let mut i = 0;
1035 loop {
1036 let type_name = CString::new(if i == 0 {
1037 T::NAME.to_string()
1038 } else {
1039 format!("{}-{}", T::NAME, i)
1040 })
1041 .unwrap();
1042 if gobject_ffi::g_type_from_name(type_name.as_ptr()) == gobject_ffi::G_TYPE_INVALID
1043 {
1044 break type_name;
1045 }
1046 i += 1;
1047 }
1048 } else {
1049 let type_name = CString::new(T::NAME).unwrap();
1050 assert_eq!(
1051 gobject_ffi::g_type_from_name(type_name.as_ptr()),
1052 gobject_ffi::G_TYPE_INVALID,
1053 "Type {} has already been registered",
1054 type_name.to_str().unwrap()
1055 );
1056
1057 type_name
1058 };
1059
1060 let type_ = Type::from_glib(gobject_ffi::g_type_register_static_simple(
1061 <T::ParentType as StaticType>::static_type().into_glib(),
1062 type_name.as_ptr(),
1063 mem::size_of::<T::Class>() as u32,
1064 Some(class_init::<T>),
1065 mem::size_of::<T::Instance>() as u32,
1066 Some(instance_init::<T>),
1067 if T::ABSTRACT {
1068 gobject_ffi::G_TYPE_FLAG_ABSTRACT
1069 } else {
1070 0
1071 },
1072 ));
1073 assert!(type_.is_valid());
1074
1075 let mut data = T::type_data();
1076 data.as_mut().type_ = type_;
1077
1078 let private_offset = gobject_ffi::g_type_add_instance_private(
1079 type_.into_glib(),
1080 mem::size_of::<PrivateStruct<T>>(),
1081 );
1082 data.as_mut().private_offset = private_offset as isize;
1083
1084 data.as_mut().private_imp_offset = {
1087 let priv_ = mem::MaybeUninit::<PrivateStruct<T>>::uninit();
1089 let ptr = priv_.as_ptr();
1090 let imp_ptr = ptr::addr_of!((*ptr).imp);
1091 (imp_ptr as isize) - (ptr as isize)
1092 };
1093
1094 let iface_types = T::Interfaces::iface_infos();
1095 for (iface_type, iface_info) in iface_types {
1096 gobject_ffi::g_type_add_interface_static(
1097 type_.into_glib(),
1098 iface_type.into_glib(),
1099 iface_info.as_ptr(),
1100 );
1101 }
1102
1103 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1104
1105 type_
1106 }
1107}
1108
1109pub fn register_dynamic_type<P: DynamicObjectRegisterExt, T: ObjectSubclass>(
1126 type_plugin: &P,
1127) -> Type {
1128 assert!(
1131 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1132 "Alignment {} of type not supported, bigger than {}",
1133 mem::align_of::<T>(),
1134 2 * mem::size_of::<usize>(),
1135 );
1136
1137 unsafe {
1138 use std::ffi::CString;
1139
1140 let type_name = CString::new(T::NAME).unwrap();
1141
1142 let already_registered =
1143 gobject_ffi::g_type_from_name(type_name.as_ptr()) != gobject_ffi::G_TYPE_INVALID;
1144
1145 let type_info = TypeInfo(gobject_ffi::GTypeInfo {
1146 class_size: mem::size_of::<T::Class>() as u16,
1147 class_init: Some(class_init::<T>),
1148 instance_size: mem::size_of::<T::Instance>() as u16,
1149 instance_init: Some(instance_init::<T>),
1150 ..TypeInfo::default().0
1151 });
1152
1153 let type_ = type_plugin.register_dynamic_type(
1155 <T::ParentType as StaticType>::static_type(),
1156 type_name.to_str().unwrap(),
1157 &type_info,
1158 if T::ABSTRACT {
1159 TypeFlags::ABSTRACT
1160 } else {
1161 TypeFlags::NONE
1162 },
1163 );
1164 assert!(type_.is_valid());
1165
1166 let mut data = T::type_data();
1167 data.as_mut().type_ = type_;
1168
1169 let private_offset = mem::size_of::<PrivateStruct<T>>();
1170 data.as_mut().private_offset = private_offset as isize;
1171
1172 data.as_mut().private_imp_offset = {
1175 let priv_ = mem::MaybeUninit::<PrivateStruct<T>>::uninit();
1177 let ptr = priv_.as_ptr();
1178 let imp_ptr = ptr::addr_of!((*ptr).imp);
1179 (imp_ptr as isize) - (ptr as isize)
1180 };
1181
1182 let plugin_ptr = type_plugin.as_ref().to_glib_none().0;
1183 let iface_types = T::Interfaces::iface_infos();
1184 for (iface_type, iface_info) in iface_types {
1185 match gobject_ffi::g_type_get_plugin(iface_type.into_glib()) {
1186 iface_plugin if iface_plugin != plugin_ptr => {
1189 if !already_registered {
1191 gobject_ffi::g_type_add_interface_static(
1192 type_.into_glib(),
1193 iface_type.into_glib(),
1194 iface_info.as_ptr(),
1195 );
1196 }
1197 }
1198 _ => type_plugin.add_dynamic_interface(type_, iface_type, &iface_info),
1200 }
1201 }
1202
1203 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1204
1205 type_
1206 }
1207}
1208
1209pub(crate) unsafe fn signal_override_class_handler<F>(
1210 name: &str,
1211 type_: ffi::GType,
1212 class_handler: F,
1213) where
1214 F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
1215{
1216 let (signal_id, _) = SignalId::parse_name(name, from_glib(type_), false)
1217 .unwrap_or_else(|| panic!("Signal '{name}' not found"));
1218
1219 let query = signal_id.query();
1220 let return_type = query.return_type();
1221
1222 let class_handler = Closure::new(move |values| {
1223 let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
1224 let res = class_handler(
1225 &super::SignalClassHandlerToken(
1226 instance as *mut _,
1227 return_type.into(),
1228 values.as_ptr(),
1229 ),
1230 values,
1231 );
1232
1233 if return_type == Type::UNIT {
1234 if let Some(ref v) = res {
1235 panic!(
1236 "Signal has no return value but class handler returned a value of type {}",
1237 v.type_()
1238 );
1239 }
1240 } else {
1241 match res {
1242 None => {
1243 panic!("Signal has a return value but class handler returned none");
1244 }
1245 Some(ref v) => {
1246 assert!(
1247 v.type_().is_a(return_type.into()),
1248 "Signal has a return type of {} but class handler returned {}",
1249 Type::from(return_type),
1250 v.type_()
1251 );
1252 }
1253 }
1254 }
1255
1256 res
1257 });
1258
1259 gobject_ffi::g_signal_override_class_closure(
1260 signal_id.into_glib(),
1261 type_,
1262 class_handler.to_glib_none().0,
1263 );
1264}
1265
1266pub(crate) unsafe fn signal_chain_from_overridden(
1267 instance: *mut gobject_ffi::GTypeInstance,
1268 token: &super::SignalClassHandlerToken,
1269 values: &[Value],
1270) -> Option<Value> {
1271 assert_eq!(instance, token.0);
1272 assert_eq!(
1273 values.as_ptr(),
1274 token.2,
1275 "Arguments must be forwarded without changes when chaining up"
1276 );
1277
1278 let mut result = Value::from_type_unchecked(token.1);
1279 gobject_ffi::g_signal_chain_from_overridden(
1280 values.as_ptr() as *mut Value as *mut gobject_ffi::GValue,
1281 result.to_glib_none_mut().0,
1282 );
1283 Some(result).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
1284}