1use std::{cmp, fmt, hash, marker::PhantomData, mem, mem::ManuallyDrop, ops, pin::Pin, ptr};
7
8use crate::{
9 closure::TryFromClosureReturnValue,
10 ffi, gobject_ffi,
11 prelude::*,
12 quark::Quark,
13 subclass::{prelude::*, SignalId, SignalQuery},
14 thread_guard::thread_id,
15 translate::*,
16 value::FromValue,
17 Closure, PtrSlice, RustClosure, SignalHandlerId, Type, Value,
18};
19
20pub unsafe trait ObjectType:
23 UnsafeFrom<ObjectRef>
24 + Into<ObjectRef>
25 + StaticType
26 + fmt::Debug
27 + Clone
28 + PartialEq
29 + Eq
30 + PartialOrd
31 + Ord
32 + hash::Hash
33 + crate::value::ValueType
34 + ToValue
35 + crate::value::ToValueOptional
36 + crate::value::FromValueOptional<'static>
37 + for<'a> ToGlibPtr<'a, *mut <Self as ObjectType>::GlibType>
38 + IntoGlibPtr<*mut <Self as ObjectType>::GlibType>
39 + 'static
40{
41 type GlibType: 'static;
44 type GlibClassType: 'static;
47
48 fn as_object_ref(&self) -> &ObjectRef;
49 fn as_ptr(&self) -> *mut Self::GlibType;
50
51 unsafe fn from_glib_ptr_borrow(ptr: &*mut Self::GlibType) -> &Self;
52}
53
54pub unsafe trait IsA<T: ObjectType>:
67 ObjectType + Into<T> + AsRef<T> + std::borrow::Borrow<T>
68{
69}
70
71pub trait Cast: ObjectType {
76 #[inline]
91 fn upcast<T: ObjectType>(self) -> T
92 where
93 Self: IsA<T>,
94 {
95 unsafe { self.unsafe_cast() }
96 }
97
98 #[inline]
113 fn upcast_ref<T: ObjectType>(&self) -> &T
114 where
115 Self: IsA<T>,
116 {
117 unsafe { self.unsafe_cast_ref() }
118 }
119
120 #[inline]
138 fn downcast<T: ObjectType>(self) -> Result<T, Self>
139 where
140 Self: MayDowncastTo<T>,
141 {
142 if self.is::<T>() {
143 Ok(unsafe { self.unsafe_cast() })
144 } else {
145 Err(self)
146 }
147 }
148
149 #[inline]
167 fn downcast_ref<T: ObjectType>(&self) -> Option<&T>
168 where
169 Self: MayDowncastTo<T>,
170 {
171 if self.is::<T>() {
172 Some(unsafe { self.unsafe_cast_ref() })
173 } else {
174 None
175 }
176 }
177
178 #[inline]
201 fn dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
202 if !self.is::<T>() {
203 Err(self)
204 } else {
205 Ok(unsafe { self.unsafe_cast() })
206 }
207 }
208
209 #[inline]
230 fn dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
231 if !self.is::<T>() {
232 None
233 } else {
234 Some(unsafe { self.unsafe_cast_ref() })
239 }
240 }
241
242 #[track_caller]
254 #[inline]
255 unsafe fn unsafe_cast<T: ObjectType>(self) -> T {
256 debug_assert!(self.is::<T>());
257 T::unsafe_from(self.into())
258 }
259
260 #[track_caller]
272 #[inline]
273 unsafe fn unsafe_cast_ref<T: ObjectType>(&self) -> &T {
274 debug_assert!(self.is::<T>());
275 &*(self as *const Self as *const T)
280 }
281}
282
283impl<T: ObjectType> Cast for T {}
284
285pub trait CastNone: Sized {
304 type Inner;
305 fn and_downcast<T: ObjectType>(self) -> Option<T>
306 where
307 Self::Inner: MayDowncastTo<T>;
308 fn and_downcast_ref<T: ObjectType>(&self) -> Option<&T>
309 where
310 Self::Inner: MayDowncastTo<T>;
311 fn and_upcast<T: ObjectType>(self) -> Option<T>
312 where
313 Self::Inner: IsA<T>;
314 fn and_upcast_ref<T: ObjectType>(&self) -> Option<&T>
315 where
316 Self::Inner: IsA<T>;
317 fn and_dynamic_cast<T: ObjectType>(self) -> Result<T, Self>;
318 fn and_dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T>;
319}
320impl<I: ObjectType + Sized> CastNone for Option<I> {
321 type Inner = I;
322
323 #[inline]
324 fn and_downcast<T: ObjectType>(self) -> Option<T>
325 where
326 Self::Inner: MayDowncastTo<T>,
327 {
328 self.and_then(|i| i.downcast().ok())
329 }
330
331 #[inline]
332 fn and_downcast_ref<T: ObjectType>(&self) -> Option<&T>
333 where
334 Self::Inner: MayDowncastTo<T>,
335 {
336 self.as_ref().and_then(|i| i.downcast_ref())
337 }
338
339 #[inline]
340 fn and_upcast<T: ObjectType>(self) -> Option<T>
341 where
342 Self::Inner: IsA<T>,
343 {
344 self.map(|i| i.upcast())
345 }
346
347 #[inline]
348 fn and_upcast_ref<T: ObjectType>(&self) -> Option<&T>
349 where
350 Self::Inner: IsA<T>,
351 {
352 self.as_ref().map(|i| i.upcast_ref())
353 }
354
355 #[inline]
356 fn and_dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
357 self.ok_or(None)
358 .and_then(|i| i.dynamic_cast().map_err(|e| Some(e)))
359 }
360
361 #[inline]
362 fn and_dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
363 self.as_ref().and_then(|i| i.dynamic_cast_ref())
364 }
365}
366
367pub trait MayDowncastTo<T> {}
370
371impl<Super: IsA<Super>, Sub: IsA<Super>> MayDowncastTo<Sub> for Super {}
372
373#[repr(transparent)]
375pub struct ObjectRef {
376 inner: ptr::NonNull<gobject_ffi::GObject>,
377}
378
379impl Clone for ObjectRef {
380 #[inline]
381 fn clone(&self) -> Self {
382 unsafe {
383 Self {
384 inner: ptr::NonNull::new_unchecked(gobject_ffi::g_object_ref(self.inner.as_ptr())),
385 }
386 }
387 }
388}
389
390impl Drop for ObjectRef {
391 #[inline]
392 fn drop(&mut self) {
393 unsafe {
394 gobject_ffi::g_object_unref(self.inner.as_ptr());
395 }
396 }
397}
398
399impl fmt::Debug for ObjectRef {
400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
401 let type_ = unsafe {
402 let klass = (*self.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
403 (*klass).type_()
404 };
405
406 f.debug_struct("ObjectRef")
407 .field("inner", &self.inner)
408 .field("type", &type_)
409 .finish()
410 }
411}
412
413impl PartialOrd for ObjectRef {
414 #[inline]
415 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
416 Some(self.cmp(other))
417 }
418}
419
420impl Ord for ObjectRef {
421 #[inline]
422 fn cmp(&self, other: &Self) -> cmp::Ordering {
423 self.inner.cmp(&other.inner)
424 }
425}
426
427impl PartialEq for ObjectRef {
428 #[inline]
429 fn eq(&self, other: &Self) -> bool {
430 self.inner == other.inner
431 }
432}
433
434impl Eq for ObjectRef {}
435
436impl hash::Hash for ObjectRef {
437 #[inline]
438 fn hash<H>(&self, state: &mut H)
439 where
440 H: hash::Hasher,
441 {
442 self.inner.hash(state)
443 }
444}
445
446#[doc(hidden)]
447impl GlibPtrDefault for ObjectRef {
448 type GlibType = *mut gobject_ffi::GObject;
449}
450
451#[doc(hidden)]
452impl<'a> ToGlibPtr<'a, *mut gobject_ffi::GObject> for ObjectRef {
453 type Storage = PhantomData<&'a ObjectRef>;
454
455 #[inline]
456 fn to_glib_none(&'a self) -> Stash<'a, *mut gobject_ffi::GObject, Self> {
457 Stash(self.inner.as_ptr(), PhantomData)
458 }
459
460 #[inline]
461 fn to_glib_full(&self) -> *mut gobject_ffi::GObject {
462 unsafe { gobject_ffi::g_object_ref(self.inner.as_ptr()) }
463 }
464}
465
466#[doc(hidden)]
467impl FromGlibPtrNone<*mut gobject_ffi::GObject> for ObjectRef {
468 #[inline]
469 unsafe fn from_glib_none(ptr: *mut gobject_ffi::GObject) -> Self {
470 debug_assert!(!ptr.is_null());
471 debug_assert_ne!((*ptr).ref_count, 0);
472
473 Self {
475 inner: ptr::NonNull::new_unchecked(gobject_ffi::g_object_ref_sink(ptr)),
476 }
477 }
478}
479
480#[doc(hidden)]
481impl FromGlibPtrNone<*const gobject_ffi::GObject> for ObjectRef {
482 #[inline]
483 unsafe fn from_glib_none(ptr: *const gobject_ffi::GObject) -> Self {
484 from_glib_none(ptr as *mut gobject_ffi::GObject)
486 }
487}
488
489#[doc(hidden)]
490impl FromGlibPtrFull<*mut gobject_ffi::GObject> for ObjectRef {
491 #[inline]
492 unsafe fn from_glib_full(ptr: *mut gobject_ffi::GObject) -> Self {
493 debug_assert!(!ptr.is_null());
494 debug_assert_ne!((*ptr).ref_count, 0);
495
496 Self {
497 inner: ptr::NonNull::new_unchecked(ptr),
498 }
499 }
500}
501
502#[doc(hidden)]
503impl FromGlibPtrBorrow<*mut gobject_ffi::GObject> for ObjectRef {
504 #[inline]
505 unsafe fn from_glib_borrow(ptr: *mut gobject_ffi::GObject) -> Borrowed<Self> {
506 debug_assert!(!ptr.is_null());
507 debug_assert_ne!((*ptr).ref_count, 0);
508
509 Borrowed::new(Self {
510 inner: ptr::NonNull::new_unchecked(ptr),
511 })
512 }
513}
514
515#[doc(hidden)]
516impl FromGlibPtrBorrow<*const gobject_ffi::GObject> for ObjectRef {
517 #[inline]
518 unsafe fn from_glib_borrow(ptr: *const gobject_ffi::GObject) -> Borrowed<Self> {
519 from_glib_borrow(ptr as *mut gobject_ffi::GObject)
520 }
521}
522
523#[repr(transparent)]
524pub struct TypedObjectRef<T, P> {
525 inner: ObjectRef,
526 imp: PhantomData<T>,
527 parent: PhantomData<P>,
528}
529
530impl<T, P> TypedObjectRef<T, P> {
531 #[inline]
532 pub unsafe fn new(obj: ObjectRef) -> Self {
533 Self {
534 inner: obj,
535 imp: PhantomData,
536 parent: PhantomData,
537 }
538 }
539
540 #[inline]
541 pub fn into_inner(self) -> ObjectRef {
542 self.inner
543 }
544}
545
546impl<T, P> Clone for TypedObjectRef<T, P> {
547 #[inline]
548 fn clone(&self) -> Self {
549 Self {
550 inner: self.inner.clone(),
551 imp: PhantomData,
552 parent: PhantomData,
553 }
554 }
555}
556
557impl<T, P> ops::Deref for TypedObjectRef<T, P> {
558 type Target = ObjectRef;
559
560 #[inline]
561 fn deref(&self) -> &Self::Target {
562 &self.inner
563 }
564}
565
566impl<T, P> fmt::Debug for TypedObjectRef<T, P> {
567 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568 let type_ = unsafe {
569 let klass = (*self.inner.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
570 (*klass).type_()
571 };
572
573 f.debug_struct("TypedObjectRef")
574 .field("inner", &self.inner.inner)
575 .field("type", &type_)
576 .finish()
577 }
578}
579
580impl<T, P> PartialOrd for TypedObjectRef<T, P> {
581 #[inline]
582 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
583 Some(self.cmp(other))
584 }
585}
586
587impl<T, P> Ord for TypedObjectRef<T, P> {
588 #[inline]
589 fn cmp(&self, other: &Self) -> cmp::Ordering {
590 self.inner.cmp(&other.inner)
591 }
592}
593
594impl<T, P> PartialEq for TypedObjectRef<T, P> {
595 #[inline]
596 fn eq(&self, other: &Self) -> bool {
597 self.inner == other.inner
598 }
599}
600
601impl<T, P> Eq for TypedObjectRef<T, P> {}
602
603impl<T, P> hash::Hash for TypedObjectRef<T, P> {
604 #[inline]
605 fn hash<H>(&self, state: &mut H)
606 where
607 H: hash::Hasher,
608 {
609 self.inner.hash(state)
610 }
611}
612
613unsafe impl<T: Send + Sync, P: Send + Sync> Send for TypedObjectRef<T, P> {}
614unsafe impl<T: Send + Sync, P: Send + Sync> Sync for TypedObjectRef<T, P> {}
615
616#[macro_export]
619macro_rules! glib_object_wrapper {
620 (@generic_impl [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty, $ffi_class_name:ty, @type_ $get_type_expr:expr) => {
621 $(#[$attr])*
622 #[doc = "\n\nGLib type: GObject with reference counted clone semantics."]
623 #[repr(transparent)]
624 $visibility struct $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? {
625 inner: $crate::object::TypedObjectRef<$impl_type, $parent_type>,
626 phantom: std::marker::PhantomData<($($($generic),+)?)>,
627 }
628
629 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::clone::Clone for $name $(<$($generic),+>)? {
637 #[doc = "Makes a clone of this shared reference.\n\nThis increments the strong reference count of the object. Dropping the object will decrement it again."]
638 #[inline]
639 fn clone(&self) -> Self {
640 Self {
641 inner: std::clone::Clone::clone(&self.inner),
642 phantom: std::marker::PhantomData,
643 }
644 }
645 }
646
647 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::hash::Hash for $name $(<$($generic),+>)? {
648 #[doc = "Hashes the memory address of this object."]
649 #[inline]
650 fn hash<H>(&self, state: &mut H)
651 where
652 H: std::hash::Hasher
653 {
654 std::hash::Hash::hash(&self.inner, state);
655 }
656 }
657
658 impl<OT: $crate::object::ObjectType $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> std::cmp::PartialEq<OT> for $name $(<$($generic),+>)? {
659 #[doc = "Equality for two GObjects.\n\nTwo GObjects are equal if their memory addresses are equal."]
660 #[inline]
661 fn eq(&self, other: &OT) -> bool {
662 std::cmp::PartialEq::eq(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
663 }
664 }
665
666 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::cmp::Eq for $name $(<$($generic),+>)? {}
667
668 impl<OT: $crate::object::ObjectType $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> std::cmp::PartialOrd<OT> for $name $(<$($generic),+>)? {
669 #[doc = "Partial comparison for two GObjects.\n\nCompares the memory addresses of the provided objects."]
670 #[inline]
671 fn partial_cmp(&self, other: &OT) -> Option<std::cmp::Ordering> {
672 std::cmp::PartialOrd::partial_cmp(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
673 }
674 }
675
676 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::cmp::Ord for $name $(<$($generic),+>)? {
677 #[doc = "Comparison for two GObjects.\n\nCompares the memory addresses of the provided objects."]
678 #[inline]
679 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
680 std::cmp::Ord::cmp(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
681 }
682 }
683
684
685 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::fmt::Debug for $name $(<$($generic),+>)? {
686 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
687 f.debug_struct(stringify!($name)).field("inner", &self.inner).finish()
688 }
689 }
690
691 #[doc(hidden)]
692 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::ObjectRef {
693 #[inline]
694 fn from(s: $name $(<$($generic),+>)?) -> $crate::object::ObjectRef {
695 s.inner.into_inner()
696 }
697 }
698
699 #[doc(hidden)]
700 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::UnsafeFrom<$crate::object::ObjectRef> for $name $(<$($generic),+>)? {
701 #[inline]
702 unsafe fn unsafe_from(t: $crate::object::ObjectRef) -> Self {
703 $name {
704 inner: $crate::object::TypedObjectRef::new(t),
705 phantom: std::marker::PhantomData,
706 }
707 }
708 }
709
710 #[doc(hidden)]
711 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::GlibPtrDefault for $name $(<$($generic),+>)? {
712 type GlibType = *mut $ffi_name;
713 }
714
715 #[doc(hidden)]
716 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::TransparentPtrType for $name $(<$($generic),+>)? {}
717
718 #[doc(hidden)]
719 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectType for $name $(<$($generic),+>)? {
720 type GlibType = $ffi_name;
721 type GlibClassType = $ffi_class_name;
722
723 #[inline]
724 fn as_object_ref(&self) -> &$crate::object::ObjectRef {
725 &self.inner
726 }
727
728 #[inline]
729 fn as_ptr(&self) -> *mut Self::GlibType {
730 unsafe { *(self as *const Self as *const *const $ffi_name) as *mut $ffi_name }
731 }
732
733 #[inline]
734 unsafe fn from_glib_ptr_borrow(ptr: &*mut Self::GlibType) -> &Self {
735 debug_assert_eq!(
736 std::mem::size_of::<Self>(),
737 std::mem::size_of::<$crate::ffi::gpointer>()
738 );
739 debug_assert!(!ptr.is_null());
740 debug_assert_ne!((*(*ptr as *const $crate::gobject_ffi::GObject)).ref_count, 0);
741 &*(ptr as *const *mut $ffi_name as *const Self)
742 }
743 }
744
745 #[doc(hidden)]
746 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::ObjectRef> for $name $(<$($generic),+>)? {
747 #[inline]
748 fn as_ref(&self) -> &$crate::object::ObjectRef {
749 &self.inner
750 }
751 }
752
753 #[doc(hidden)]
754 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<Self> for $name $(<$($generic),+>)? {
755 #[inline]
756 fn as_ref(&self) -> &Self {
757 self
758 }
759 }
760
761 #[doc(hidden)]
762 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<Self> for $name $(<$($generic),+>)? { }
763
764 #[doc(hidden)]
765 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::subclass::types::FromObject for $name $(<$($generic),+>)? {
766 type FromObjectType = Self;
767
768 #[inline]
769 fn from_object(obj: &Self::FromObjectType) -> &Self {
770 obj
771 }
772 }
773
774 #[doc(hidden)]
775 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name $(<$($generic),+>)? {
776 type Storage = <$crate::object::ObjectRef as
777 $crate::translate::ToGlibPtr<'a, *mut $crate::gobject_ffi::GObject>>::Storage;
778
779 #[inline]
780 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
781 let stash = $crate::translate::ToGlibPtr::to_glib_none(&*self.inner);
782 $crate::translate::Stash(stash.0 as *const _, stash.1)
783 }
784
785 #[inline]
786 fn to_glib_full(&self) -> *const $ffi_name {
787 $crate::translate::ToGlibPtr::to_glib_full(&*self.inner) as *const _
788 }
789 }
790
791 #[doc(hidden)]
792 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name $(<$($generic),+>)? {
793 type Storage = <$crate::object::ObjectRef as
794 $crate::translate::ToGlibPtr<'a, *mut $crate::gobject_ffi::GObject>>::Storage;
795
796 #[inline]
797 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
798 let stash = $crate::translate::ToGlibPtr::to_glib_none(&*self.inner);
799 $crate::translate::Stash(stash.0 as *mut _, stash.1)
800 }
801
802 #[inline]
803 fn to_glib_full(&self) -> *mut $ffi_name {
804 $crate::translate::ToGlibPtr::to_glib_full(&*self.inner) as *mut _
805 }
806 }
807
808 #[doc(hidden)]
809 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*mut $ffi_name> for $name $(<$($generic),+>)? {
810 #[inline]
811 unsafe fn into_glib_ptr(self) -> *mut $ffi_name {
812 let s = std::mem::ManuallyDrop::new(self);
813 $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *mut _
814 }
815 }
816
817 #[doc(hidden)]
818 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*const $ffi_name> for $name $(<$($generic),+>)? {
819 #[inline]
820 unsafe fn into_glib_ptr(self) -> *const $ffi_name {
821 let s = std::mem::ManuallyDrop::new(self);
822 $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *const _
823 }
824 }
825
826 #[doc(hidden)]
827 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
828 type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*mut $ffi_name>>);
829
830 fn to_glib_none_from_slice(t: &'a [Self]) -> (*mut *mut $ffi_name, Self::Storage) {
831 let mut v_ptr = Vec::with_capacity(t.len() + 1);
832 unsafe {
833 let ptr = v_ptr.as_mut_ptr();
834 std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *mut $ffi_name, ptr, t.len());
835 std::ptr::write(ptr.add(t.len()), std::ptr::null_mut());
836 v_ptr.set_len(t.len() + 1);
837 }
838
839 (v_ptr.as_ptr() as *mut *mut $ffi_name, (std::marker::PhantomData, Some(v_ptr)))
840 }
841
842 fn to_glib_container_from_slice(t: &'a [Self]) -> (*mut *mut $ffi_name, Self::Storage) {
843 let v_ptr = unsafe {
844 let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
845
846 std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *mut $ffi_name, v_ptr, t.len());
847 std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut());
848
849 v_ptr
850 };
851
852 (v_ptr, (std::marker::PhantomData, None))
853 }
854
855 fn to_glib_full_from_slice(t: &[Self]) -> *mut *mut $ffi_name {
856 unsafe {
857 let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
858
859 for (i, s) in t.iter().enumerate() {
860 std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
861 }
862 std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut());
863
864 v_ptr
865 }
866 }
867 }
868
869 #[doc(hidden)]
870 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
871 type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*mut $ffi_name>>);
872
873 fn to_glib_none_from_slice(t: &'a [Self]) -> (*const *mut $ffi_name, Self::Storage) {
874 let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *mut $ffi_name>::to_glib_none_from_slice(t);
875 (ptr as *const *mut $ffi_name, stash)
876 }
877
878 fn to_glib_container_from_slice(_: &'a [Self]) -> (*const *mut $ffi_name, Self::Storage) {
879 unimplemented!()
881 }
882
883 fn to_glib_full_from_slice(_: &[Self]) -> *const *mut $ffi_name {
884 unimplemented!()
886 }
887 }
888
889 #[doc(hidden)]
890 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name $(<$($generic),+>)? {
891 #[inline]
892 #[allow(clippy::cast_ptr_alignment)]
893 unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
894 debug_assert!(!ptr.is_null());
895 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
896 $name {
897 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_none(ptr as *mut _)),
898 phantom: std::marker::PhantomData,
899 }
900 }
901 }
902
903 #[doc(hidden)]
904 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name $(<$($generic),+>)? {
905 #[inline]
906 #[allow(clippy::cast_ptr_alignment)]
907 unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
908 debug_assert!(!ptr.is_null());
909 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
910 $name {
911 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_none(ptr as *mut _)),
912 phantom: std::marker::PhantomData,
913 }
914 }
915 }
916
917 #[doc(hidden)]
918 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name $(<$($generic),+>)? {
919 #[inline]
920 #[allow(clippy::cast_ptr_alignment)]
921 unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
922 debug_assert!(!ptr.is_null());
923 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
924 $name {
925 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_full(ptr as *mut _)),
926 phantom: std::marker::PhantomData,
927 }
928 }
929 }
930
931 #[doc(hidden)]
932 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name $(<$($generic),+>)? {
933 #[inline]
934 #[allow(clippy::cast_ptr_alignment)]
935 unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> $crate::translate::Borrowed<Self> {
936 debug_assert!(!ptr.is_null());
937 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
938 $crate::translate::Borrowed::new(
939 $name {
940 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_borrow::<_, $crate::object::ObjectRef>(ptr as *mut _).into_inner()),
941 phantom: std::marker::PhantomData,
942 }
943 )
944 }
945 }
946
947 #[doc(hidden)]
948 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name $(<$($generic),+>)? {
949 #[inline]
950 #[allow(clippy::cast_ptr_alignment)]
951 unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> $crate::translate::Borrowed<Self> {
952 $crate::translate::from_glib_borrow::<_, Self>(ptr as *mut $ffi_name)
953 }
954 }
955
956 #[doc(hidden)]
957 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
958 unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
959 if num == 0 || ptr.is_null() {
960 return Vec::new();
961 }
962
963 let mut res = Vec::<Self>::with_capacity(num);
964 let res_ptr = res.as_mut_ptr();
965 for i in 0..num {
966 ::std::ptr::write(res_ptr.add(i), $crate::translate::from_glib_none(std::ptr::read(ptr.add(i))));
967 }
968 res.set_len(num);
969 res
970 }
971
972 unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
973 let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
974 $crate::ffi::g_free(ptr as *mut _);
975 res
976 }
977
978 unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
979 if num == 0 || ptr.is_null() {
980 $crate::ffi::g_free(ptr as *mut _);
981 return Vec::new();
982 }
983
984 let mut res = Vec::with_capacity(num);
985 let res_ptr = res.as_mut_ptr();
986 ::std::ptr::copy_nonoverlapping(ptr as *mut Self, res_ptr, num);
987 res.set_len(num);
988 $crate::ffi::g_free(ptr as *mut _);
989 res
990 }
991 }
992
993 #[doc(hidden)]
994 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
995 unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
996 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
997 }
998
999 unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1000 $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1001 }
1002
1003 unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1004 $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1005 }
1006 }
1007
1008 #[doc(hidden)]
1009 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
1010 unsafe fn from_glib_none_num_as_vec(ptr: *const *mut $ffi_name, num: usize) -> Vec<Self> {
1011 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
1012 }
1013
1014 unsafe fn from_glib_container_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1015 unimplemented!()
1017 }
1018
1019 unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1020 unimplemented!()
1022 }
1023 }
1024
1025 #[doc(hidden)]
1026 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
1027 unsafe fn from_glib_none_as_vec(ptr: *const *mut $ffi_name) -> Vec<Self> {
1028 $crate::translate::FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
1029 }
1030
1031 unsafe fn from_glib_container_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1032 unimplemented!()
1034 }
1035
1036 unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1037 unimplemented!()
1039 }
1040 }
1041
1042 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::StaticType for $name $(<$($generic),+>)? {
1043 #[inline]
1044 fn static_type() -> $crate::types::Type {
1045 #[allow(unused_unsafe)]
1046 #[allow(clippy::macro_metavars_in_unsafe)]
1047 unsafe { $crate::translate::from_glib($get_type_expr) }
1048 }
1049 }
1050
1051 #[doc(hidden)]
1052 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueType for $name $(<$($generic),+>)? {
1053 type Type = $name $(<$($generic),+>)?;
1054 }
1055
1056 #[doc(hidden)]
1057 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueTypeOptional for $name $(<$($generic),+>)? { }
1058
1059 #[doc(hidden)]
1060 unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for $name $(<$($generic),+>)? {
1061 type Checker = $crate::object::ObjectValueTypeChecker<Self>;
1062
1063 #[inline]
1064 unsafe fn from_value(value: &'a $crate::Value) -> Self {
1065 let ptr = $crate::gobject_ffi::g_value_dup_object($crate::translate::ToGlibPtr::to_glib_none(value).0);
1066 debug_assert!(!ptr.is_null());
1067 debug_assert_ne!((*ptr).ref_count, 0);
1068 <Self as $crate::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(ptr as *mut $ffi_name)
1069 }
1070 }
1071
1072 #[doc(hidden)]
1073 unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for &'a $name $(<$($generic),+>)? {
1074 type Checker = $crate::object::ObjectValueTypeChecker<Self>;
1075
1076 #[inline]
1077 unsafe fn from_value(value: &'a $crate::Value) -> Self {
1078 let value = &*(value as *const $crate::Value as *const $crate::gobject_ffi::GValue);
1079 <$name $(<$($generic),+>)? as $crate::object::ObjectType>::from_glib_ptr_borrow(&*(&value.data[0].v_pointer as *const $crate::ffi::gpointer as *const *mut $ffi_name))
1080 }
1081 }
1082
1083 #[doc(hidden)]
1084 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValue for $name $(<$($generic),+>)? {
1085 #[inline]
1086 fn to_value(&self) -> $crate::Value {
1087 unsafe {
1088 let mut value = $crate::Value::from_type_unchecked(<Self as $crate::prelude::StaticType>::static_type());
1089 $crate::gobject_ffi::g_value_take_object(
1090 $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1091 $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(self) as *mut _,
1092 );
1093 value
1094 }
1095 }
1096
1097 #[inline]
1098 fn value_type(&self) -> $crate::Type {
1099 <Self as $crate::prelude::StaticType>::static_type()
1100 }
1101 }
1102
1103 #[doc(hidden)]
1104 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? ::std::convert::From<$name $(<$($generic),+>)?> for $crate::Value {
1105 #[inline]
1106 fn from(o: $name $(<$($generic),+>)?) -> Self {
1107 unsafe {
1108 let mut value = $crate::Value::from_type_unchecked(<$name $(<$($generic),+>)? as $crate::prelude::StaticType>::static_type());
1109 $crate::gobject_ffi::g_value_take_object(
1110 $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1111 $crate::translate::IntoGlibPtr::<*mut $ffi_name>::into_glib_ptr(o) as *mut _,
1112 );
1113 value
1114 }
1115 }
1116 }
1117
1118 #[doc(hidden)]
1119 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValueOptional for $name $(<$($generic),+>)? {
1120 #[inline]
1121 fn to_value_optional(s: Option<&Self>) -> $crate::Value {
1122 let mut value = $crate::Value::for_value_type::<Self>();
1123 unsafe {
1124 $crate::gobject_ffi::g_value_take_object(
1125 $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1126 $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(&s) as *mut _,
1127 );
1128 }
1129
1130 value
1131 }
1132 }
1133
1134 $crate::glib_object_wrapper!(@weak_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?);
1135
1136 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::HasParamSpec for $name $(<$($generic),+>)? {
1137 type ParamSpec = $crate::ParamSpecObject;
1138 type SetValue = Self;
1139 type BuilderFn = fn(&str) -> $crate::ParamSpecObjectBuilder<Self>;
1140
1141 fn param_spec_builder() -> Self::BuilderFn {
1142 |name| Self::ParamSpec::builder(name)
1143 }
1144 }
1145 };
1146
1147 (@weak_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?) => {
1148 #[doc(hidden)]
1149 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::clone::Downgrade for $name $(<$($generic),+>)? {
1150 type Weak = $crate::object::WeakRef<Self>;
1151
1152 #[inline]
1153 fn downgrade(&self) -> Self::Weak {
1154 <Self as $crate::object::ObjectExt>::downgrade(&self)
1155 }
1156 }
1157 };
1158
1159 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => { };
1160
1161 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1162 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$super_name> for $name $(<$($generic),+>)? { }
1163
1164 #[doc(hidden)]
1165 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $super_name {
1166 #[inline]
1167 fn from(v: $name $(<$($generic),+>)?) -> Self {
1168 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1169 }
1170 }
1171
1172 #[doc(hidden)]
1173 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$super_name> for $name $(<$($generic),+>)? {
1174 #[inline]
1175 fn as_ref(&self) -> &$super_name {
1176 $crate::object::Cast::upcast_ref(self)
1177 }
1178 }
1179
1180 #[doc(hidden)]
1181 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$super_name> for $name $(<$($generic),+>)? {
1182 #[inline]
1183 fn borrow(&self) -> &$super_name {
1184 $crate::object::Cast::upcast_ref(self)
1185 }
1186 }
1187 };
1188
1189 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1190 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1191 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1192 };
1193
1194 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => {
1196 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, );
1197 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1198 type Parent = $crate::object::Object;
1199 }
1200 };
1201
1202 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1204 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1205 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1206 type Parent = $super_name;
1207 }
1208 };
1209
1210 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1212 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1213 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1214 type Parent = $super_name;
1215 }
1216 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1217 };
1218
1219 (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty, @type_ $get_type_expr:expr) => {
1222 $crate::glib_object_wrapper!(
1223 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1224 @type_ $get_type_expr);
1225
1226 #[doc(hidden)]
1227 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1228 };
1229
1230 (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty,
1231 @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1232 $crate::glib_object_wrapper!(
1233 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, @ffi_class std::os::raw::c_void,
1234 @type_ $get_type_expr, @extends [$($extends)*], @implements [$($implements)*]
1235 );
1236 };
1237
1238 (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty,
1239 @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1240 $crate::glib_object_wrapper!(
1241 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1242 @type_ $get_type_expr
1243 );
1244
1245 $crate::glib_object_wrapper!(@munch_first_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($extends)*);
1246
1247 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1248
1249 #[doc(hidden)]
1250 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1251 #[inline]
1252 fn as_ref(&self) -> &$crate::object::Object {
1253 $crate::object::Cast::upcast_ref(self)
1254 }
1255 }
1256
1257 #[doc(hidden)]
1258 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1259 #[inline]
1260 fn borrow(&self) -> &$crate::object::Object {
1261 $crate::object::Cast::upcast_ref(self)
1262 }
1263 }
1264
1265 #[doc(hidden)]
1266 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1267 #[inline]
1268 fn from(v: $name $(<$($generic),+>)?) -> Self {
1269 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1270 }
1271 }
1272
1273 #[doc(hidden)]
1274 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1275
1276 #[doc(hidden)]
1277 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1278 };
1279
1280 (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1283 @extends [], @implements [$($implements:tt)*]) => {
1284 $crate::glib_object_wrapper!(
1285 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1286 $subclass, (),
1287 <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1288 @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1289 @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1290 @extends [], @implements [$($implements)*]
1291 );
1292
1293 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1294 type Subclass = $subclass;
1295 }
1296 };
1297
1298 (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1299 @extends [$($extends:tt)+], @implements [$($implements:tt)*]) => {
1300 $crate::glib_object_wrapper!(
1301 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1302 $subclass, <$subclass as $crate::subclass::types::ObjectSubclass>::ParentType,
1303 <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1304 @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1305 @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1306 @extends [$($extends)*], @implements [$($implements)*]
1307 );
1308
1309 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1310 type Subclass = $subclass;
1311 }
1312 };
1313
1314 (@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty,
1315 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1316 $crate::glib_object_wrapper!(
1317 @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $ffi_name, @ffi_class std::os::raw::c_void,
1318 @type_ $get_type_expr, @requires [$($requires)*]
1319 );
1320 };
1321
1322 (@object_interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $iface:ty,
1323 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1324 $crate::glib_object_wrapper!(
1325 @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $iface, <$iface as $crate::subclass::interface::ObjectInterface>::Instance,
1326 @ffi_class <$iface as $crate::subclass::interface::ObjectInterface>::Interface,
1327 @type_ $get_type_expr, @requires [$($requires)*]
1328 );
1329 };
1330
1331 (@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty,
1332 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1333 $crate::glib_object_wrapper!(
1334 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, (), $ffi_name, $ffi_class_name,
1335 @type_ $get_type_expr
1336 );
1337 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($requires)*);
1338
1339 #[doc(hidden)]
1340 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1341 #[inline]
1342 fn as_ref(&self) -> &$crate::object::Object {
1343 $crate::object::Cast::upcast_ref(self)
1344 }
1345 }
1346
1347 #[doc(hidden)]
1348 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1349 #[inline]
1350 fn borrow(&self) -> &$crate::object::Object {
1351 $crate::object::Cast::upcast_ref(self)
1352 }
1353 }
1354
1355 #[doc(hidden)]
1356 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1357 #[inline]
1358 fn from(v: $name $(<$($generic),+>)?) -> Self {
1359 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1360 }
1361 }
1362
1363 #[doc(hidden)]
1364 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1365
1366 #[doc(hidden)]
1367 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsInterface for $name $(<$($generic),+>)? { }
1368 };
1369}
1370
1371glib_object_wrapper!(@object
1372 [doc = "The base class in the object hierarchy."]
1373 pub Object, *mut std::os::raw::c_void, (), gobject_ffi::GObject, @ffi_class gobject_ffi::GObjectClass, @type_ gobject_ffi::g_object_get_type()
1374);
1375pub type ObjectClass = Class<Object>;
1376
1377impl Object {
1378 pub const NONE: Option<&'static Object> = None;
1379
1380 #[track_caller]
1387 #[allow(clippy::new_ret_no_self)]
1388 pub fn new<T: IsA<Object> + IsClass>() -> T {
1389 let object = Object::with_type(T::static_type());
1390 unsafe { object.unsafe_cast() }
1391 }
1392
1393 #[track_caller]
1400 pub fn with_type(type_: Type) -> Object {
1401 Object::with_mut_values(type_, &mut [])
1402 }
1403
1404 #[track_caller]
1413 pub fn with_mut_values(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1414 #[cfg(feature = "gio")]
1415 unsafe {
1416 let iface_type = from_glib(gio_sys::g_initable_get_type());
1417 if type_.is_a(iface_type) {
1418 panic!("Can't instantiate type '{type_}' implementing `gio::Initable`. Use `gio::Initable::new()`");
1419 }
1420 let iface_type = from_glib(gio_sys::g_async_initable_get_type());
1421 if type_.is_a(iface_type) {
1422 panic!("Can't instantiate type '{type_}' implementing `gio::AsyncInitable`. Use `gio::AsyncInitable::new()`");
1423 }
1424 }
1425
1426 unsafe { Object::new_internal(type_, properties) }
1427 }
1428
1429 #[track_caller]
1441 pub unsafe fn new_internal(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1442 if !type_.is_a(Object::static_type()) {
1443 panic!("Can't instantiate non-GObject type '{type_}'");
1444 }
1445
1446 if gobject_ffi::g_type_test_flags(
1447 type_.into_glib(),
1448 gobject_ffi::G_TYPE_FLAG_INSTANTIATABLE,
1449 ) == ffi::GFALSE
1450 {
1451 panic!("Can't instantiate type '{type_}'");
1452 }
1453
1454 if gobject_ffi::g_type_test_flags(type_.into_glib(), gobject_ffi::G_TYPE_FLAG_ABSTRACT)
1455 != ffi::GFALSE
1456 {
1457 panic!("Can't instantiate abstract type '{type_}'");
1458 }
1459
1460 let mut property_names = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1461 let mut property_values = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1462
1463 if !properties.is_empty() {
1464 let klass = ObjectClass::from_type(type_)
1465 .unwrap_or_else(|| panic!("Can't retrieve class for type '{type_}'"));
1466
1467 for (idx, (name, value)) in properties.iter_mut().enumerate() {
1468 let pspec = klass
1469 .find_property(name)
1470 .unwrap_or_else(|| panic!("Can't find property '{name}' for type '{type_}'"));
1471
1472 if (pspec.flags().contains(crate::ParamFlags::CONSTRUCT)
1473 || pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
1474 && property_names[0..idx]
1475 .iter()
1476 .any(|other_name| pspec.name().as_ptr() == *other_name)
1477 {
1478 panic!("Can't set construct property '{name}' for type '{type_}' twice");
1479 }
1480
1481 validate_property_type(type_, true, &pspec, value);
1485
1486 property_names.push(pspec.name().as_ptr());
1487 property_values.push(*value.to_glib_none().0);
1488 }
1489 }
1490
1491 let ptr = gobject_ffi::g_object_new_with_properties(
1492 type_.into_glib(),
1493 properties.len() as u32,
1494 mut_override(property_names.as_ptr() as *const *const _),
1495 property_values.as_ptr(),
1496 );
1497
1498 if ptr.is_null() {
1499 panic!("Can't instantiate object for type '{type_}'");
1500 } else if type_.is_a(InitiallyUnowned::static_type()) {
1501 from_glib_none(ptr)
1503 } else {
1504 from_glib_full(ptr)
1505 }
1506 }
1507
1508 pub fn builder<'a, O: IsA<Object> + IsClass>() -> ObjectBuilder<'a, O> {
1511 ObjectBuilder::new(O::static_type())
1512 }
1513
1514 pub fn builder_with_type<'a>(type_: Type) -> ObjectBuilder<'a, Object> {
1517 ObjectBuilder::new(type_)
1518 }
1519}
1520
1521#[must_use = "builder doesn't do anything unless built"]
1522pub struct ObjectBuilder<'a, O> {
1523 type_: Type,
1524 properties: smallvec::SmallVec<[(&'a str, Value); 16]>,
1525 phantom: PhantomData<O>,
1526}
1527
1528impl<'a, O: IsA<Object> + IsClass> ObjectBuilder<'a, O> {
1529 #[inline]
1530 fn new(type_: Type) -> Self {
1531 ObjectBuilder {
1532 type_,
1533 properties: smallvec::SmallVec::new(),
1534 phantom: PhantomData,
1535 }
1536 }
1537
1538 #[inline]
1541 pub fn type_(&self) -> Type {
1542 self.type_
1543 }
1544
1545 pub fn property(self, name: &'a str, value: impl Into<Value>) -> Self {
1550 let ObjectBuilder {
1551 type_,
1552 mut properties,
1553 ..
1554 } = self;
1555 properties.push((name, value.into()));
1556
1557 ObjectBuilder {
1558 type_,
1559 properties,
1560 phantom: PhantomData,
1561 }
1562 }
1563
1564 #[inline]
1570 pub fn property_if(self, name: &'a str, value: impl Into<Value>, predicate: bool) -> Self {
1571 if predicate {
1572 self.property(name, value)
1573 } else {
1574 self
1575 }
1576 }
1577
1578 #[inline]
1583 pub fn property_if_some(self, name: &'a str, value: Option<impl Into<Value>>) -> Self {
1584 if let Some(value) = value {
1585 self.property(name, value)
1586 } else {
1587 self
1588 }
1589 }
1590
1591 #[inline]
1596 pub fn property_from_iter<V: ValueType + Into<Value> + FromIterator<Value>>(
1597 self,
1598 name: &'a str,
1599 iter: impl IntoIterator<Item = impl Into<Value>>,
1600 ) -> Self {
1601 let iter = iter.into_iter().map(|item| item.into());
1602 self.property(name, V::from_iter(iter))
1603 }
1604
1605 #[inline]
1611 pub fn property_if_not_empty<V: ValueType + Into<Value> + FromIterator<Value>>(
1612 self,
1613 name: &'a str,
1614 iter: impl IntoIterator<Item = impl Into<Value>>,
1615 ) -> Self {
1616 let mut iter = iter.into_iter().peekable();
1617 if iter.peek().is_some() {
1618 let iter = iter.map(|item| item.into());
1619 self.property(name, V::from_iter(iter))
1620 } else {
1621 self
1622 }
1623 }
1624
1625 #[track_caller]
1633 #[inline]
1634 pub fn build(mut self) -> O {
1635 let object = Object::with_mut_values(self.type_, &mut self.properties);
1636 unsafe { object.unsafe_cast::<O>() }
1637 }
1638}
1639
1640#[must_use = "if unused the property notifications will immediately be thawed"]
1641pub struct PropertyNotificationFreezeGuard(ObjectRef);
1642
1643impl Drop for PropertyNotificationFreezeGuard {
1644 #[doc(alias = "g_object_thaw_notify")]
1645 #[inline]
1646 fn drop(&mut self) {
1647 unsafe { gobject_ffi::g_object_thaw_notify(self.0.to_glib_none().0) }
1648 }
1649}
1650
1651pub trait ObjectExt: ObjectType {
1652 fn is<T: StaticType>(&self) -> bool;
1655
1656 #[doc(alias = "get_type")]
1659 fn type_(&self) -> Type;
1660
1661 #[doc(alias = "get_object_class")]
1666 fn object_class(&self) -> &ObjectClass;
1667
1668 #[doc(alias = "get_class")]
1670 fn class(&self) -> &Class<Self>
1671 where
1672 Self: IsClass;
1673
1674 #[doc(alias = "get_class_of")]
1679 fn class_of<T: IsClass>(&self) -> Option<&Class<T>>;
1680
1681 #[doc(alias = "get_interface")]
1686 fn interface<T: IsInterface>(&self) -> Option<InterfaceRef<T>>;
1687
1688 #[doc(alias = "g_object_set_property")]
1696 fn set_property(&self, property_name: &str, value: impl Into<Value>);
1697
1698 #[doc(alias = "g_object_set_property")]
1706 fn set_property_from_value(&self, property_name: &str, value: &Value);
1707
1708 #[doc(alias = "g_object_set")]
1716 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]);
1717
1718 #[doc(alias = "g_object_set")]
1726 fn set_properties_from_value(&self, property_values: &[(&str, Value)]);
1727
1728 #[doc(alias = "get_property")]
1735 #[doc(alias = "g_object_get_property")]
1736 fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V;
1737
1738 #[doc(alias = "get_property")]
1745 #[doc(alias = "g_object_get_property")]
1746 fn property_value(&self, property_name: &str) -> Value;
1747
1748 fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool;
1753
1754 #[doc(alias = "get_property_type")]
1759 fn property_type(&self, property_name: &str) -> Option<Type>;
1760
1761 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec>;
1764
1765 fn list_properties(&self) -> PtrSlice<crate::ParamSpec>;
1768
1769 #[doc(alias = "g_object_freeze_notify")]
1774 fn freeze_notify(&self) -> PropertyNotificationFreezeGuard;
1775
1776 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD);
1783
1784 #[doc(alias = "get_qdata")]
1794 unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>>;
1795
1796 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>;
1805
1806 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD);
1813
1814 #[doc(alias = "get_data")]
1824 unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>>;
1825
1826 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD>;
1835
1836 #[doc(alias = "g_signal_handler_block")]
1841 fn block_signal(&self, handler_id: &SignalHandlerId);
1842
1843 #[doc(alias = "g_signal_handler_unblock")]
1846 fn unblock_signal(&self, handler_id: &SignalHandlerId);
1847
1848 #[doc(alias = "g_signal_stop_emission")]
1851 fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>);
1852
1853 #[doc(alias = "g_signal_stop_emission_by_name")]
1856 fn stop_signal_emission_by_name(&self, signal_name: &str);
1857
1858 fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1868 where
1869 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1870
1871 fn connect_id<F>(
1883 &self,
1884 signal_id: SignalId,
1885 details: Option<Quark>,
1886 after: bool,
1887 callback: F,
1888 ) -> SignalHandlerId
1889 where
1890 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1891
1892 fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1905 where
1906 F: Fn(&[Value]) -> Option<Value> + 'static;
1907
1908 fn connect_local_id<F>(
1921 &self,
1922 signal_id: SignalId,
1923 details: Option<Quark>,
1924 after: bool,
1925 callback: F,
1926 ) -> SignalHandlerId
1927 where
1928 F: Fn(&[Value]) -> Option<Value> + 'static;
1929
1930 unsafe fn connect_unsafe<F>(
1948 &self,
1949 signal_name: &str,
1950 after: bool,
1951 callback: F,
1952 ) -> SignalHandlerId
1953 where
1954 F: Fn(&[Value]) -> Option<Value>;
1955
1956 unsafe fn connect_unsafe_id<F>(
1975 &self,
1976 signal_id: SignalId,
1977 details: Option<Quark>,
1978 after: bool,
1979 callback: F,
1980 ) -> SignalHandlerId
1981 where
1982 F: Fn(&[Value]) -> Option<Value>;
1983
1984 #[doc(alias = "g_signal_connect_closure")]
1999 #[doc(alias = "g_signal_connect_object")]
2000 fn connect_closure(
2001 &self,
2002 signal_name: &str,
2003 after: bool,
2004 closure: RustClosure,
2005 ) -> SignalHandlerId;
2006
2007 #[doc(alias = "g_signal_connect_closure_by_id")]
2018 fn connect_closure_id(
2019 &self,
2020 signal_id: SignalId,
2021 details: Option<Quark>,
2022 after: bool,
2023 closure: RustClosure,
2024 ) -> SignalHandlerId;
2025
2026 #[doc(alias = "g_object_watch_closure")]
2033 fn watch_closure(&self, closure: &impl AsRef<Closure>);
2034
2035 #[doc(alias = "g_signal_emitv")]
2045 fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R;
2046
2047 fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value>;
2050
2051 #[doc(alias = "g_signal_emit_by_name")]
2061 fn emit_by_name<R: TryFromClosureReturnValue>(
2062 &self,
2063 signal_name: &str,
2064 args: &[&dyn ToValue],
2065 ) -> R;
2066
2067 fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value>;
2077
2078 fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2088 &self,
2089 signal_name: &str,
2090 details: Quark,
2091 args: &[&dyn ToValue],
2092 ) -> R;
2093
2094 fn emit_by_name_with_details_and_values(
2104 &self,
2105 signal_name: &str,
2106 details: Quark,
2107 args: &[Value],
2108 ) -> Option<Value>;
2109
2110 fn emit_with_details<R: TryFromClosureReturnValue>(
2120 &self,
2121 signal_id: SignalId,
2122 details: Quark,
2123 args: &[&dyn ToValue],
2124 ) -> R;
2125
2126 fn emit_with_details_and_values(
2136 &self,
2137 signal_id: SignalId,
2138 details: Quark,
2139 args: &[Value],
2140 ) -> Option<Value>;
2141
2142 #[doc(alias = "g_signal_handler_disconnect")]
2145 fn disconnect(&self, handler_id: SignalHandlerId);
2146
2147 fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
2153 &self,
2154 name: Option<&str>,
2155 f: F,
2156 ) -> SignalHandlerId;
2157
2158 fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
2167 &self,
2168 name: Option<&str>,
2169 f: F,
2170 ) -> SignalHandlerId;
2171
2172 unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
2186 &self,
2187 name: Option<&str>,
2188 f: F,
2189 ) -> SignalHandlerId;
2190
2191 #[doc(alias = "g_object_notify")]
2196 fn notify(&self, property_name: &str);
2197
2198 #[doc(alias = "g_object_notify_by_pspec")]
2203 fn notify_by_pspec(&self, pspec: &crate::ParamSpec);
2204
2205 fn downgrade(&self) -> WeakRef<Self>;
2208
2209 #[doc(alias = "g_object_weak_ref")]
2212 #[doc(alias = "connect_drop")]
2213 fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2214
2215 #[doc(alias = "g_object_weak_ref")]
2221 #[doc(alias = "connect_drop")]
2222 fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2223
2224 fn bind_property<'a, 'f, 't, O: ObjectType>(
2232 &'a self,
2233 source_property: &'a str,
2234 target: &'a O,
2235 target_property: &'a str,
2236 ) -> BindingBuilder<'a, 'f, 't>;
2237
2238 fn ref_count(&self) -> u32;
2241
2242 #[doc(alias = "g_object_run_dispose")]
2254 unsafe fn run_dispose(&self);
2255}
2256
2257impl<T: ObjectType> ObjectExt for T {
2258 #[inline]
2259 fn is<U: StaticType>(&self) -> bool {
2260 self.type_().is_a(U::static_type())
2261 }
2262
2263 #[inline]
2264 fn type_(&self) -> Type {
2265 self.object_class().type_()
2266 }
2267
2268 #[inline]
2269 fn object_class(&self) -> &ObjectClass {
2270 unsafe {
2271 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2272 let klass = (*obj).g_type_instance.g_class as *const ObjectClass;
2273 &*klass
2274 }
2275 }
2276
2277 #[inline]
2278 fn class(&self) -> &Class<Self>
2279 where
2280 Self: IsClass,
2281 {
2282 unsafe {
2283 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2284 let klass = (*obj).g_type_instance.g_class as *const Class<Self>;
2285 &*klass
2286 }
2287 }
2288
2289 #[inline]
2290 fn class_of<U: IsClass>(&self) -> Option<&Class<U>> {
2291 if !self.is::<U>() {
2292 return None;
2293 }
2294
2295 unsafe {
2296 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2297 let klass = (*obj).g_type_instance.g_class as *const Class<U>;
2298 Some(&*klass)
2299 }
2300 }
2301
2302 #[inline]
2303 fn interface<U: IsInterface>(&self) -> Option<InterfaceRef<U>> {
2304 Interface::from_class(self.object_class())
2305 }
2306
2307 #[track_caller]
2308 fn set_property(&self, property_name: &str, value: impl Into<Value>) {
2309 let pspec = self.find_property(property_name).unwrap_or_else(|| {
2310 panic!(
2311 "property '{property_name}' of type '{}' not found",
2312 self.type_()
2313 )
2314 });
2315
2316 let mut property_value = value.into();
2317 validate_property_type(self.type_(), false, &pspec, &mut property_value);
2318 unsafe {
2319 gobject_ffi::g_object_set_property(
2320 self.as_object_ref().to_glib_none().0,
2321 pspec.name().as_ptr() as *const _,
2322 property_value.to_glib_none().0,
2323 );
2324 }
2325 }
2326
2327 #[track_caller]
2328 fn set_property_from_value(&self, property_name: &str, value: &Value) {
2329 let pspec = match self.find_property(property_name) {
2330 Some(pspec) => pspec,
2331 None => {
2332 panic!(
2333 "property '{property_name}' of type '{}' not found",
2334 self.type_()
2335 );
2336 }
2337 };
2338
2339 let mut property_value = value.clone();
2343 validate_property_type(self.type_(), false, &pspec, &mut property_value);
2344 unsafe {
2345 gobject_ffi::g_object_set_property(
2346 self.as_object_ref().to_glib_none().0,
2347 pspec.name().as_ptr() as *const _,
2348 property_value.to_glib_none().0,
2349 );
2350 }
2351 }
2352
2353 #[track_caller]
2354 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]) {
2355 let params = property_values
2356 .iter()
2357 .map(|&(name, value)| {
2358 let pspec = self.find_property(name).unwrap_or_else(|| {
2359 panic!("Can't find property '{name}' for type '{}'", self.type_());
2360 });
2361
2362 let mut value = value.to_value();
2363 validate_property_type(self.type_(), false, &pspec, &mut value);
2364 (pspec.name().as_ptr(), value)
2365 })
2366 .collect::<smallvec::SmallVec<[_; 10]>>();
2367
2368 let _guard = self.freeze_notify();
2369 for (name, value) in params {
2370 unsafe {
2371 gobject_ffi::g_object_set_property(
2372 self.as_object_ref().to_glib_none().0,
2373 name as *const _,
2374 value.to_glib_none().0,
2375 );
2376 }
2377 }
2378 }
2379
2380 #[track_caller]
2381 fn set_properties_from_value(&self, property_values: &[(&str, Value)]) {
2382 let params = property_values
2383 .iter()
2384 .map(|(name, value)| {
2385 let pspec = self.find_property(name).unwrap_or_else(|| {
2386 panic!("Can't find property '{name}' for type '{}'", self.type_());
2387 });
2388
2389 let mut value = value.clone();
2390 validate_property_type(self.type_(), false, &pspec, &mut value);
2391 (pspec.name().as_ptr(), value)
2392 })
2393 .collect::<smallvec::SmallVec<[_; 10]>>();
2394
2395 let _guard = self.freeze_notify();
2396 for (name, value) in params {
2397 unsafe {
2398 gobject_ffi::g_object_set_property(
2399 self.as_object_ref().to_glib_none().0,
2400 name as *const _,
2401 value.to_glib_none().0,
2402 );
2403 }
2404 }
2405 }
2406
2407 #[track_caller]
2408 fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V {
2409 let prop = self.property_value(property_name);
2410 let v = prop
2411 .get_owned::<V>()
2412 .unwrap_or_else(|e| panic!("Failed to get cast value to a different type {e}"));
2413
2414 v
2415 }
2416
2417 #[track_caller]
2418 fn property_value(&self, property_name: &str) -> Value {
2419 let pspec = self.find_property(property_name).unwrap_or_else(|| {
2420 panic!(
2421 "property '{property_name}' of type '{}' not found",
2422 self.type_()
2423 )
2424 });
2425
2426 if !pspec.flags().contains(crate::ParamFlags::READABLE) {
2427 panic!(
2428 "property '{property_name}' of type '{}' is not readable",
2429 self.type_()
2430 );
2431 }
2432
2433 unsafe {
2434 let mut value = Value::from_type_unchecked(pspec.value_type());
2435 gobject_ffi::g_object_get_property(
2436 self.as_object_ref().to_glib_none().0,
2437 pspec.name().as_ptr() as *const _,
2438 value.to_glib_none_mut().0,
2439 );
2440
2441 if !value.type_().is_valid() {
2443 panic!(
2444 "Failed to get property value for property '{property_name}' of type '{}'",
2445 self.type_()
2446 )
2447 }
2448
2449 value
2450 }
2451 }
2452
2453 fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool {
2454 self.object_class().has_property(property_name, type_)
2455 }
2456
2457 fn property_type(&self, property_name: &str) -> Option<Type> {
2458 self.object_class().property_type(property_name)
2459 }
2460
2461 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
2462 self.object_class().find_property(property_name)
2463 }
2464
2465 fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
2466 self.object_class().list_properties()
2467 }
2468
2469 #[inline]
2470 fn freeze_notify(&self) -> PropertyNotificationFreezeGuard {
2471 unsafe { gobject_ffi::g_object_freeze_notify(self.as_object_ref().to_glib_none().0) };
2472 PropertyNotificationFreezeGuard(self.as_object_ref().clone())
2473 }
2474
2475 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD) {
2476 unsafe extern "C" fn drop_value<QD>(ptr: ffi::gpointer) {
2477 debug_assert!(!ptr.is_null());
2478 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2479 drop(value)
2480 }
2481
2482 let ptr = Box::into_raw(Box::new(value)) as ffi::gpointer;
2483 gobject_ffi::g_object_set_qdata_full(
2484 self.as_object_ref().to_glib_none().0,
2485 key.into_glib(),
2486 ptr,
2487 Some(drop_value::<QD>),
2488 );
2489 }
2490
2491 unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>> {
2492 ptr::NonNull::new(gobject_ffi::g_object_get_qdata(
2493 self.as_object_ref().to_glib_none().0,
2494 key.into_glib(),
2495 ) as *mut QD)
2496 }
2497
2498 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD> {
2499 let ptr = gobject_ffi::g_object_steal_qdata(
2500 self.as_object_ref().to_glib_none().0,
2501 key.into_glib(),
2502 );
2503 if ptr.is_null() {
2504 None
2505 } else {
2506 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2507 Some(*value)
2508 }
2509 }
2510
2511 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD) {
2512 self.set_qdata::<QD>(Quark::from_str(key), value)
2513 }
2514
2515 unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>> {
2516 self.qdata::<QD>(Quark::from_str(key))
2517 }
2518
2519 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD> {
2520 self.steal_qdata::<QD>(Quark::from_str(key))
2521 }
2522
2523 fn block_signal(&self, handler_id: &SignalHandlerId) {
2524 unsafe {
2525 gobject_ffi::g_signal_handler_block(
2526 self.as_object_ref().to_glib_none().0,
2527 handler_id.as_raw(),
2528 );
2529 }
2530 }
2531
2532 fn unblock_signal(&self, handler_id: &SignalHandlerId) {
2533 unsafe {
2534 gobject_ffi::g_signal_handler_unblock(
2535 self.as_object_ref().to_glib_none().0,
2536 handler_id.as_raw(),
2537 );
2538 }
2539 }
2540
2541 fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>) {
2542 unsafe {
2543 gobject_ffi::g_signal_stop_emission(
2544 self.as_object_ref().to_glib_none().0,
2545 signal_id.into_glib(),
2546 detail.into_glib(),
2547 );
2548 }
2549 }
2550
2551 fn stop_signal_emission_by_name(&self, signal_name: &str) {
2552 unsafe {
2553 signal_name.run_with_gstr(|signal_name| {
2554 gobject_ffi::g_signal_stop_emission_by_name(
2555 self.as_object_ref().to_glib_none().0,
2556 signal_name.as_ptr(),
2557 )
2558 });
2559 }
2560 }
2561
2562 #[track_caller]
2563 fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2564 where
2565 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2566 {
2567 unsafe { self.connect_unsafe(signal_name, after, callback) }
2568 }
2569
2570 #[track_caller]
2571 fn connect_id<F>(
2572 &self,
2573 signal_id: SignalId,
2574 details: Option<Quark>,
2575 after: bool,
2576 callback: F,
2577 ) -> SignalHandlerId
2578 where
2579 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2580 {
2581 unsafe { self.connect_unsafe_id(signal_id, details, after, callback) }
2582 }
2583
2584 #[track_caller]
2585 fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2586 where
2587 F: Fn(&[Value]) -> Option<Value> + 'static,
2588 {
2589 let callback = crate::thread_guard::ThreadGuard::new(callback);
2590
2591 unsafe {
2592 self.connect_unsafe(signal_name, after, move |values| {
2593 (callback.get_ref())(values)
2594 })
2595 }
2596 }
2597
2598 #[track_caller]
2599 fn connect_local_id<F>(
2600 &self,
2601 signal_id: SignalId,
2602 details: Option<Quark>,
2603 after: bool,
2604 callback: F,
2605 ) -> SignalHandlerId
2606 where
2607 F: Fn(&[Value]) -> Option<Value> + 'static,
2608 {
2609 let callback = crate::thread_guard::ThreadGuard::new(callback);
2610
2611 unsafe {
2612 self.connect_unsafe_id(signal_id, details, after, move |values| {
2613 (callback.get_ref())(values)
2614 })
2615 }
2616 }
2617
2618 #[track_caller]
2619 unsafe fn connect_unsafe<F>(
2620 &self,
2621 signal_name: &str,
2622 after: bool,
2623 callback: F,
2624 ) -> SignalHandlerId
2625 where
2626 F: Fn(&[Value]) -> Option<Value>,
2627 {
2628 let type_ = self.type_();
2629 let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2630 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2631 self.connect_unsafe_id(signal_id, details, after, callback)
2632 }
2633
2634 #[track_caller]
2635 unsafe fn connect_unsafe_id<F>(
2636 &self,
2637 signal_id: SignalId,
2638 details: Option<Quark>,
2639 after: bool,
2640 callback: F,
2641 ) -> SignalHandlerId
2642 where
2643 F: Fn(&[Value]) -> Option<Value>,
2644 {
2645 let signal_query = signal_id.query();
2646 let type_ = self.type_();
2647 let return_type: Type = signal_query.return_type().into();
2648 let signal_name = signal_id.name();
2649 let signal_query_type = signal_query.type_();
2650
2651 let closure = if return_type == Type::UNIT {
2652 Closure::new_unsafe(move |values| {
2653 let ret = callback(values);
2654 if let Some(ret) = ret {
2655 panic!(
2656 "Signal '{signal_name}' of type '{type_}' required no return value but got value of type '{}'",
2657 ret.type_()
2658 );
2659 }
2660 None
2661 })
2662 } else {
2663 Closure::new_unsafe(move |values| {
2664 let mut ret = callback(values).unwrap_or_else(|| {
2665 panic!(
2666 "Signal '{signal_name}' of type '{type_}' required return value of type '{}' but got None",
2667 return_type.name()
2668 );
2669 });
2670 let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
2671 mut_override(ret.to_glib_none().0),
2672 return_type.into_glib(),
2673 ));
2674
2675 if valid_type {
2676 return Some(ret);
2677 }
2678
2679 if let Err(got) = coerce_object_type(&mut ret, return_type) {
2680 panic!(
2681 "Signal '{signal_name}' of type '{type_}' required return value of type '{return_type}' but got '{got}'",
2682 );
2683 };
2684 Some(ret)
2685 })
2686 };
2687
2688 assert!(
2689 type_.is_a(signal_query_type),
2690 "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2691 );
2692
2693 let handler = gobject_ffi::g_signal_connect_closure_by_id(
2694 self.as_object_ref().to_glib_none().0,
2695 signal_id.into_glib(),
2696 details.into_glib(),
2697 closure.as_ref().to_glib_none().0,
2698 after.into_glib(),
2699 );
2700
2701 if handler == 0 {
2702 panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2703 }
2704
2705 from_glib(handler)
2706 }
2707
2708 #[track_caller]
2709 fn connect_closure(
2710 &self,
2711 signal_name: &str,
2712 after: bool,
2713 closure: RustClosure,
2714 ) -> SignalHandlerId {
2715 let type_ = self.type_();
2716 let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2717 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2718 self.connect_closure_id(signal_id, details, after, closure)
2719 }
2720
2721 #[track_caller]
2722 fn connect_closure_id(
2723 &self,
2724 signal_id: SignalId,
2725 details: Option<Quark>,
2726 after: bool,
2727 closure: RustClosure,
2728 ) -> SignalHandlerId {
2729 let signal_query = signal_id.query();
2730 let type_ = self.type_();
2731 let signal_name = signal_id.name();
2732
2733 let signal_query_type = signal_query.type_();
2734 assert!(
2735 type_.is_a(signal_query_type),
2736 "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2737 );
2738
2739 unsafe {
2740 let handler = gobject_ffi::g_signal_connect_closure_by_id(
2741 self.as_object_ref().to_glib_none().0,
2742 signal_id.into_glib(),
2743 details.into_glib(),
2744 closure.as_ref().to_glib_none().0,
2745 after.into_glib(),
2746 );
2747
2748 if handler == 0 {
2749 panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2750 }
2751
2752 from_glib(handler)
2753 }
2754 }
2755
2756 #[inline]
2757 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
2758 let closure = closure.as_ref();
2759 unsafe {
2760 gobject_ffi::g_object_watch_closure(
2761 self.as_object_ref().to_glib_none().0,
2762 closure.to_glib_none().0,
2763 );
2764 }
2765 }
2766
2767 #[track_caller]
2768 fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R {
2769 let signal_query = signal_id.query();
2770 unsafe {
2771 let type_ = self.type_();
2772
2773 let self_v = {
2774 let mut v = Value::uninitialized();
2775 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2776 gobject_ffi::g_value_set_object(
2777 v.to_glib_none_mut().0,
2778 self.as_object_ref().to_glib_none().0,
2779 );
2780 v
2781 };
2782
2783 let mut args = Iterator::chain(
2784 std::iter::once(self_v),
2785 args.iter().copied().map(ToValue::to_value),
2786 )
2787 .collect::<smallvec::SmallVec<[_; 10]>>();
2788
2789 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2790
2791 let mut return_value = if signal_query.return_type() != Type::UNIT {
2792 Value::from_type_unchecked(signal_query.return_type().into())
2793 } else {
2794 Value::uninitialized()
2795 };
2796 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2797 return_value.to_glib_none_mut().0
2798 } else {
2799 ptr::null_mut()
2800 };
2801
2802 gobject_ffi::g_signal_emitv(
2803 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2804 signal_id.into_glib(),
2805 0,
2806 return_value_ptr,
2807 );
2808
2809 R::try_from_closure_return_value(
2810 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2811 )
2812 .unwrap()
2813 }
2814 }
2815
2816 #[track_caller]
2817 fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value> {
2818 unsafe {
2819 let type_ = self.type_();
2820
2821 let signal_query = signal_id.query();
2822
2823 let self_v = {
2824 let mut v = Value::uninitialized();
2825 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2826 gobject_ffi::g_value_set_object(
2827 v.to_glib_none_mut().0,
2828 self.as_object_ref().to_glib_none().0,
2829 );
2830 v
2831 };
2832
2833 let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
2834 .collect::<smallvec::SmallVec<[_; 10]>>();
2835
2836 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2837
2838 let mut return_value = if signal_query.return_type() != Type::UNIT {
2839 Value::from_type_unchecked(signal_query.return_type().into())
2840 } else {
2841 Value::uninitialized()
2842 };
2843 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2844 return_value.to_glib_none_mut().0
2845 } else {
2846 ptr::null_mut()
2847 };
2848
2849 gobject_ffi::g_signal_emitv(
2850 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2851 signal_id.into_glib(),
2852 0,
2853 return_value_ptr,
2854 );
2855
2856 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
2857 }
2858 }
2859
2860 #[track_caller]
2861 fn emit_by_name<R: TryFromClosureReturnValue>(
2862 &self,
2863 signal_name: &str,
2864 args: &[&dyn ToValue],
2865 ) -> R {
2866 let type_ = self.type_();
2867 let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2868 panic!("Signal '{signal_name}' of type '{type_}' not found");
2869 });
2870 self.emit(signal_id, args)
2871 }
2872
2873 #[track_caller]
2874 fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value> {
2875 let type_ = self.type_();
2876 let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2877 panic!("Signal '{signal_name}' of type '{type_}' not found");
2878 });
2879 self.emit_with_values(signal_id, args)
2880 }
2881
2882 #[track_caller]
2883 fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2884 &self,
2885 signal_name: &str,
2886 details: Quark,
2887 args: &[&dyn ToValue],
2888 ) -> R {
2889 let type_ = self.type_();
2890 let signal_id = SignalId::lookup(signal_name, type_)
2891 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2892 self.emit_with_details(signal_id, details, args)
2893 }
2894
2895 #[track_caller]
2896 fn emit_by_name_with_details_and_values(
2897 &self,
2898 signal_name: &str,
2899 details: Quark,
2900 args: &[Value],
2901 ) -> Option<Value> {
2902 let type_ = self.type_();
2903 let signal_id = SignalId::lookup(signal_name, type_)
2904 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2905 self.emit_with_details_and_values(signal_id, details, args)
2906 }
2907
2908 #[track_caller]
2909 fn emit_with_details<R: TryFromClosureReturnValue>(
2910 &self,
2911 signal_id: SignalId,
2912 details: Quark,
2913 args: &[&dyn ToValue],
2914 ) -> R {
2915 let signal_query = signal_id.query();
2916 assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2917
2918 unsafe {
2919 let type_ = self.type_();
2920
2921 let self_v = {
2922 let mut v = Value::uninitialized();
2923 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2924 gobject_ffi::g_value_set_object(
2925 v.to_glib_none_mut().0,
2926 self.as_object_ref().to_glib_none().0,
2927 );
2928 v
2929 };
2930
2931 let mut args = Iterator::chain(
2932 std::iter::once(self_v),
2933 args.iter().copied().map(ToValue::to_value),
2934 )
2935 .collect::<smallvec::SmallVec<[_; 10]>>();
2936
2937 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2938
2939 let mut return_value = if signal_query.return_type() != Type::UNIT {
2940 Value::from_type_unchecked(signal_query.return_type().into())
2941 } else {
2942 Value::uninitialized()
2943 };
2944 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2945 return_value.to_glib_none_mut().0
2946 } else {
2947 ptr::null_mut()
2948 };
2949
2950 gobject_ffi::g_signal_emitv(
2951 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2952 signal_id.into_glib(),
2953 details.into_glib(),
2954 return_value_ptr,
2955 );
2956
2957 R::try_from_closure_return_value(
2958 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2959 )
2960 .unwrap()
2961 }
2962 }
2963
2964 #[track_caller]
2965 fn emit_with_details_and_values(
2966 &self,
2967 signal_id: SignalId,
2968 details: Quark,
2969 args: &[Value],
2970 ) -> Option<Value> {
2971 let signal_query = signal_id.query();
2972 assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2973
2974 unsafe {
2975 let type_ = self.type_();
2976
2977 let self_v = {
2978 let mut v = Value::uninitialized();
2979 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2980 gobject_ffi::g_value_set_object(
2981 v.to_glib_none_mut().0,
2982 self.as_object_ref().to_glib_none().0,
2983 );
2984 v
2985 };
2986
2987 let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
2988 .collect::<smallvec::SmallVec<[_; 10]>>();
2989
2990 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2991
2992 let mut return_value = if signal_query.return_type() != Type::UNIT {
2993 Value::from_type_unchecked(signal_query.return_type().into())
2994 } else {
2995 Value::uninitialized()
2996 };
2997 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2998 return_value.to_glib_none_mut().0
2999 } else {
3000 ptr::null_mut()
3001 };
3002
3003 gobject_ffi::g_signal_emitv(
3004 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
3005 signal_id.into_glib(),
3006 details.into_glib(),
3007 return_value_ptr,
3008 );
3009
3010 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
3011 }
3012 }
3013
3014 #[inline]
3015 fn disconnect(&self, handler_id: SignalHandlerId) {
3016 unsafe {
3017 gobject_ffi::g_signal_handler_disconnect(
3018 self.as_object_ref().to_glib_none().0,
3019 handler_id.as_raw(),
3020 );
3021 }
3022 }
3023
3024 fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
3025 &self,
3026 name: Option<&str>,
3027 f: F,
3028 ) -> SignalHandlerId {
3029 unsafe { self.connect_notify_unsafe(name, f) }
3030 }
3031
3032 fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
3033 &self,
3034 name: Option<&str>,
3035 f: F,
3036 ) -> SignalHandlerId {
3037 let f = crate::thread_guard::ThreadGuard::new(f);
3038
3039 unsafe {
3040 self.connect_notify_unsafe(name, move |s, pspec| {
3041 (f.get_ref())(s, pspec);
3042 })
3043 }
3044 }
3045
3046 unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
3047 &self,
3048 name: Option<&str>,
3049 f: F,
3050 ) -> SignalHandlerId {
3051 unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &crate::ParamSpec)>(
3052 this: *mut gobject_ffi::GObject,
3053 param_spec: *mut gobject_ffi::GParamSpec,
3054 f: ffi::gpointer,
3055 ) where
3056 P: ObjectType,
3057 {
3058 let f: &F = &*(f as *const F);
3059 f(
3060 Object::from_glib_borrow(this).unsafe_cast_ref(),
3061 &from_glib_borrow(param_spec),
3062 )
3063 }
3064
3065 let signal_name = if let Some(name) = name {
3066 format!("notify::{name}\0")
3067 } else {
3068 "notify\0".into()
3069 };
3070
3071 let f: Box<F> = Box::new(f);
3072 crate::signal::connect_raw(
3073 self.as_object_ref().to_glib_none().0,
3074 signal_name.as_ptr() as *const _,
3075 Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
3076 notify_trampoline::<Self, F> as *const (),
3077 )),
3078 Box::into_raw(f),
3079 )
3080 }
3081
3082 #[inline]
3083 fn notify(&self, property_name: &str) {
3084 unsafe {
3085 property_name.run_with_gstr(|property_name| {
3086 gobject_ffi::g_object_notify(
3087 self.as_object_ref().to_glib_none().0,
3088 property_name.as_ptr(),
3089 )
3090 });
3091 }
3092 }
3093
3094 #[inline]
3095 fn notify_by_pspec(&self, pspec: &crate::ParamSpec) {
3096 unsafe {
3097 gobject_ffi::g_object_notify_by_pspec(
3098 self.as_object_ref().to_glib_none().0,
3099 pspec.to_glib_none().0,
3100 );
3101 }
3102 }
3103
3104 #[inline]
3105 fn downgrade(&self) -> WeakRef<T> {
3106 unsafe {
3107 let w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3108 gobject_ffi::g_weak_ref_init(
3109 mut_override(&*w.0),
3110 self.as_object_ref().to_glib_none().0,
3111 );
3112 w
3113 }
3114 }
3115
3116 fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<T> {
3117 WeakRefNotify::new(self, f)
3118 }
3119
3120 fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<T> {
3121 let callback = crate::thread_guard::ThreadGuard::new(f);
3122
3123 WeakRefNotify::new(self, move || callback.into_inner()())
3124 }
3125
3126 fn bind_property<'a, 'f, 't, O: ObjectType>(
3127 &'a self,
3128 source_property: &'a str,
3129 target: &'a O,
3130 target_property: &'a str,
3131 ) -> BindingBuilder<'a, 'f, 't> {
3132 BindingBuilder::new(self, source_property, target, target_property)
3133 }
3134
3135 #[inline]
3136 fn ref_count(&self) -> u32 {
3137 let stash = self.as_object_ref().to_glib_none();
3138 let ptr: *mut gobject_ffi::GObject = stash.0;
3139
3140 unsafe { ffi::g_atomic_int_get(&(*ptr).ref_count as *const u32 as *const i32) as u32 }
3141 }
3142
3143 #[inline]
3144 unsafe fn run_dispose(&self) {
3145 gobject_ffi::g_object_run_dispose(self.as_ptr() as *mut _);
3146 }
3147}
3148
3149#[doc(hidden)]
3152pub struct WatchedObject<T: ObjectType>(ptr::NonNull<T::GlibType>);
3153
3154#[doc(hidden)]
3155unsafe impl<T: ObjectType + Send + Sync> Send for WatchedObject<T> {}
3156
3157#[doc(hidden)]
3158unsafe impl<T: ObjectType + Send + Sync> Sync for WatchedObject<T> {}
3159
3160#[doc(hidden)]
3161impl<T: ObjectType> WatchedObject<T> {
3162 pub fn new(obj: &T) -> Self {
3163 Self(unsafe { ptr::NonNull::new_unchecked(obj.as_ptr()) })
3164 }
3165 #[inline]
3171 pub unsafe fn borrow(&self) -> Borrowed<T>
3172 where
3173 T: FromGlibPtrBorrow<*mut <T as ObjectType>::GlibType>,
3174 {
3175 from_glib_borrow(self.0.as_ptr())
3176 }
3177}
3178
3179#[doc(hidden)]
3180pub trait Watchable<T: ObjectType> {
3181 fn watched_object(&self) -> WatchedObject<T>;
3182 fn watch_closure(&self, closure: &impl AsRef<Closure>);
3183}
3184
3185#[doc(hidden)]
3186impl<T: ObjectType> Watchable<T> for T {
3187 fn watched_object(&self) -> WatchedObject<T> {
3188 WatchedObject::new(self)
3189 }
3190 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3191 ObjectExt::watch_closure(self, closure)
3192 }
3193}
3194
3195#[doc(hidden)]
3196impl<T: ObjectType> Watchable<T> for BorrowedObject<'_, T> {
3197 fn watched_object(&self) -> WatchedObject<T> {
3198 WatchedObject::new(self)
3199 }
3200 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3201 ObjectExt::watch_closure(&**self, closure)
3202 }
3203}
3204
3205#[doc(hidden)]
3206impl<T: ObjectType> Watchable<T> for &T {
3207 fn watched_object(&self) -> WatchedObject<T> {
3208 WatchedObject::new(*self)
3209 }
3210 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3211 ObjectExt::watch_closure(*self, closure)
3212 }
3213}
3214
3215#[track_caller]
3218fn validate_property_type(
3219 type_: Type,
3220 allow_construct_only: bool,
3221 pspec: &crate::ParamSpec,
3222 property_value: &mut Value,
3223) {
3224 if !pspec.flags().contains(crate::ParamFlags::WRITABLE)
3225 || (!allow_construct_only && pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
3226 {
3227 panic!(
3228 "property '{}' of type '{type_}' is not writable",
3229 pspec.name(),
3230 );
3231 }
3232
3233 unsafe {
3234 let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
3239 mut_override(property_value.to_glib_none().0),
3240 pspec.value_type().into_glib(),
3241 ));
3242
3243 if !valid_type {
3244 if let Err(got) = coerce_object_type(property_value, pspec.value_type()) {
3245 panic!(
3246 "property '{}' of type '{type_}' can't be set from the given type (expected: '{}', got: '{got}')",
3247 pspec.name(),
3248 pspec.value_type(),
3249 );
3250 }
3251 }
3252
3253 let changed: bool = from_glib(gobject_ffi::g_param_value_validate(
3254 pspec.to_glib_none().0,
3255 property_value.to_glib_none_mut().0,
3256 ));
3257 let change_allowed = pspec.flags().contains(crate::ParamFlags::LAX_VALIDATION);
3258 if changed && !change_allowed {
3259 panic!(
3260 "property '{}' of type '{type_}' can't be set from given value, it is invalid or out of range",
3261 pspec.name(),
3262 );
3263 }
3264 }
3265}
3266
3267fn coerce_object_type(property_value: &mut Value, type_: Type) -> Result<(), Type> {
3273 match property_value.get::<Option<Object>>() {
3275 Ok(Some(obj)) if !(obj.type_().is_a(type_)) => Err(obj.type_()),
3276 Ok(_) => {
3277 property_value.inner.g_type = type_.into_glib();
3278 Ok(())
3279 }
3280 Err(_) => Err(property_value.type_()),
3281 }
3282}
3283
3284#[track_caller]
3285fn validate_signal_arguments(type_: Type, signal_query: &SignalQuery, args: &mut [Value]) {
3286 let signal_name = signal_query.signal_name();
3287
3288 if signal_query.n_params() != args.len() as u32 {
3289 panic!(
3290 "Incompatible number of arguments for signal '{signal_name}' of type '{type_}' (expected {}, got {})",
3291 signal_query.n_params(),
3292 args.len(),
3293 );
3294 }
3295
3296 let param_types = Iterator::zip(args.iter_mut(), signal_query.param_types());
3297
3298 for (i, (arg, param_type)) in param_types.enumerate() {
3299 let param_type: Type = (*param_type).into();
3300 if param_type != arg.type_() {
3301 coerce_object_type(arg, param_type).unwrap_or_else(|got|
3302 panic!(
3303 "Incompatible argument type in argument {i} for signal '{signal_name}' of type '{type_}' (expected {param_type}, got {got})",
3304 )
3305 );
3306 }
3307 }
3308}
3309
3310pub unsafe trait ObjectClassExt {
3312 fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool {
3317 let ptype = self.property_type(property_name);
3318
3319 match (ptype, type_) {
3320 (None, _) => false,
3321 (Some(_), None) => true,
3322 (Some(ptype), Some(type_)) => ptype == type_,
3323 }
3324 }
3325
3326 #[doc(alias = "get_property_type")]
3331 fn property_type(&self, property_name: &str) -> Option<Type> {
3332 self.find_property(property_name)
3333 .map(|pspec| pspec.value_type())
3334 }
3335
3336 #[doc(alias = "g_object_class_find_property")]
3339 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
3340 unsafe {
3341 let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3342
3343 property_name.run_with_gstr(|property_name| {
3344 from_glib_none(gobject_ffi::g_object_class_find_property(
3345 klass as *mut _,
3346 property_name.as_ptr(),
3347 ))
3348 })
3349 }
3350 }
3351
3352 #[doc(alias = "g_object_class_list_properties")]
3355 fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
3356 unsafe {
3357 let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3358
3359 let mut n_properties = 0;
3360
3361 let props =
3362 gobject_ffi::g_object_class_list_properties(klass as *mut _, &mut n_properties);
3363 PtrSlice::from_glib_container_num(props, n_properties as usize, true)
3364 }
3365 }
3366}
3367
3368unsafe impl<T: ObjectType + IsClass> ObjectClassExt for Class<T> {}
3369
3370wrapper! {
3371 #[doc(alias = "GInitiallyUnowned")]
3372 pub struct InitiallyUnowned(Object<gobject_ffi::GInitiallyUnowned, gobject_ffi::GInitiallyUnownedClass>);
3373
3374 match fn {
3375 type_ => || gobject_ffi::g_initially_unowned_get_type(),
3376 }
3377}
3378
3379type WeakRefNotifyData = ManuallyDrop<Pin<Box<Box<dyn FnOnce() + 'static>>>>;
3384
3385pub struct WeakRefNotify<T: ObjectType> {
3388 object: WeakRef<T>,
3389 data: WeakRefNotifyData,
3390}
3391
3392unsafe extern "C" fn notify_func(data: ffi::gpointer, _obj: *mut gobject_ffi::GObject) {
3393 let callback: Box<Box<dyn FnOnce()>> = Box::from_raw(data as *mut _);
3396
3397 (*callback)()
3400}
3401
3402impl<T: ObjectType> WeakRefNotify<T> {
3403 fn new<F: FnOnce() + 'static>(obj: &T, f: F) -> WeakRefNotify<T> {
3404 let data: WeakRefNotifyData = ManuallyDrop::new(Box::pin(Box::new(f)));
3405 let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&data).get_ref();
3406
3407 unsafe {
3408 gobject_ffi::g_object_weak_ref(
3410 obj.as_ptr() as *mut gobject_ffi::GObject,
3411 Some(notify_func),
3412 data_ptr as *mut _,
3413 );
3414 }
3415
3416 let object = obj.downgrade();
3417
3418 WeakRefNotify { object, data }
3419 }
3420
3421 pub fn upgrade(&self) -> Option<T> {
3426 self.object.upgrade()
3427 }
3428
3429 #[doc(alias = "g_object_weak_unref")]
3430 pub fn disconnect(mut self) {
3431 if let Some(obj) = self.object.upgrade() {
3433 let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&self.data).get_ref();
3434
3435 unsafe {
3436 gobject_ffi::g_object_weak_unref(
3438 obj.as_ptr() as *mut gobject_ffi::GObject,
3439 Some(notify_func),
3440 data_ptr as *mut _,
3441 );
3442
3443 ManuallyDrop::drop(&mut self.data);
3447 }
3448 }
3449 }
3450}
3451
3452#[derive(Debug)]
3455#[doc(alias = "GWeakRef")]
3456pub struct WeakRef<T: ObjectType>(Pin<Box<gobject_ffi::GWeakRef>>, PhantomData<*mut T>);
3457
3458impl<T: ObjectType> WeakRef<T> {
3459 #[inline]
3464 pub fn new() -> WeakRef<T> {
3465 unsafe {
3466 let mut w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3467 gobject_ffi::g_weak_ref_init(
3468 Pin::as_mut(&mut w.0).get_unchecked_mut(),
3469 ptr::null_mut(),
3470 );
3471 w
3472 }
3473 }
3474
3475 #[doc(alias = "g_weak_ref_set")]
3478 #[inline]
3479 pub fn set(&self, obj: Option<&T>) {
3480 unsafe {
3481 gobject_ffi::g_weak_ref_set(
3482 mut_override(Pin::as_ref(&self.0).get_ref()),
3483 obj.map_or(std::ptr::null_mut(), |obj| {
3484 obj.as_object_ref().to_glib_none().0
3485 }),
3486 );
3487 }
3488 }
3489
3490 #[inline]
3496 pub fn upgrade(&self) -> Option<T> {
3497 unsafe {
3498 let ptr = gobject_ffi::g_weak_ref_get(mut_override(Pin::as_ref(&self.0).get_ref()));
3499 if ptr.is_null() {
3500 None
3501 } else {
3502 let obj: Object = from_glib_full(ptr);
3503 Some(T::unsafe_from(obj.into()))
3504 }
3505 }
3506 }
3507}
3508
3509impl<T: ObjectType> Drop for WeakRef<T> {
3510 #[inline]
3511 fn drop(&mut self) {
3512 unsafe {
3513 gobject_ffi::g_weak_ref_clear(Pin::as_mut(&mut self.0).get_unchecked_mut());
3514 }
3515 }
3516}
3517
3518impl<T: ObjectType> Clone for WeakRef<T> {
3519 #[inline]
3520 fn clone(&self) -> Self {
3521 unsafe {
3522 let o = self.upgrade();
3523
3524 let mut c = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3525 gobject_ffi::g_weak_ref_init(
3526 Pin::as_mut(&mut c.0).get_unchecked_mut(),
3527 o.to_glib_none().0 as *mut gobject_ffi::GObject,
3528 );
3529
3530 c
3531 }
3532 }
3533}
3534
3535impl<T: ObjectType> Default for WeakRef<T> {
3536 #[inline]
3537 fn default() -> Self {
3538 Self::new()
3539 }
3540}
3541
3542unsafe impl<T: ObjectType + Sync + Sync> Sync for WeakRef<T> {}
3543unsafe impl<T: ObjectType + Send + Sync> Send for WeakRef<T> {}
3544
3545impl<T: ObjectType> PartialEq for WeakRef<T> {
3546 #[inline]
3547 fn eq(&self, other: &Self) -> bool {
3548 unsafe { self.0.priv_.p == other.0.priv_.p }
3549 }
3550}
3551
3552impl<T: ObjectType> PartialEq<T> for WeakRef<T> {
3553 #[inline]
3554 fn eq(&self, other: &T) -> bool {
3555 unsafe { self.0.priv_.p == other.as_ptr() as *mut std::os::raw::c_void }
3556 }
3557}
3558
3559impl<T: ObjectType> PartialOrd for WeakRef<T> {
3560 #[inline]
3561 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
3562 unsafe { self.0.priv_.p.partial_cmp(&other.0.priv_.p) }
3563 }
3564}
3565
3566#[derive(Debug)]
3574pub struct SendWeakRef<T: ObjectType>(WeakRef<T>, Option<usize>);
3575
3576impl<T: ObjectType> SendWeakRef<T> {
3577 #[inline]
3578 #[deprecated = "Use from() instead. See https://github.com/gtk-rs/gtk-rs-core/issues/1617"]
3579 pub fn new() -> SendWeakRef<T> {
3580 SendWeakRef(WeakRef::new(), None)
3581 }
3582
3583 #[inline]
3584 pub fn into_weak_ref(self) -> WeakRef<T> {
3585 assert!(
3586 self.1.is_none() || self.1 == Some(thread_id()),
3587 "SendWeakRef dereferenced on a different thread",
3588 );
3589
3590 self.0
3591 }
3592}
3593
3594impl<T: ObjectType> ops::Deref for SendWeakRef<T> {
3595 type Target = WeakRef<T>;
3596
3597 #[inline]
3598 fn deref(&self) -> &WeakRef<T> {
3599 assert!(
3600 self.1.is_none() || self.1 == Some(thread_id()),
3601 "SendWeakRef dereferenced on a different thread"
3602 );
3603
3604 &self.0
3605 }
3606}
3607
3608impl<T: ObjectType> Clone for SendWeakRef<T> {
3610 #[inline]
3611 fn clone(&self) -> Self {
3612 Self(self.0.clone(), self.1)
3613 }
3614}
3615
3616impl<T: ObjectType> Default for SendWeakRef<T> {
3617 #[inline]
3618 fn default() -> Self {
3619 #[allow(deprecated)]
3620 Self::new()
3621 }
3622}
3623
3624impl<T: ObjectType> From<WeakRef<T>> for SendWeakRef<T> {
3625 #[inline]
3626 fn from(v: WeakRef<T>) -> SendWeakRef<T> {
3627 SendWeakRef(v, Some(thread_id()))
3628 }
3629}
3630
3631unsafe impl<T: ObjectType> Sync for SendWeakRef<T> {}
3632unsafe impl<T: ObjectType> Send for SendWeakRef<T> {}
3633
3634type TransformFn<'b> =
3635 Option<Box<dyn Fn(&'b crate::Binding, &'b Value) -> Option<Value> + Send + Sync + 'static>>;
3636
3637#[must_use = "The builder must be built to be used"]
3640pub struct BindingBuilder<'a, 'f, 't> {
3641 source: &'a ObjectRef,
3642 source_property: &'a str,
3643 target: &'a ObjectRef,
3644 target_property: &'a str,
3645 flags: crate::BindingFlags,
3646 transform_from: TransformFn<'f>,
3647 transform_to: TransformFn<'t>,
3648}
3649
3650impl fmt::Debug for BindingBuilder<'_, '_, '_> {
3651 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3652 f.debug_struct("BindingBuilder")
3653 .field("source", &self.source)
3654 .field("source_property", &self.source_property)
3655 .field("target", &self.target)
3656 .field("target_property", &self.target_property)
3657 .field("flags", &self.flags)
3658 .finish()
3659 }
3660}
3661
3662impl<'a, 'f, 't> BindingBuilder<'a, 'f, 't> {
3663 fn new(
3664 source: &'a impl ObjectType,
3665 source_property: &'a str,
3666 target: &'a impl ObjectType,
3667 target_property: &'a str,
3668 ) -> Self {
3669 Self {
3670 source: source.as_object_ref(),
3671 source_property,
3672 target: target.as_object_ref(),
3673 target_property,
3674 flags: crate::BindingFlags::DEFAULT,
3675 transform_to: None,
3676 transform_from: None,
3677 }
3678 }
3679
3680 pub fn transform_from_with_values<
3686 F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3687 >(
3688 self,
3689 func: F,
3690 ) -> Self {
3691 Self {
3692 transform_from: Some(Box::new(func)),
3693 ..self
3694 }
3695 }
3696
3697 pub fn transform_from<
3703 S: FromValue<'f>,
3704 T: Into<Value>,
3705 F: Fn(&'f crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3706 >(
3707 self,
3708 func: F,
3709 ) -> Self {
3710 Self {
3711 transform_from: Some(Box::new(move |binding, from_value| {
3712 let from_value = from_value.get().expect("Wrong value type");
3713 func(binding, from_value).map(|r| r.into())
3714 })),
3715 ..self
3716 }
3717 }
3718
3719 pub fn transform_to_with_values<
3725 F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3726 >(
3727 self,
3728 func: F,
3729 ) -> Self {
3730 Self {
3731 transform_to: Some(Box::new(func)),
3732 ..self
3733 }
3734 }
3735
3736 pub fn transform_to<
3742 S: FromValue<'t>,
3743 T: Into<Value>,
3744 F: Fn(&'t crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3745 >(
3746 self,
3747 func: F,
3748 ) -> Self {
3749 Self {
3750 transform_to: Some(Box::new(move |binding, from_value| {
3751 let from_value = from_value.get().expect("Wrong value type");
3752 func(binding, from_value).map(|r| r.into())
3753 })),
3754 ..self
3755 }
3756 }
3757
3758 pub fn flags(self, flags: crate::BindingFlags) -> Self {
3761 Self { flags, ..self }
3762 }
3763
3764 pub fn bidirectional(mut self) -> Self {
3767 self.flags |= crate::BindingFlags::BIDIRECTIONAL;
3768 self
3769 }
3770
3771 pub fn sync_create(mut self) -> Self {
3774 self.flags |= crate::BindingFlags::SYNC_CREATE;
3775 self
3776 }
3777
3778 pub fn invert_boolean(mut self) -> Self {
3781 self.flags |= crate::BindingFlags::INVERT_BOOLEAN;
3782 self
3783 }
3784
3785 #[track_caller]
3791 pub fn build(self) -> crate::Binding {
3792 unsafe extern "C" fn transform_to_trampoline(
3793 binding: *mut gobject_ffi::GBinding,
3794 from_value: *const gobject_ffi::GValue,
3795 to_value: *mut gobject_ffi::GValue,
3796 user_data: ffi::gpointer,
3797 ) -> ffi::gboolean {
3798 let transform_data = &*(user_data
3799 as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3800
3801 match (transform_data.0.as_ref().unwrap())(
3802 &from_glib_borrow(binding),
3803 &*(from_value as *const Value),
3804 ) {
3805 None => false,
3806 Some(res) => {
3807 assert!(
3808 res.type_().is_a(transform_data.3.value_type()),
3809 "Target property {} expected type {} but transform_to function returned {}",
3810 transform_data.3.name(),
3811 transform_data.3.value_type(),
3812 res.type_()
3813 );
3814 *to_value = res.into_raw();
3815 true
3816 }
3817 }
3818 .into_glib()
3819 }
3820
3821 unsafe extern "C" fn transform_from_trampoline(
3822 binding: *mut gobject_ffi::GBinding,
3823 from_value: *const gobject_ffi::GValue,
3824 to_value: *mut gobject_ffi::GValue,
3825 user_data: ffi::gpointer,
3826 ) -> ffi::gboolean {
3827 let transform_data = &*(user_data
3828 as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3829
3830 match (transform_data.1.as_ref().unwrap())(
3831 &from_glib_borrow(binding),
3832 &*(from_value as *const Value),
3833 ) {
3834 None => false,
3835 Some(res) => {
3836 assert!(
3837 res.type_().is_a(transform_data.2.value_type()),
3838 "Source property {} expected type {} but transform_from function returned {}",
3839 transform_data.2.name(),
3840 transform_data.2.value_type(),
3841 res.type_()
3842 );
3843 *to_value = res.into_raw();
3844 true
3845 }
3846 }
3847 .into_glib()
3848 }
3849
3850 unsafe extern "C" fn free_transform_data(data: ffi::gpointer) {
3851 let _ = Box::from_raw(
3852 data as *mut (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec),
3853 );
3854 }
3855
3856 unsafe {
3857 let source = Object {
3858 inner: TypedObjectRef::new(self.source.clone()),
3859 phantom: std::marker::PhantomData,
3860 };
3861 let target = Object {
3862 inner: TypedObjectRef::new(self.target.clone()),
3863 phantom: std::marker::PhantomData,
3864 };
3865
3866 let source_property = source
3867 .find_property(self.source_property)
3868 .unwrap_or_else(|| {
3869 panic!(
3870 "Source property {} on type {} not found",
3871 self.source_property,
3872 source.type_()
3873 );
3874 });
3875 let target_property = target
3876 .find_property(self.target_property)
3877 .unwrap_or_else(|| {
3878 panic!(
3879 "Target property {} on type {} not found",
3880 self.target_property,
3881 target.type_()
3882 );
3883 });
3884
3885 let source_property_name = source_property.name().as_ptr();
3886 let target_property_name = target_property.name().as_ptr();
3887
3888 let have_transform_to = self.transform_to.is_some();
3889 let have_transform_from = self.transform_from.is_some();
3890 let transform_data = if have_transform_to || have_transform_from {
3891 Box::into_raw(Box::new((
3892 self.transform_to,
3893 self.transform_from,
3894 source_property,
3895 target_property,
3896 )))
3897 } else {
3898 ptr::null_mut()
3899 };
3900
3901 from_glib_none(gobject_ffi::g_object_bind_property_full(
3902 source.to_glib_none().0,
3903 source_property_name as *const _,
3904 target.to_glib_none().0,
3905 target_property_name as *const _,
3906 self.flags.into_glib(),
3907 if have_transform_to {
3908 Some(transform_to_trampoline)
3909 } else {
3910 None
3911 },
3912 if have_transform_from {
3913 Some(transform_from_trampoline)
3914 } else {
3915 None
3916 },
3917 transform_data as ffi::gpointer,
3918 if transform_data.is_null() {
3919 None
3920 } else {
3921 Some(free_transform_data)
3922 },
3923 ))
3924 }
3925 }
3926}
3927
3928#[repr(transparent)]
3931pub struct Class<T: IsClass>(T::GlibClassType);
3932
3933impl<T: IsClass> Class<T> {
3934 #[doc(alias = "get_type")]
3940 #[inline]
3941 pub fn type_(&self) -> Type {
3942 unsafe {
3943 let klass = self as *const _ as *const gobject_ffi::GTypeClass;
3946 from_glib((*klass).g_type)
3947 }
3948 }
3949
3950 #[inline]
3953 pub fn upcast_ref<U: IsClass>(&self) -> &Class<U>
3954 where
3955 T: IsA<U>,
3956 {
3957 unsafe {
3958 let klass = self as *const _ as *const Class<U>;
3959 &*klass
3960 }
3961 }
3962
3963 #[inline]
3966 pub fn upcast_ref_mut<U: IsClass>(&mut self) -> &mut Class<U>
3967 where
3968 T: IsA<U>,
3969 {
3970 unsafe {
3971 let klass = self as *mut _ as *mut Class<U>;
3972 &mut *klass
3973 }
3974 }
3975
3976 #[inline]
3980 pub fn downcast_ref<U: IsClass + IsA<T>>(&self) -> Option<&Class<U>> {
3981 if !self.type_().is_a(U::static_type()) {
3982 return None;
3983 }
3984
3985 unsafe {
3986 let klass = self as *const _ as *const Class<U>;
3987 Some(&*klass)
3988 }
3989 }
3990
3991 #[inline]
3995 pub fn downcast_ref_mut<U: IsClass + IsA<T>>(&mut self) -> Option<&mut Class<U>> {
3996 if !self.type_().is_a(U::static_type()) {
3997 return None;
3998 }
3999
4000 unsafe {
4001 let klass = self as *mut _ as *mut Class<U>;
4002 Some(&mut *klass)
4003 }
4004 }
4005
4006 #[doc(alias = "g_type_class_ref")]
4011 #[inline]
4012 pub fn from_type(type_: Type) -> Option<ClassRef<'static, T>> {
4013 if !type_.is_a(T::static_type()) {
4014 return None;
4015 }
4016
4017 unsafe {
4018 let ptr = gobject_ffi::g_type_class_ref(type_.into_glib());
4019 if ptr.is_null() {
4020 None
4021 } else {
4022 Some(ClassRef(
4023 ptr::NonNull::new_unchecked(ptr as *mut Self),
4024 true,
4025 PhantomData,
4026 ))
4027 }
4028 }
4029 }
4030
4031 #[doc(alias = "g_type_class_peek_parent")]
4034 #[inline]
4035 pub fn parent(&self) -> Option<ClassRef<T>> {
4036 unsafe {
4037 let ptr = gobject_ffi::g_type_class_peek_parent(&self.0 as *const _ as *mut _);
4038 if ptr.is_null() {
4039 None
4040 } else {
4041 Some(ClassRef(
4042 ptr::NonNull::new_unchecked(ptr as *mut Self),
4043 false,
4044 PhantomData,
4045 ))
4046 }
4047 }
4048 }
4049}
4050
4051unsafe impl<T: IsClass> Send for Class<T> {}
4052unsafe impl<T: IsClass> Sync for Class<T> {}
4053
4054impl<T: IsClass> AsRef<T::GlibClassType> for Class<T> {
4055 #[inline]
4056 fn as_ref(&self) -> &T::GlibClassType {
4057 &self.0
4058 }
4059}
4060
4061impl<T: IsClass> AsMut<T::GlibClassType> for Class<T> {
4062 #[inline]
4063 fn as_mut(&mut self) -> &mut T::GlibClassType {
4064 &mut self.0
4065 }
4066}
4067
4068#[derive(Debug)]
4071pub struct ClassRef<'a, T: IsClass>(ptr::NonNull<Class<T>>, bool, PhantomData<&'a ()>);
4072
4073impl<T: IsClass> ops::Deref for ClassRef<'_, T> {
4074 type Target = Class<T>;
4075
4076 #[inline]
4077 fn deref(&self) -> &Class<T> {
4078 unsafe { self.0.as_ref() }
4079 }
4080}
4081
4082impl<T: IsClass> Drop for ClassRef<'_, T> {
4083 #[inline]
4084 fn drop(&mut self) {
4085 if self.1 {
4086 unsafe {
4087 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
4088 }
4089 }
4090 }
4091}
4092
4093unsafe impl<T: IsClass> Send for ClassRef<'_, T> {}
4094unsafe impl<T: IsClass> Sync for ClassRef<'_, T> {}
4095
4096pub unsafe trait ParentClassIs: IsClass {
4098 type Parent: IsClass;
4099}
4100
4101pub unsafe trait ObjectSubclassIs: IsClass {
4105 type Subclass: ObjectSubclass;
4106}
4107
4108impl<T: ParentClassIs> ops::Deref for Class<T> {
4109 type Target = Class<T::Parent>;
4110
4111 #[inline]
4112 fn deref(&self) -> &Self::Target {
4113 unsafe {
4114 let klass = self as *const _ as *const Self::Target;
4115 &*klass
4116 }
4117 }
4118}
4119
4120impl<T: ParentClassIs> ops::DerefMut for Class<T> {
4121 #[inline]
4122 fn deref_mut(&mut self) -> &mut Self::Target {
4123 unsafe {
4124 let klass = self as *mut _ as *mut Self::Target;
4125 &mut *klass
4126 }
4127 }
4128}
4129
4130pub unsafe trait IsClass: ObjectType {}
4133
4134#[repr(transparent)]
4137pub struct Interface<T: IsInterface>(T::GlibClassType);
4138
4139impl<T: IsInterface> Interface<T> {
4140 #[doc(alias = "get_type")]
4145 #[inline]
4146 pub fn type_(&self) -> Type {
4147 unsafe {
4148 let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4149 from_glib((*klass).g_type)
4150 }
4151 }
4152
4153 #[doc(alias = "get_instance_type")]
4159 #[inline]
4160 pub fn instance_type(&self) -> Type {
4161 unsafe {
4162 let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4165 from_glib((*klass).g_instance_type)
4166 }
4167 }
4168
4169 #[inline]
4174 pub fn from_class<U: IsClass>(klass: &Class<U>) -> Option<InterfaceRef<T>> {
4175 if !klass.type_().is_a(T::static_type()) {
4176 return None;
4177 }
4178
4179 unsafe {
4180 let ptr = gobject_ffi::g_type_interface_peek(
4181 &klass.0 as *const _ as *mut _,
4182 T::static_type().into_glib(),
4183 );
4184 if ptr.is_null() {
4185 None
4186 } else {
4187 Some(InterfaceRef(
4188 ptr::NonNull::new_unchecked(ptr as *mut Self),
4189 false,
4190 PhantomData,
4191 ))
4192 }
4193 }
4194 }
4195
4196 #[inline]
4201 pub fn from_type(type_: Type) -> Option<InterfaceRef<'static, T>> {
4202 if !type_.is_a(Type::INTERFACE) {
4203 return None;
4204 }
4205
4206 unsafe {
4207 let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4208 if ptr.is_null() {
4209 None
4210 } else {
4211 Some(InterfaceRef(
4212 ptr::NonNull::new_unchecked(ptr as *mut Self),
4213 true,
4214 PhantomData,
4215 ))
4216 }
4217 }
4218 }
4219
4220 #[doc(alias = "g_type_default_interface_ref")]
4223 #[allow(clippy::should_implement_trait)]
4224 #[inline]
4225 pub fn default() -> InterfaceRef<'static, T> {
4226 unsafe {
4227 let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4228 debug_assert!(!ptr.is_null());
4229 InterfaceRef(
4230 ptr::NonNull::new_unchecked(ptr as *mut Self),
4231 true,
4232 PhantomData,
4233 )
4234 }
4235 }
4236
4237 #[doc(alias = "g_type_interface_peek_parent")]
4243 #[inline]
4244 pub fn parent(&self) -> Option<InterfaceRef<T>> {
4245 unsafe {
4246 let ptr = gobject_ffi::g_type_interface_peek_parent(&self.0 as *const _ as *mut _);
4247 if ptr.is_null() {
4248 None
4249 } else {
4250 Some(InterfaceRef(
4251 ptr::NonNull::new_unchecked(ptr as *mut Self),
4252 false,
4253 PhantomData,
4254 ))
4255 }
4256 }
4257 }
4258}
4259
4260impl<T: IsA<Object> + IsInterface> Interface<T> {
4261 pub fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool {
4266 let ptype = self.property_type(property_name);
4267
4268 match (ptype, type_) {
4269 (None, _) => false,
4270 (Some(_), None) => true,
4271 (Some(ptype), Some(type_)) => ptype == type_,
4272 }
4273 }
4274
4275 #[doc(alias = "get_property_type")]
4280 pub fn property_type(&self, property_name: &str) -> Option<Type> {
4281 self.find_property(property_name)
4282 .map(|pspec| pspec.value_type())
4283 }
4284
4285 #[doc(alias = "g_object_interface_find_property")]
4288 pub fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
4289 unsafe {
4290 let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4291
4292 from_glib_none(gobject_ffi::g_object_interface_find_property(
4293 interface as *mut _,
4294 property_name.to_glib_none().0,
4295 ))
4296 }
4297 }
4298
4299 #[doc(alias = "g_object_interface_list_properties")]
4302 pub fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
4303 unsafe {
4304 let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4305
4306 let mut n_properties = 0;
4307
4308 let props = gobject_ffi::g_object_interface_list_properties(
4309 interface as *mut _,
4310 &mut n_properties,
4311 );
4312 PtrSlice::from_glib_container_num(props, n_properties as usize, true)
4313 }
4314 }
4315}
4316
4317unsafe impl<T: IsInterface> Send for Interface<T> {}
4318unsafe impl<T: IsInterface> Sync for Interface<T> {}
4319
4320impl<T: IsInterface> AsRef<T::GlibClassType> for Interface<T> {
4321 #[inline]
4322 fn as_ref(&self) -> &T::GlibClassType {
4323 &self.0
4324 }
4325}
4326
4327impl<T: IsInterface> AsMut<T::GlibClassType> for Interface<T> {
4328 #[inline]
4329 fn as_mut(&mut self) -> &mut T::GlibClassType {
4330 &mut self.0
4331 }
4332}
4333
4334#[derive(Debug)]
4337pub struct InterfaceRef<'a, T: IsInterface>(ptr::NonNull<Interface<T>>, bool, PhantomData<&'a ()>);
4338
4339impl<T: IsInterface> Drop for InterfaceRef<'_, T> {
4340 #[inline]
4341 fn drop(&mut self) {
4342 if self.1 {
4343 unsafe {
4344 gobject_ffi::g_type_default_interface_unref(self.0.as_ptr() as *mut _);
4345 }
4346 }
4347 }
4348}
4349
4350impl<T: IsInterface> ops::Deref for InterfaceRef<'_, T> {
4351 type Target = Interface<T>;
4352
4353 #[inline]
4354 fn deref(&self) -> &Interface<T> {
4355 unsafe { self.0.as_ref() }
4356 }
4357}
4358
4359unsafe impl<T: IsInterface> Send for InterfaceRef<'_, T> {}
4360unsafe impl<T: IsInterface> Sync for InterfaceRef<'_, T> {}
4361
4362pub unsafe trait IsInterface: ObjectType {}
4365
4366pub struct ObjectValueTypeChecker<T>(std::marker::PhantomData<T>);
4369
4370unsafe impl<T: StaticType> crate::value::ValueTypeChecker for ObjectValueTypeChecker<T> {
4371 type Error = crate::value::ValueTypeMismatchOrNoneError<crate::value::ValueTypeMismatchError>;
4372
4373 fn check(value: &Value) -> Result<(), Self::Error> {
4374 unsafe {
4379 let requested_type = T::static_type().into_glib();
4380 let type_ = value.inner.g_type;
4381
4382 if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4384 let obj = gobject_ffi::g_value_get_object(&value.inner);
4385 if obj.is_null() {
4386 return Err(Self::Error::UnexpectedNone);
4387 } else {
4388 return Ok(());
4389 }
4390 }
4391
4392 if gobject_ffi::g_type_is_a(type_, gobject_ffi::G_TYPE_OBJECT) == ffi::GFALSE {
4394 return Err(crate::value::ValueTypeMismatchError::new(
4395 Type::from_glib(type_),
4396 T::static_type(),
4397 )
4398 .into());
4399 }
4400
4401 let obj = gobject_ffi::g_value_get_object(&value.inner);
4403
4404 if obj.is_null() {
4406 return Err(Self::Error::UnexpectedNone);
4407 }
4408
4409 let type_ = (*(*obj).g_type_instance.g_class).g_type;
4410 if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4412 Ok(())
4413 } else {
4414 Err(crate::value::ValueTypeMismatchError::new(
4415 Type::from_glib(type_),
4416 T::static_type(),
4417 )
4418 .into())
4419 }
4420 }
4421 }
4422}
4423
4424#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4429#[repr(transparent)]
4430pub struct BorrowedObject<'a, T> {
4431 ptr: ptr::NonNull<gobject_ffi::GObject>,
4432 phantom: PhantomData<&'a T>,
4433}
4434
4435unsafe impl<T: Send + Sync> Send for BorrowedObject<'_, T> {}
4436unsafe impl<T: Send + Sync> Sync for BorrowedObject<'_, T> {}
4437
4438impl<'a, T: ObjectType> BorrowedObject<'a, T> {
4439 #[inline]
4446 pub unsafe fn new(ptr: *mut T::GlibType) -> BorrowedObject<'a, T> {
4447 BorrowedObject {
4448 ptr: ptr::NonNull::new_unchecked(ptr as *mut _),
4449 phantom: PhantomData,
4450 }
4451 }
4452
4453 #[inline]
4456 pub fn downgrade(&self) -> <Self as crate::clone::Downgrade>::Weak
4457 where
4458 T: crate::clone::Downgrade,
4459 {
4460 <T as crate::clone::Downgrade>::downgrade(self)
4461 }
4462}
4463
4464impl<T> ops::Deref for BorrowedObject<'_, T> {
4465 type Target = T;
4466
4467 #[inline]
4468 fn deref(&self) -> &T {
4469 unsafe { &*(&self.ptr as *const _ as *const T) }
4470 }
4471}
4472
4473impl<T> AsRef<T> for BorrowedObject<'_, T> {
4474 #[inline]
4475 fn as_ref(&self) -> &T {
4476 unsafe { &*(&self.ptr as *const _ as *const T) }
4477 }
4478}
4479
4480impl<T: PartialEq> PartialEq<T> for BorrowedObject<'_, T> {
4481 #[inline]
4482 fn eq(&self, other: &T) -> bool {
4483 <T as PartialEq>::eq(self, other)
4484 }
4485}
4486
4487impl<T: PartialOrd> PartialOrd<T> for BorrowedObject<'_, T> {
4488 #[inline]
4489 fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
4490 <T as PartialOrd>::partial_cmp(self, other)
4491 }
4492}
4493
4494impl<T: crate::clone::Downgrade + ObjectType> crate::clone::Downgrade for BorrowedObject<'_, T> {
4495 type Weak = <T as crate::clone::Downgrade>::Weak;
4496
4497 #[inline]
4498 fn downgrade(&self) -> Self::Weak {
4499 <T as crate::clone::Downgrade>::downgrade(self)
4500 }
4501}
4502
4503#[cfg(test)]
4504mod tests {
4505 use std::{
4506 cell::Cell,
4507 rc::Rc,
4508 sync::{
4509 atomic::{AtomicBool, Ordering},
4510 Arc,
4511 },
4512 };
4513
4514 use super::*;
4515
4516 #[test]
4517 fn new() {
4518 let obj: Object = Object::new();
4519 drop(obj);
4520 }
4521
4522 #[test]
4523 fn data() {
4524 let obj: Object = Object::new();
4525 unsafe {
4526 obj.set_data::<String>("foo", "hello".into());
4527 let data = obj.data::<String>("foo").unwrap();
4528 assert_eq!(data.as_ref(), "hello");
4529 let data2 = obj.steal_data::<String>("foo").unwrap();
4530 assert_eq!(data2, "hello");
4531 }
4532 }
4533
4534 #[test]
4535 fn weak_ref() {
4536 let obj: Object = Object::new();
4537
4538 let weakref: WeakRef<Object> = WeakRef::new();
4539 weakref.set(Some(&obj));
4540 assert!(weakref.upgrade().is_some());
4541 weakref.set(None);
4542 assert!(weakref.upgrade().is_none());
4543
4544 let weakref = WeakRef::new();
4545 weakref.set(Some(&obj));
4546 assert!(weakref.upgrade().is_some());
4547
4548 drop(obj);
4549 assert!(weakref.upgrade().is_none());
4550 }
4551
4552 #[test]
4553 fn weak_ref_notify() {
4554 let obj: Object = Object::new();
4555
4556 let handle = obj.add_weak_ref_notify(|| {
4557 unreachable!();
4558 });
4559
4560 handle.disconnect();
4561
4562 let called = Arc::new(AtomicBool::new(false));
4563 let called_weak = Arc::downgrade(&called);
4564 let handle = obj.add_weak_ref_notify(move || {
4565 called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4566 });
4567
4568 drop(obj);
4569 assert!(called.load(Ordering::SeqCst));
4570 handle.disconnect();
4571
4572 let obj: Object = Object::new();
4573
4574 let called = Arc::new(AtomicBool::new(false));
4575 let called_weak = Arc::downgrade(&called);
4576 obj.add_weak_ref_notify(move || {
4577 called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4578 });
4579
4580 drop(obj);
4581 assert!(called.load(Ordering::SeqCst));
4582
4583 let obj: Object = Object::new();
4584
4585 let called = Rc::new(Cell::new(false));
4586 let called_weak = Rc::downgrade(&called);
4587 obj.add_weak_ref_notify_local(move || {
4588 called_weak.upgrade().unwrap().set(true);
4589 });
4590
4591 drop(obj);
4592 assert!(called.get());
4593 }
4594
4595 #[test]
4596 fn test_value() {
4597 let obj1: Object = Object::new();
4598 let v = obj1.to_value();
4599 let obj2 = v.get::<&Object>().unwrap();
4600
4601 assert_eq!(obj1.as_ptr(), obj2.as_ptr());
4602 }
4603
4604 #[test]
4605 fn test_borrow_hashing() {
4606 let mut m = std::collections::HashSet::new();
4607 let boxed_object = crate::BoxedAnyObject::new("");
4608
4609 m.insert(boxed_object.clone());
4610
4611 let object: &Object = std::borrow::Borrow::borrow(&boxed_object);
4612 assert_eq!(m.get(object), Some(&boxed_object));
4613 }
4614}