1use std::{any::Any, collections::BTreeMap, marker, mem, ptr};
7
8use super::{SignalId, interface::ObjectInterface};
9use crate::{
10 Closure, InterfaceInfo, Object, Type, 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 FINAL: bool = false;
630
631 const DEPRECATED: bool = false;
638
639 const ALLOW_NAME_CONFLICT: bool = false;
656
657 type Type: ObjectType
660 + ObjectSubclassIs<Subclass = Self>
661 + FromGlibPtrFull<*mut <Self::Type as ObjectType>::GlibType>
662 + FromGlibPtrBorrow<*mut <Self::Type as ObjectType>::GlibType>
663 + FromGlibPtrNone<*mut <Self::Type as ObjectType>::GlibType>;
664
665 type ParentType: IsSubclassable<Self>
668 + FromGlibPtrFull<*mut <Self::ParentType as ObjectType>::GlibType>
669 + FromGlibPtrBorrow<*mut <Self::ParentType as ObjectType>::GlibType>
670 + FromGlibPtrNone<*mut <Self::ParentType as ObjectType>::GlibType>;
671
672 type Interfaces: InterfaceList<Self>;
675
676 type Instance: InstanceStruct<Type = Self>;
686
687 type Class: ClassStruct<Type = Self>;
697
698 #[inline]
707 fn type_init(_type_: &mut InitializingType<Self>) {}
708
709 #[inline]
719 fn class_init(_klass: &mut Self::Class) {}
720
721 fn new() -> Self {
730 unimplemented!();
731 }
732
733 #[inline]
745 fn with_class(_klass: &Self::Class) -> Self {
746 Self::new()
747 }
748
749 #[inline]
755 fn instance_init(_obj: &InitializingObject<Self>) {}
756}
757
758pub trait ObjectSubclassExt: ObjectSubclass {
761 #[doc(alias = "get_instance")]
766 fn obj(&self) -> crate::BorrowedObject<'_, Self::Type>;
767
768 fn from_obj(obj: &Self::Type) -> &Self;
773
774 fn ref_counted(&self) -> super::ObjectImplRef<Self>;
777
778 #[doc(alias = "get_instance_data")]
783 fn instance_data<U: Any + Send + Sync + 'static>(&self, type_: Type) -> Option<&U>;
784}
785
786impl<T: ObjectSubclass> ObjectSubclassExt for T {
787 #[inline]
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 unsafe {
921 let mut data = T::type_data();
922
923 let mut private_offset = data.as_ref().private_offset as i32;
926 gobject_ffi::g_type_class_adjust_private_offset(klass, &mut private_offset);
927 data.as_mut().private_offset = private_offset as isize;
928
929 {
931 let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
932
933 gobject_klass.finalize = Some(finalize::<T>);
934 }
935
936 {
940 let klass = &mut *(klass as *mut T::Class);
941 let parent_class =
942 gobject_ffi::g_type_class_peek_parent(klass as *mut _ as ffi::gpointer)
943 as *mut <T::ParentType as ObjectType>::GlibClassType;
944 debug_assert!(!parent_class.is_null());
945
946 data.as_mut().parent_class = parent_class as ffi::gpointer;
947
948 klass.class_init();
949 T::class_init(klass);
950 }
951 }
952}
953
954unsafe extern "C" fn instance_init<T: ObjectSubclass>(
955 obj: *mut gobject_ffi::GTypeInstance,
956 klass: ffi::gpointer,
957) {
958 unsafe {
959 let mut data = T::type_data();
962 let private_offset = data.as_mut().private_offset;
963 let priv_ptr = offset_ptr_by_bytes_mut::<gobject_ffi::GTypeInstance, PrivateStruct<T>>(
964 obj,
965 private_offset,
966 );
967
968 assert!(
969 (priv_ptr as *const PrivateStruct<T>).is_aligned(),
970 "Private instance data has higher alignment requirements ({}) than \
971 the allocation from GLib. If alignment of more than {} bytes \
972 is required, store the corresponding data separately on the heap.",
973 mem::align_of::<PrivateStruct<T>>(),
974 2 * mem::size_of::<usize>(),
975 );
976
977 let klass = &*(klass as *const T::Class);
978
979 let imp = T::with_class(klass);
980 ptr::write(
981 priv_ptr,
982 PrivateStruct {
983 imp,
984 instance_data: None,
985 },
986 );
987
988 T::Instance::instance_init(&mut *(obj as *mut _));
990
991 let obj = from_glib_borrow::<_, Object>(obj.cast());
992 let obj = Borrowed::new(obj.into_inner().unsafe_cast());
993 let mut obj = InitializingObject(obj);
994
995 T::Interfaces::instance_init(&mut obj);
996 T::instance_init(&obj);
997 }
998}
999
1000unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
1001 unsafe {
1002 let mut data = T::type_data();
1004 let private_offset = data.as_mut().private_offset;
1005 let priv_ptr =
1006 offset_ptr_by_bytes_mut::<gobject_ffi::GObject, PrivateStruct<T>>(obj, private_offset);
1007 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).imp));
1008 ptr::drop_in_place(ptr::addr_of_mut!((*priv_ptr).instance_data));
1009
1010 let parent_class = &*(data.as_ref().parent_class() as *const gobject_ffi::GObjectClass);
1012 if let Some(ref func) = parent_class.finalize {
1013 func(obj);
1014 }
1015 }
1016}
1017
1018pub fn register_type<T: ObjectSubclass>() -> Type {
1028 assert!(
1031 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1032 "Alignment {} of type not supported, bigger than {}",
1033 mem::align_of::<T>(),
1034 2 * mem::size_of::<usize>(),
1035 );
1036
1037 unsafe {
1038 use std::ffi::CString;
1039
1040 let type_name = if T::ALLOW_NAME_CONFLICT {
1041 let mut i = 0;
1042 loop {
1043 let type_name = CString::new(if i == 0 {
1044 T::NAME.to_string()
1045 } else {
1046 format!("{}-{}", T::NAME, i)
1047 })
1048 .unwrap();
1049 if gobject_ffi::g_type_from_name(type_name.as_ptr()) == gobject_ffi::G_TYPE_INVALID
1050 {
1051 break type_name;
1052 }
1053 i += 1;
1054 }
1055 } else {
1056 let type_name = CString::new(T::NAME).unwrap();
1057 assert_eq!(
1058 gobject_ffi::g_type_from_name(type_name.as_ptr()),
1059 gobject_ffi::G_TYPE_INVALID,
1060 "Type {} has already been registered",
1061 type_name.to_str().unwrap()
1062 );
1063
1064 type_name
1065 };
1066 let mut flags = glib::TypeFlags::empty();
1067 if T::ABSTRACT {
1068 flags |= glib::TypeFlags::ABSTRACT;
1069 }
1070 if T::FINAL {
1071 flags |= glib::TypeFlags::FINAL;
1072 }
1073 if T::DEPRECATED {
1074 flags |= glib::TypeFlags::DEPRECATED;
1075 }
1076
1077 let type_ = Type::from_glib(gobject_ffi::g_type_register_static_simple(
1078 <T::ParentType as StaticType>::static_type().into_glib(),
1079 type_name.as_ptr(),
1080 mem::size_of::<T::Class>() as u32,
1081 Some(class_init::<T>),
1082 mem::size_of::<T::Instance>() as u32,
1083 Some(instance_init::<T>),
1084 flags.into_glib(),
1085 ));
1086 assert!(type_.is_valid());
1087
1088 let mut data = T::type_data();
1089 data.as_mut().type_ = type_;
1090
1091 let private_offset = gobject_ffi::g_type_add_instance_private(
1092 type_.into_glib(),
1093 mem::size_of::<PrivateStruct<T>>(),
1094 );
1095 data.as_mut().private_offset = private_offset as isize;
1096 data.as_mut().private_imp_offset = mem::offset_of!(PrivateStruct<T>, imp) as isize;
1097
1098 let iface_types = T::Interfaces::iface_infos();
1099 for (iface_type, iface_info) in iface_types {
1100 gobject_ffi::g_type_add_interface_static(
1101 type_.into_glib(),
1102 iface_type.into_glib(),
1103 iface_info.as_ptr(),
1104 );
1105 }
1106
1107 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1108
1109 type_
1110 }
1111}
1112
1113pub fn register_dynamic_type<P: DynamicObjectRegisterExt, T: ObjectSubclass>(
1130 type_plugin: &P,
1131) -> Type {
1132 assert!(
1135 mem::align_of::<T>() <= 2 * mem::size_of::<usize>(),
1136 "Alignment {} of type not supported, bigger than {}",
1137 mem::align_of::<T>(),
1138 2 * mem::size_of::<usize>(),
1139 );
1140
1141 unsafe {
1142 use std::ffi::CString;
1143
1144 let type_name = CString::new(T::NAME).unwrap();
1145
1146 let already_registered =
1147 gobject_ffi::g_type_from_name(type_name.as_ptr()) != gobject_ffi::G_TYPE_INVALID;
1148
1149 let type_info = TypeInfo(gobject_ffi::GTypeInfo {
1150 class_size: mem::size_of::<T::Class>() as u16,
1151 class_init: Some(class_init::<T>),
1152 instance_size: mem::size_of::<T::Instance>() as u16,
1153 instance_init: Some(instance_init::<T>),
1154 ..TypeInfo::default().0
1155 });
1156
1157 let mut flags = glib::TypeFlags::empty();
1158 if T::ABSTRACT {
1159 flags |= glib::TypeFlags::ABSTRACT;
1160 }
1161 if T::FINAL {
1162 flags |= glib::TypeFlags::FINAL;
1163 }
1164 if T::DEPRECATED {
1165 flags |= glib::TypeFlags::DEPRECATED;
1166 }
1167
1168 let type_ = type_plugin.register_dynamic_type(
1170 <T::ParentType as StaticType>::static_type(),
1171 type_name.to_str().unwrap(),
1172 &type_info,
1173 flags,
1174 );
1175 assert!(type_.is_valid());
1176
1177 let mut data = T::type_data();
1178 data.as_mut().type_ = type_;
1179
1180 let private_offset = mem::size_of::<PrivateStruct<T>>();
1181 data.as_mut().private_offset = private_offset as isize;
1182 data.as_mut().private_imp_offset = mem::offset_of!(PrivateStruct<T>, imp) as isize;
1183
1184 let plugin_ptr = type_plugin.as_ref().to_glib_none().0;
1185 let iface_types = T::Interfaces::iface_infos();
1186 for (iface_type, iface_info) in iface_types {
1187 match gobject_ffi::g_type_get_plugin(iface_type.into_glib()) {
1188 iface_plugin if iface_plugin != plugin_ptr => {
1191 if !already_registered {
1193 gobject_ffi::g_type_add_interface_static(
1194 type_.into_glib(),
1195 iface_type.into_glib(),
1196 iface_info.as_ptr(),
1197 );
1198 }
1199 }
1200 _ => type_plugin.add_dynamic_interface(type_, iface_type, &iface_info),
1202 }
1203 }
1204
1205 T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
1206
1207 type_
1208 }
1209}
1210
1211pub(crate) unsafe fn signal_override_class_handler<F>(
1212 name: &str,
1213 type_: ffi::GType,
1214 class_handler: F,
1215) where
1216 F: Fn(&super::SignalClassHandlerToken, &[Value]) -> Option<Value> + Send + Sync + 'static,
1217{
1218 unsafe {
1219 let (signal_id, _) = SignalId::parse_name(name, from_glib(type_), false)
1220 .unwrap_or_else(|| panic!("Signal '{name}' not found"));
1221
1222 let query = signal_id.query();
1223 let return_type = query.return_type();
1224
1225 let class_handler = Closure::new(move |values| {
1226 let instance = gobject_ffi::g_value_get_object(values[0].to_glib_none().0);
1227 let res = class_handler(
1228 &super::SignalClassHandlerToken(
1229 instance as *mut _,
1230 return_type.into(),
1231 values.as_ptr(),
1232 ),
1233 values,
1234 );
1235
1236 if return_type == Type::UNIT {
1237 if let Some(ref v) = res {
1238 panic!(
1239 "Signal has no return value but class handler returned a value of type {}",
1240 v.type_()
1241 );
1242 }
1243 } else {
1244 match res {
1245 None => {
1246 panic!("Signal has a return value but class handler returned none");
1247 }
1248 Some(ref v) => {
1249 assert!(
1250 v.type_().is_a(return_type.into()),
1251 "Signal has a return type of {} but class handler returned {}",
1252 Type::from(return_type),
1253 v.type_()
1254 );
1255 }
1256 }
1257 }
1258
1259 res
1260 });
1261
1262 gobject_ffi::g_signal_override_class_closure(
1263 signal_id.into_glib(),
1264 type_,
1265 class_handler.to_glib_none().0,
1266 );
1267 }
1268}
1269
1270pub(crate) unsafe fn signal_chain_from_overridden(
1271 instance: *mut gobject_ffi::GTypeInstance,
1272 token: &super::SignalClassHandlerToken,
1273 values: &[Value],
1274) -> Option<Value> {
1275 unsafe {
1276 assert_eq!(instance, token.0);
1277 assert_eq!(
1278 values.as_ptr(),
1279 token.2,
1280 "Arguments must be forwarded without changes when chaining up"
1281 );
1282
1283 let mut result = Value::from_type_unchecked(token.1);
1284 gobject_ffi::g_signal_chain_from_overridden(
1285 values.as_ptr() as *mut Value as *mut gobject_ffi::GValue,
1286 result.to_glib_none_mut().0,
1287 );
1288 Some(result).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
1289 }
1290}