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.expose_provenance();
103 let ptr = if offset < 0 {
104 ptr - (-offset) as usize
105 } else {
106 ptr + offset as usize
107 };
108 let ptr: *const U = std::ptr::with_exposed_provenance(ptr);
109 debug_assert!(ptr.is_aligned());
110 ptr
111}
112
113#[inline]
123fn offset_ptr_by_bytes_mut<T, U>(ptr: *mut T, offset: isize) -> *mut U {
124 let ptr = ptr.expose_provenance();
125 let ptr = if offset < 0 {
126 ptr - (-offset) as usize
127 } else {
128 ptr + offset as usize
129 };
130 let ptr: *mut U = std::ptr::with_exposed_provenance_mut(ptr);
131 debug_assert!(ptr.is_aligned());
132 ptr
133}
134
135unsafe impl<T: InstanceStruct> InstanceStructExt for T {
136 #[inline]
137 fn imp(&self) -> &Self::Type {
138 unsafe {
139 let data = Self::Type::type_data();
140 let private_offset = data.as_ref().impl_offset();
141 let imp = offset_ptr_by_bytes::<T, Self::Type>(self, private_offset);
142 &*imp
143 }
144 }
145
146 #[inline]
147 fn class(&self) -> &<Self::Type as ObjectSubclass>::Class {
148 unsafe { &**(self as *const _ as *const *const <Self::Type as ObjectSubclass>::Class) }
149 }
150}
151
152pub trait ObjectSubclassIsExt: ObjectSubclassIs {
155 fn imp(&self) -> &Self::Subclass;
158}
159
160impl<T: ObjectSubclassIs<Subclass = S>, S: ObjectSubclass<Type = Self>> ObjectSubclassIsExt for T {
161 #[inline]
162 fn imp(&self) -> &T::Subclass {
163 T::Subclass::from_obj(self)
164 }
165}
166
167pub unsafe trait ClassStruct: Sized + 'static {
179 type Type: ObjectSubclass;
182
183 #[inline]
188 fn class_init(&mut self) {
189 unsafe {
190 let base = &mut *(self as *mut _
191 as *mut crate::Class<<Self::Type as ObjectSubclass>::ParentType>);
192 <<Self::Type as ObjectSubclass>::ParentType as IsSubclassable<Self::Type>>::class_init(
193 base,
194 );
195 }
196 }
197}
198
199pub unsafe trait IsSubclassable<T: ObjectSubclass>: IsSubclassableDefault<T> {
202 #[inline]
209 fn class_init(class: &mut crate::Class<Self>) {
210 Self::default_class_init(class);
211 }
212
213 #[inline]
219 fn instance_init(instance: &mut InitializingObject<T>) {
220 Self::default_instance_init(instance);
221 }
222}
223
224#[doc(hidden)]
227pub trait IsSubclassableDefault<T: ObjectSubclass>: IsClass {
228 fn default_class_init(class: &mut crate::Class<Self>);
229 fn default_instance_init(instance: &mut InitializingObject<T>);
230}
231
232impl<T: ObjectSubclass, U: IsSubclassable<T> + ParentClassIs> IsSubclassableDefault<T> for U
233where
234 U::Parent: IsSubclassable<T>,
235{
236 #[inline]
237 fn default_class_init(class: &mut crate::Class<Self>) {
238 U::Parent::class_init(class);
239 }
240
241 #[inline]
242 fn default_instance_init(instance: &mut InitializingObject<T>) {
243 U::Parent::instance_init(instance);
244 }
245}
246
247impl<T: ObjectSubclass> IsSubclassableDefault<T> for Object {
248 #[inline]
249 fn default_class_init(_class: &mut crate::Class<Self>) {}
250
251 #[inline]
252 fn default_instance_init(_instance: &mut InitializingObject<T>) {}
253}
254
255pub trait IsSubclassableExt: IsClass + ParentClassIs {
256 fn parent_class_init<T: ObjectSubclass>(class: &mut crate::Class<Self>)
257 where
258 Self::Parent: IsSubclassable<T>;
259 fn parent_instance_init<T: ObjectSubclass>(instance: &mut InitializingObject<T>)
260 where
261 Self::Parent: IsSubclassable<T>;
262}
263
264impl<U: IsClass + ParentClassIs> IsSubclassableExt for U {
265 #[inline]
266 fn parent_class_init<T: ObjectSubclass>(class: &mut crate::Class<Self>)
267 where
268 U::Parent: IsSubclassable<T>,
269 {
270 Self::Parent::class_init(class);
271 }
272
273 #[inline]
274 fn parent_instance_init<T: ObjectSubclass>(instance: &mut InitializingObject<T>)
275 where
276 U::Parent: IsSubclassable<T>,
277 {
278 Self::Parent::instance_init(instance);
279 }
280}
281
282pub unsafe trait InterfaceStruct: Sized + 'static
288where
289 Self: Copy,
290{
291 type Type: ObjectInterface;
294
295 #[inline]
300 fn interface_init(&mut self) {}
301}
302
303pub unsafe trait IsImplementable<T: ObjectSubclass>: IsInterface {
306 fn interface_init(_iface: &mut crate::Interface<Self>) {}
312
313 fn instance_init(_instance: &mut InitializingObject<T>) {}
318}
319
320unsafe extern "C" fn interface_init<T: ObjectSubclass, A: IsImplementable<T>>(
321 iface: ffi::gpointer,
322 _iface_data: ffi::gpointer,
323) where
324 <A as ObjectType>::GlibClassType: Copy,
325{
326 unsafe {
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}
345
346pub trait InterfaceList<T: ObjectSubclass> {
349 fn iface_infos() -> Vec<(Type, InterfaceInfo)>;
352
353 fn instance_init(_instance: &mut InitializingObject<T>);
356}
357
358impl<T: ObjectSubclass> InterfaceList<T> for () {
359 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
360 vec![]
361 }
362
363 #[inline]
364 fn instance_init(_instance: &mut InitializingObject<T>) {}
365}
366
367impl<T: ObjectSubclass, A: IsImplementable<T>> InterfaceList<T> for (A,)
368where
369 <A as ObjectType>::GlibClassType: Copy,
370{
371 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
372 vec![(
373 A::static_type(),
374 InterfaceInfo(gobject_ffi::GInterfaceInfo {
375 interface_init: Some(interface_init::<T, A>),
376 ..InterfaceInfo::default().0
377 }),
378 )]
379 }
380
381 #[inline]
382 fn instance_init(instance: &mut InitializingObject<T>) {
383 A::instance_init(instance);
384 }
385}
386
387macro_rules! interface_list_trait(
390 ($name1:ident, $name2: ident, $($name:ident),*) => (
391 interface_list_trait!(__impl $name1, $name2; $($name),*);
392 );
393 (__impl $($name:ident),+; $name1:ident, $($name2:ident),*) => (
394 interface_list_trait_impl!($($name),+);
395 interface_list_trait!(__impl $($name),+ , $name1; $($name2),*);
396 );
397 (__impl $($name:ident),+; $name1:ident) => (
398 interface_list_trait_impl!($($name),+);
399 interface_list_trait_impl!($($name),+, $name1);
400 );
401);
402
403macro_rules! interface_list_trait_impl(
407 ($($name:ident),+) => (
408 impl<T: ObjectSubclass, $($name: IsImplementable<T>),+> InterfaceList<T> for ( $($name),+ )
409 where
410 $(<$name as ObjectType>::GlibClassType: Copy),+
411 {
412 fn iface_infos() -> Vec<(Type, InterfaceInfo)> {
413 vec![
414 $(
415 (
416 $name::static_type(),
417 InterfaceInfo(gobject_ffi::GInterfaceInfo {
418 interface_init: Some(interface_init::<T, $name>),
419 interface_finalize: None,
420 interface_data: ptr::null_mut(),
421 }),
422 )
423 ),+
424 ]
425 }
426
427 #[inline]
428 fn instance_init(instance: &mut InitializingObject<T>) {
429 $(
430 $name::instance_init(instance);
431 )+
432 }
433 }
434 );
435);
436
437interface_list_trait!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
438
439pub struct TypeData {
441 type_: Type,
442 parent_class: ffi::gpointer,
443 parent_ifaces: Option<BTreeMap<Type, ffi::gpointer>>,
444 class_data: Option<BTreeMap<Type, Box<dyn Any + Send + Sync>>>,
445 private_offset: isize,
446 private_imp_offset: isize,
447}
448
449unsafe impl Send for TypeData {}
450unsafe impl Sync for TypeData {}
451
452impl TypeData {
453 pub const fn new() -> Self {
454 Self {
455 type_: Type::INVALID,
456 parent_class: ::std::ptr::null_mut(),
457 parent_ifaces: None,
458 class_data: None,
459 private_offset: 0,
460 private_imp_offset: 0,
461 }
462 }
463
464 #[inline]
467 #[doc(alias = "get_type")]
468 pub fn type_(&self) -> Type {
469 self.type_
470 }
471
472 #[doc(alias = "get_parent_class")]
478 #[inline]
479 pub fn parent_class(&self) -> ffi::gpointer {
480 debug_assert!(!self.parent_class.is_null());
481 self.parent_class
482 }
483
484 #[doc(alias = "get_parent_interface")]
495 pub fn parent_interface<I: crate::object::IsInterface>(&self) -> ffi::gpointer {
496 match self.parent_ifaces {
497 None => unreachable!("No parent interfaces"),
498 Some(ref parent_ifaces) => *parent_ifaces
499 .get(&I::static_type())
500 .expect("Parent interface not found"),
501 }
502 }
503
504 #[doc(alias = "get_class_data")]
509 pub fn class_data<T: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&T> {
510 match self.class_data {
511 None => None,
512 Some(ref data) => data.get(&type_).and_then(|ptr| ptr.downcast_ref()),
513 }
514 }
515
516 #[doc(alias = "get_class_data_mut")]
523 pub unsafe fn class_data_mut<T: Any + Send + Sync + 'static>(
524 &mut self,
525 type_: Type,
526 ) -> Option<&mut T> {
527 match self.class_data {
528 None => None,
529 Some(ref mut data) => data.get_mut(&type_).and_then(|v| v.downcast_mut()),
530 }
531 }
532
533 pub unsafe fn set_class_data<T: Any + Send + Sync + 'static>(&mut self, type_: Type, data: T) {
544 if self.class_data.is_none() {
545 self.class_data = Some(BTreeMap::default());
546 }
547
548 if let Some(ref mut class_data) = self.class_data {
549 assert!(
550 class_data.get(&type_).is_none(),
551 "The class_data already contains a key for {type_}",
552 );
553
554 class_data.insert(type_, Box::new(data));
555 }
556 }
557
558 #[doc(alias = "get_impl_offset")]
562 #[inline]
563 pub fn impl_offset(&self) -> isize {
564 self.private_offset + self.private_imp_offset
565 }
566}
567
568impl Default for TypeData {
569 fn default() -> Self {
570 Self::new()
571 }
572}
573
574pub unsafe trait ObjectSubclassType {
579 fn type_data() -> ptr::NonNull<TypeData>;
582
583 #[doc(alias = "get_type")]
588 fn type_() -> Type;
589}
590
591pub trait ObjectSubclass: ObjectSubclassType + Sized + 'static {
603 const NAME: &'static str;
608
609 const ABSTRACT: bool = false;
619
620 const ALLOW_NAME_CONFLICT: bool = false;
637
638 type Type: ObjectType
641 + ObjectSubclassIs<Subclass = Self>
642 + FromGlibPtrFull<*mut <Self::Type as ObjectType>::GlibType>
643 + FromGlibPtrBorrow<*mut <Self::Type as ObjectType>::GlibType>
644 + FromGlibPtrNone<*mut <Self::Type as ObjectType>::GlibType>;
645
646 type ParentType: IsSubclassable<Self>
649 + FromGlibPtrFull<*mut <Self::ParentType as ObjectType>::GlibType>
650 + FromGlibPtrBorrow<*mut <Self::ParentType as ObjectType>::GlibType>
651 + FromGlibPtrNone<*mut <Self::ParentType as ObjectType>::GlibType>;
652
653 type Interfaces: InterfaceList<Self>;
656
657 type Instance: InstanceStruct<Type = Self>;
667
668 type Class: ClassStruct<Type = Self>;
678
679 #[inline]
688 fn type_init(_type_: &mut InitializingType<Self>) {}
689
690 #[inline]
700 fn class_init(_klass: &mut Self::Class) {}
701
702 fn new() -> Self {
711 unimplemented!();
712 }
713
714 #[inline]
726 fn with_class(_klass: &Self::Class) -> Self {
727 Self::new()
728 }
729
730 #[inline]
736 fn instance_init(_obj: &InitializingObject<Self>) {}
737}
738
739pub trait ObjectSubclassExt: ObjectSubclass {
742 #[doc(alias = "get_instance")]
747 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type>;
748
749 fn from_obj(obj: &Self::Type) -> &Self;
754
755 fn ref_counted(&self) -> super::ObjectImplRef<Self>;
758
759 #[doc(alias = "get_instance_data")]
764 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U>;
765}
766
767impl<T: ObjectSubclass> ObjectSubclassExt for T {
768 #[inline]
769 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type> {
770 unsafe {
771 let data = Self::type_data();
772 let type_ = data.as_ref().type_();
773 debug_assert!(type_.is_valid());
774
775 let offset = -data.as_ref().impl_offset();
776 let ptr =
777 offset_ptr_by_bytes::<Self, <Self::Type as ObjectType>::GlibType>(self, offset);
778
779 debug_assert_ne!((*(ptr as *const gobject_ffi::GObject)).ref_count, 0);
783
784 crate::BorrowedObject::new(mut_override(ptr))
785 }
786 }
787
788 #[inline]
789 fn from_obj(obj: &Self::Type) -> &Self {
790 unsafe {
791 let ptr = obj.as_ptr() as *const Self::Instance;
792 (*ptr).imp()
793 }
794 }
795
796 #[inline]
797 fn ref_counted(&self) -> super::ObjectImplRef<Self> {
798 super::ObjectImplRef::new(self)
799 }
800
801 #[inline]
802 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U> {
803 unsafe {
804 let type_data = Self::type_data();
805 let self_type_ = type_data.as_ref().type_();
806 debug_assert!(self_type_.is_valid());
807
808 let offset = -type_data.as_ref().private_imp_offset;
809 let ptr = offset_ptr_by_bytes::<Self, PrivateStruct<Self>>(self, offset);
810 let priv_ = &*ptr;
811
812 match priv_.instance_data {
813 None => None,
814 Some(ref data) => data.get(&type_).and_then(|ptr| ptr.downcast_ref()),
815 }
816 }
817 }
818}
819
820pub trait FromObject {
823 type FromObjectType;
824 fn from_object(obj: &Self::FromObjectType) -> &Self;
825}
826
827pub struct InitializingObject<T: ObjectSubclass>(Borrowed<T::Type>);
833
834impl<T: ObjectSubclass> InitializingObject<T> {
835 #[inline]
844 pub unsafe fn as_ref(&self) -> &T::Type {
845 &self.0
846 }
847
848 #[inline]
857 pub fn as_ptr(&self) -> *mut T::Type {
858 self.0.as_ptr() as *const T::Type as *mut T::Type
859 }
860
861 pub fn set_instance_data<U: Any + Send + Sync + 'static>(&mut self, type_: Type, data: U) {
868 unsafe {
869 let type_data = T::type_data();
870 let self_type_ = type_data.as_ref().type_();
871 debug_assert!(self_type_.is_valid());
872
873 let offset = type_data.as_ref().private_offset;
874
875 let ptr = offset_ptr_by_bytes_mut::<
876 <<T as ObjectSubclass>::Type as ObjectType>::GlibType,
877 PrivateStruct<T>,
878 >(self.0.as_ptr(), offset);
879 let priv_ = &mut *ptr;
880
881 if priv_.instance_data.is_none() {
882 priv_.instance_data = Some(BTreeMap::default());
883 }
884
885 if let Some(ref mut instance_data) = priv_.instance_data {
886 assert!(
887 instance_data.get(&type_).is_none(),
888 "The class_data already contains a key for {type_}",
889 );
890
891 instance_data.insert(type_, Box::new(data));
892 }
893 }
894 }
895}
896
897unsafe extern "C" fn class_init<T: ObjectSubclass>(
898 klass: ffi::gpointer,
899 _klass_data: ffi::gpointer,
900) {
901 unsafe {
902 let mut data = T::type_data();
903
904 let mut private_offset = data.as_ref().private_offset as i32;
907 gobject_ffi::g_type_class_adjust_private_offset(klass, &mut private_offset);
908 data.as_mut().private_offset = private_offset as isize;
909
910 {
912 let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
913
914 gobject_klass.finalize = Some(finalize::<T>);
915 }
916
917 {
921 let klass = &mut *(klass as *mut T::Class);
922 let parent_class =
923 gobject_ffi::g_type_class_peek_parent(klass as *mut _ as ffi::gpointer)
924 as *mut <T::ParentType as ObjectType>::GlibClassType;
925 debug_assert!(!parent_class.is_null());
926
927 data.as_mut().parent_class = parent_class as ffi::gpointer;
928
929 klass.class_init();
930 T::class_init(klass);
931 }
932 }
933}
934
935unsafe extern "C" fn instance_init<T: ObjectSubclass>(
936 obj: *mut gobject_ffi::GTypeInstance,
937 klass: ffi::gpointer,
938) {
939 unsafe {
940 let mut data = T::type_data();
943 let private_offset = data.as_mut().private_offset;
944 let priv_ptr = offset_ptr_by_bytes_mut::<gobject_ffi::GTypeInstance, PrivateStruct<T>>(
945 obj,
946 private_offset,
947 );
948
949 assert!(
950 (priv_ptr as *const PrivateStruct<T>).is_aligned(),
951 "Private instance data has higher alignment requirements ({}) than \
952 the allocation from GLib. If alignment of more than {} bytes \
953 is required, store the corresponding data separately on the heap.",
954 mem::align_of::<PrivateStruct<T>>(),
955 2 * mem::size_of::<usize>(),
956 );
957
958 let klass = &*(klass as *const T::Class);
959
960 let imp = T::with_class(klass);
961 ptr::write(
962 priv_ptr,
963 PrivateStruct {
964 imp,
965 instance_data: None,
966 },
967 );
968
969 T::Instance::instance_init(&mut *(obj as *mut _));
971
972 let obj = from_glib_borrow::<_, Object>(obj.cast());
973 let obj = Borrowed::new(obj.into_inner().unsafe_cast());
974 let mut obj = InitializingObject(obj);
975
976 T::Interfaces::instance_init(&mut obj);
977 T::instance_init(&obj);
978 }
979}
980
981unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
982 unsafe {
983 let mut data = T::type_data();
985 let private_offset = data.as_mut().private_offset;
986 let priv_ptr =
987 offset_ptr_by_bytes_mut::<gobject_ffi::GObject, PrivateStruct<T>>(obj, private_offset);
988 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).imp));
989 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).instance_data));
990
991 let parent_class = &*(data.as_ref().parent_class() as *const gobject_ffi::GObjectClass);
993 if let Some(ref func) = parent_class.finalize {
994 func(obj);
995 }
996 }
997}
998
999pub fn register_type<T: ObjectSubclass>() -> Type {
1009 assert!(
1012 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1013 "Alignment {} of type not supported, bigger than {}",
1014 mem::align_of::<T>(),
1015 2 * mem::size_of::<usize>(),
1016 );
1017
1018 unsafe {
1019 use std::ffi::CString;
1020
1021 let type_name = if T::ALLOW_NAME_CONFLICT {
1022 let mut i = 0;
1023 loop {
1024 let type_name = CString::new(if i == 0 {
1025 T::NAME.to_string()
1026 } else {
1027 format!("{}-{}", T::NAME, i)
1028 })
1029 .unwrap();
1030 if gobject_ffi::g_type_from_name(type_name.as_ptr()) == gobject_ffi::G_TYPE_INVALID
1031 {
1032 break type_name;
1033 }
1034 i += 1;
1035 }
1036 } else {
1037 let type_name = CString::new(T::NAME).unwrap();
1038 assert_eq!(
1039 gobject_ffi::g_type_from_name(type_name.as_ptr()),
1040 gobject_ffi::G_TYPE_INVALID,
1041 "Type {} has already been registered",
1042 type_name.to_str().unwrap()
1043 );
1044
1045 type_name
1046 };
1047
1048 let type_ = Type::from_glib(gobject_ffi::g_type_register_static_simple(
1049 <T::ParentType as StaticType>::static_type().into_glib(),
1050 type_name.as_ptr(),
1051 mem::size_of::<T::Class>() as u32,
1052 Some(class_init::<T>),
1053 mem::size_of::<T::Instance>() as u32,
1054 Some(instance_init::<T>),
1055 if T::ABSTRACT {
1056 gobject_ffi::G_TYPE_FLAG_ABSTRACT
1057 } else {
1058 0
1059 },
1060 ));
1061 assert!(type_.is_valid());
1062
1063 let mut data = T::type_data();
1064 data.as_mut().type_ = type_;
1065
1066 let private_offset = gobject_ffi::g_type_add_instance_private(
1067 type_.into_glib(),
1068 mem::size_of::<PrivateStruct<T>>(),
1069 );
1070 data.as_mut().private_offset = private_offset as isize;
1071 data.as_mut().private_imp_offset = mem::offset_of!(PrivateStruct<T>, imp) as isize;
1072
1073 let iface_types = T::Interfaces::iface_infos();
1074 for (iface_type, iface_info) in iface_types {
1075 gobject_ffi::g_type_add_interface_static(
1076 type_.into_glib(),
1077 iface_type.into_glib(),
1078 iface_info.as_ptr(),
1079 );
1080 }
1081
1082 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1083
1084 type_
1085 }
1086}
1087
1088pub fn register_dynamic_type<P: DynamicObjectRegisterExt, T: ObjectSubclass>(
1105 type_plugin: &P,
1106) -> Type {
1107 assert!(
1110 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1111 "Alignment {} of type not supported, bigger than {}",
1112 mem::align_of::<T>(),
1113 2 * mem::size_of::<usize>(),
1114 );
1115
1116 unsafe {
1117 use std::ffi::CString;
1118
1119 let type_name = CString::new(T::NAME).unwrap();
1120
1121 let already_registered =
1122 gobject_ffi::g_type_from_name(type_name.as_ptr()) != gobject_ffi::G_TYPE_INVALID;
1123
1124 let type_info = TypeInfo(gobject_ffi::GTypeInfo {
1125 class_size: mem::size_of::<T::Class>() as u16,
1126 class_init: Some(class_init::<T>),
1127 instance_size: mem::size_of::<T::Instance>() as u16,
1128 instance_init: Some(instance_init::<T>),
1129 ..TypeInfo::default().0
1130 });
1131
1132 let type_ = type_plugin.register_dynamic_type(
1134 <T::ParentType as StaticType>::static_type(),
1135 type_name.to_str().unwrap(),
1136 &type_info,
1137 if T::ABSTRACT {
1138 TypeFlags::ABSTRACT
1139 } else {
1140 TypeFlags::NONE
1141 },
1142 );
1143 assert!(type_.is_valid());
1144
1145 let mut data = T::type_data();
1146 data.as_mut().type_ = type_;
1147
1148 let private_offset = mem::size_of::<PrivateStruct<T>>();
1149 data.as_mut().private_offset = private_offset as isize;
1150 data.as_mut().private_imp_offset = mem::offset_of!(PrivateStruct<T>, imp) as isize;
1151
1152 let plugin_ptr = type_plugin.as_ref().to_glib_none().0;
1153 let iface_types = T::Interfaces::iface_infos();
1154 for (iface_type, iface_info) in iface_types {
1155 match gobject_ffi::g_type_get_plugin(iface_type.into_glib()) {
1156 iface_plugin if iface_plugin != plugin_ptr => {
1159 if !already_registered {
1161 gobject_ffi::g_type_add_interface_static(
1162 type_.into_glib(),
1163 iface_type.into_glib(),
1164 iface_info.as_ptr(),
1165 );
1166 }
1167 }
1168 _ => type_plugin.add_dynamic_interface(type_, iface_type, &iface_info),
1170 }
1171 }
1172
1173 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1174
1175 type_
1176 }
1177}
1178
1179pub(crate) unsafe fn signal_override_class_handler<F>(
1180 name: &str,
1181 type_: ffi::GType,
1182 class_handler: F,
1183) where
1184 F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
1185{
1186 unsafe {
1187 let (signal_id, _) = SignalId::parse_name(name, from_glib(type_), false)
1188 .unwrap_or_else(|| panic!("Signal '{name}' not found"));
1189
1190 let query = signal_id.query();
1191 let return_type = query.return_type();
1192
1193 let class_handler = Closure::new(move |values| {
1194 let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
1195 let res = class_handler(
1196 &super::SignalClassHandlerToken(
1197 instance as *mut _,
1198 return_type.into(),
1199 values.as_ptr(),
1200 ),
1201 values,
1202 );
1203
1204 if return_type == Type::UNIT {
1205 if let Some(ref v) = res {
1206 panic!(
1207 "Signal has no return value but class handler returned a value of type {}",
1208 v.type_()
1209 );
1210 }
1211 } else {
1212 match res {
1213 None => {
1214 panic!("Signal has a return value but class handler returned none");
1215 }
1216 Some(ref v) => {
1217 assert!(
1218 v.type_().is_a(return_type.into()),
1219 "Signal has a return type of {} but class handler returned {}",
1220 Type::from(return_type),
1221 v.type_()
1222 );
1223 }
1224 }
1225 }
1226
1227 res
1228 });
1229
1230 gobject_ffi::g_signal_override_class_closure(
1231 signal_id.into_glib(),
1232 type_,
1233 class_handler.to_glib_none().0,
1234 );
1235 }
1236}
1237
1238pub(crate) unsafe fn signal_chain_from_overridden(
1239 instance: *mut gobject_ffi::GTypeInstance,
1240 token: &super::SignalClassHandlerToken,
1241 values: &[Value],
1242) -> Option<Value> {
1243 unsafe {
1244 assert_eq!(instance, token.0);
1245 assert_eq!(
1246 values.as_ptr(),
1247 token.2,
1248 "Arguments must be forwarded without changes when chaining up"
1249 );
1250
1251 let mut result = Value::from_type_unchecked(token.1);
1252 gobject_ffi::g_signal_chain_from_overridden(
1253 values.as_ptr() as *mut Value as *mut gobject_ffi::GValue,
1254 result.to_glib_none_mut().0,
1255 );
1256 Some(result).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
1257 }
1258}