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
54#[diagnostic::on_unimplemented(
67 message = "the trait `glib::object::IsA<{T}>` is not implemented for `{Self}`",
68 label = "requires `{Self}` to be a GObject that can be statically cast to `{T}`",
69 note = "if this is your own object, use the `glib::wrapper!` macro to implement this trait: https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/macro.wrapper.html"
70)]
71pub unsafe trait IsA<T: ObjectType>:
72 ObjectType + Into<T> + AsRef<T> + std::borrow::Borrow<T>
73{
74}
75
76pub trait Cast: ObjectType {
81 #[inline]
96 fn upcast<T: ObjectType>(self) -> T
97 where
98 Self: IsA<T>,
99 {
100 unsafe { self.unsafe_cast() }
101 }
102
103 #[inline]
118 fn upcast_ref<T: ObjectType>(&self) -> &T
119 where
120 Self: IsA<T>,
121 {
122 unsafe { self.unsafe_cast_ref() }
123 }
124
125 #[inline]
143 fn downcast<T: ObjectType>(self) -> Result<T, Self>
144 where
145 Self: MayDowncastTo<T>,
146 {
147 if self.is::<T>() {
148 Ok(unsafe { self.unsafe_cast() })
149 } else {
150 Err(self)
151 }
152 }
153
154 #[inline]
172 fn downcast_ref<T: ObjectType>(&self) -> Option<&T>
173 where
174 Self: MayDowncastTo<T>,
175 {
176 if self.is::<T>() {
177 Some(unsafe { self.unsafe_cast_ref() })
178 } else {
179 None
180 }
181 }
182
183 #[inline]
206 fn dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
207 if !self.is::<T>() {
208 Err(self)
209 } else {
210 Ok(unsafe { self.unsafe_cast() })
211 }
212 }
213
214 #[inline]
235 fn dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
236 if !self.is::<T>() {
237 None
238 } else {
239 Some(unsafe { self.unsafe_cast_ref() })
244 }
245 }
246
247 #[track_caller]
259 #[inline]
260 unsafe fn unsafe_cast<T: ObjectType>(self) -> T {
261 debug_assert!(self.is::<T>());
262 T::unsafe_from(self.into())
263 }
264
265 #[track_caller]
277 #[inline]
278 unsafe fn unsafe_cast_ref<T: ObjectType>(&self) -> &T {
279 debug_assert!(self.is::<T>());
280 &*(self as *const Self as *const T)
285 }
286}
287
288impl<T: ObjectType> Cast for T {}
289
290pub trait CastNone: Sized {
309 type Inner;
310 fn and_downcast<T: ObjectType>(self) -> Option<T>
311 where
312 Self::Inner: MayDowncastTo<T>;
313 fn and_downcast_ref<T: ObjectType>(&self) -> Option<&T>
314 where
315 Self::Inner: MayDowncastTo<T>;
316 fn and_upcast<T: ObjectType>(self) -> Option<T>
317 where
318 Self::Inner: IsA<T>;
319 fn and_upcast_ref<T: ObjectType>(&self) -> Option<&T>
320 where
321 Self::Inner: IsA<T>;
322 fn and_dynamic_cast<T: ObjectType>(self) -> Result<T, Self>;
323 fn and_dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T>;
324}
325impl<I: ObjectType + Sized> CastNone for Option<I> {
326 type Inner = I;
327
328 #[inline]
329 fn and_downcast<T: ObjectType>(self) -> Option<T>
330 where
331 Self::Inner: MayDowncastTo<T>,
332 {
333 self.and_then(|i| i.downcast().ok())
334 }
335
336 #[inline]
337 fn and_downcast_ref<T: ObjectType>(&self) -> Option<&T>
338 where
339 Self::Inner: MayDowncastTo<T>,
340 {
341 self.as_ref().and_then(|i| i.downcast_ref())
342 }
343
344 #[inline]
345 fn and_upcast<T: ObjectType>(self) -> Option<T>
346 where
347 Self::Inner: IsA<T>,
348 {
349 self.map(|i| i.upcast())
350 }
351
352 #[inline]
353 fn and_upcast_ref<T: ObjectType>(&self) -> Option<&T>
354 where
355 Self::Inner: IsA<T>,
356 {
357 self.as_ref().map(|i| i.upcast_ref())
358 }
359
360 #[inline]
361 fn and_dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
362 self.ok_or(None)
363 .and_then(|i| i.dynamic_cast().map_err(|e| Some(e)))
364 }
365
366 #[inline]
367 fn and_dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
368 self.as_ref().and_then(|i| i.dynamic_cast_ref())
369 }
370}
371
372pub trait MayDowncastTo<T> {}
375
376impl<Super: IsA<Super>, Sub: IsA<Super>> MayDowncastTo<Sub> for Super {}
377
378#[repr(transparent)]
380pub struct ObjectRef {
381 inner: ptr::NonNull<gobject_ffi::GObject>,
382}
383
384impl Clone for ObjectRef {
385 #[inline]
386 fn clone(&self) -> Self {
387 unsafe {
388 Self {
389 inner: ptr::NonNull::new_unchecked(gobject_ffi::g_object_ref(self.inner.as_ptr())),
390 }
391 }
392 }
393}
394
395impl Drop for ObjectRef {
396 #[inline]
397 fn drop(&mut self) {
398 unsafe {
399 gobject_ffi::g_object_unref(self.inner.as_ptr());
400 }
401 }
402}
403
404impl fmt::Debug for ObjectRef {
405 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406 let type_ = unsafe {
407 let klass = (*self.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
408 (*klass).type_()
409 };
410
411 f.debug_struct("ObjectRef")
412 .field("inner", &self.inner)
413 .field("type", &type_)
414 .finish()
415 }
416}
417
418impl PartialOrd for ObjectRef {
419 #[inline]
420 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
421 Some(self.cmp(other))
422 }
423}
424
425impl Ord for ObjectRef {
426 #[inline]
427 fn cmp(&self, other: &Self) -> cmp::Ordering {
428 self.inner.cmp(&other.inner)
429 }
430}
431
432impl PartialEq for ObjectRef {
433 #[inline]
434 fn eq(&self, other: &Self) -> bool {
435 self.inner == other.inner
436 }
437}
438
439impl Eq for ObjectRef {}
440
441impl hash::Hash for ObjectRef {
442 #[inline]
443 fn hash<H>(&self, state: &mut H)
444 where
445 H: hash::Hasher,
446 {
447 self.inner.hash(state)
448 }
449}
450
451#[doc(hidden)]
452impl GlibPtrDefault for ObjectRef {
453 type GlibType = *mut gobject_ffi::GObject;
454}
455
456#[doc(hidden)]
457impl<'a> ToGlibPtr<'a, *mut gobject_ffi::GObject> for ObjectRef {
458 type Storage = PhantomData<&'a ObjectRef>;
459
460 #[inline]
461 fn to_glib_none(&'a self) -> Stash<'a, *mut gobject_ffi::GObject, Self> {
462 Stash(self.inner.as_ptr(), PhantomData)
463 }
464
465 #[inline]
466 fn to_glib_full(&self) -> *mut gobject_ffi::GObject {
467 unsafe { gobject_ffi::g_object_ref(self.inner.as_ptr()) }
468 }
469}
470
471#[doc(hidden)]
472impl FromGlibPtrNone<*mut gobject_ffi::GObject> for ObjectRef {
473 #[inline]
474 unsafe fn from_glib_none(ptr: *mut gobject_ffi::GObject) -> Self {
475 debug_assert!(!ptr.is_null());
476 debug_assert_ne!((*ptr).ref_count, 0);
477
478 Self {
480 inner: ptr::NonNull::new_unchecked(gobject_ffi::g_object_ref_sink(ptr)),
481 }
482 }
483}
484
485#[doc(hidden)]
486impl FromGlibPtrNone<*const gobject_ffi::GObject> for ObjectRef {
487 #[inline]
488 unsafe fn from_glib_none(ptr: *const gobject_ffi::GObject) -> Self {
489 from_glib_none(ptr as *mut gobject_ffi::GObject)
491 }
492}
493
494#[doc(hidden)]
495impl FromGlibPtrFull<*mut gobject_ffi::GObject> for ObjectRef {
496 #[inline]
497 unsafe fn from_glib_full(ptr: *mut gobject_ffi::GObject) -> Self {
498 debug_assert!(!ptr.is_null());
499 debug_assert_ne!((*ptr).ref_count, 0);
500
501 Self {
502 inner: ptr::NonNull::new_unchecked(ptr),
503 }
504 }
505}
506
507#[doc(hidden)]
508impl FromGlibPtrBorrow<*mut gobject_ffi::GObject> for ObjectRef {
509 #[inline]
510 unsafe fn from_glib_borrow(ptr: *mut gobject_ffi::GObject) -> Borrowed<Self> {
511 debug_assert!(!ptr.is_null());
512 debug_assert_ne!((*ptr).ref_count, 0);
513
514 Borrowed::new(Self {
515 inner: ptr::NonNull::new_unchecked(ptr),
516 })
517 }
518}
519
520#[doc(hidden)]
521impl FromGlibPtrBorrow<*const gobject_ffi::GObject> for ObjectRef {
522 #[inline]
523 unsafe fn from_glib_borrow(ptr: *const gobject_ffi::GObject) -> Borrowed<Self> {
524 from_glib_borrow(ptr as *mut gobject_ffi::GObject)
525 }
526}
527
528#[repr(transparent)]
529pub struct TypedObjectRef<T, P> {
530 inner: ObjectRef,
531 imp: PhantomData<T>,
532 parent: PhantomData<P>,
533}
534
535impl<T, P> TypedObjectRef<T, P> {
536 #[inline]
537 pub unsafe fn new(obj: ObjectRef) -> Self {
538 Self {
539 inner: obj,
540 imp: PhantomData,
541 parent: PhantomData,
542 }
543 }
544
545 #[inline]
546 pub fn into_inner(self) -> ObjectRef {
547 self.inner
548 }
549}
550
551impl<T, P> Clone for TypedObjectRef<T, P> {
552 #[inline]
553 fn clone(&self) -> Self {
554 Self {
555 inner: self.inner.clone(),
556 imp: PhantomData,
557 parent: PhantomData,
558 }
559 }
560}
561
562impl<T, P> ops::Deref for TypedObjectRef<T, P> {
563 type Target = ObjectRef;
564
565 #[inline]
566 fn deref(&self) -> &Self::Target {
567 &self.inner
568 }
569}
570
571impl<T, P> fmt::Debug for TypedObjectRef<T, P> {
572 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
573 let type_ = unsafe {
574 let klass = (*self.inner.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
575 (*klass).type_()
576 };
577
578 f.debug_struct("TypedObjectRef")
579 .field("inner", &self.inner.inner)
580 .field("type", &type_)
581 .finish()
582 }
583}
584
585impl<T, P> PartialOrd for TypedObjectRef<T, P> {
586 #[inline]
587 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
588 Some(self.cmp(other))
589 }
590}
591
592impl<T, P> Ord for TypedObjectRef<T, P> {
593 #[inline]
594 fn cmp(&self, other: &Self) -> cmp::Ordering {
595 self.inner.cmp(&other.inner)
596 }
597}
598
599impl<T, P> PartialEq for TypedObjectRef<T, P> {
600 #[inline]
601 fn eq(&self, other: &Self) -> bool {
602 self.inner == other.inner
603 }
604}
605
606impl<T, P> Eq for TypedObjectRef<T, P> {}
607
608impl<T, P> hash::Hash for TypedObjectRef<T, P> {
609 #[inline]
610 fn hash<H>(&self, state: &mut H)
611 where
612 H: hash::Hasher,
613 {
614 self.inner.hash(state)
615 }
616}
617
618unsafe impl<T: Send + Sync, P: Send + Sync> Send for TypedObjectRef<T, P> {}
619unsafe impl<T: Send + Sync, P: Send + Sync> Sync for TypedObjectRef<T, P> {}
620
621#[macro_export]
624macro_rules! glib_object_wrapper {
625 (@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) => {
626 $(#[$attr])*
627 #[doc = "\n\nGLib type: GObject with reference counted clone semantics."]
628 #[repr(transparent)]
629 $visibility struct $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? {
630 inner: $crate::object::TypedObjectRef<$impl_type, $parent_type>,
631 phantom: std::marker::PhantomData<($($($generic),+)?)>,
632 }
633
634 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::clone::Clone for $name $(<$($generic),+>)? {
642 #[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."]
643 #[inline]
644 fn clone(&self) -> Self {
645 Self {
646 inner: std::clone::Clone::clone(&self.inner),
647 phantom: std::marker::PhantomData,
648 }
649 }
650 }
651
652 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::hash::Hash for $name $(<$($generic),+>)? {
653 #[doc = "Hashes the memory address of this object."]
654 #[inline]
655 fn hash<H>(&self, state: &mut H)
656 where
657 H: std::hash::Hasher
658 {
659 std::hash::Hash::hash(&self.inner, state);
660 }
661 }
662
663 impl<OT: $crate::object::ObjectType $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> std::cmp::PartialEq<OT> for $name $(<$($generic),+>)? {
664 #[doc = "Equality for two GObjects.\n\nTwo GObjects are equal if their memory addresses are equal."]
665 #[inline]
666 fn eq(&self, other: &OT) -> bool {
667 std::cmp::PartialEq::eq(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
668 }
669 }
670
671 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::cmp::Eq for $name $(<$($generic),+>)? {}
672
673 impl<OT: $crate::object::ObjectType $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> std::cmp::PartialOrd<OT> for $name $(<$($generic),+>)? {
674 #[doc = "Partial comparison for two GObjects.\n\nCompares the memory addresses of the provided objects."]
675 #[inline]
676 fn partial_cmp(&self, other: &OT) -> Option<std::cmp::Ordering> {
677 std::cmp::PartialOrd::partial_cmp(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
678 }
679 }
680
681 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::cmp::Ord for $name $(<$($generic),+>)? {
682 #[doc = "Comparison for two GObjects.\n\nCompares the memory addresses of the provided objects."]
683 #[inline]
684 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
685 std::cmp::Ord::cmp(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
686 }
687 }
688
689
690 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::fmt::Debug for $name $(<$($generic),+>)? {
691 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
692 f.debug_struct(stringify!($name)).field("inner", &self.inner).finish()
693 }
694 }
695
696 #[doc(hidden)]
697 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::ObjectRef {
698 #[inline]
699 fn from(s: $name $(<$($generic),+>)?) -> $crate::object::ObjectRef {
700 s.inner.into_inner()
701 }
702 }
703
704 #[doc(hidden)]
705 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::UnsafeFrom<$crate::object::ObjectRef> for $name $(<$($generic),+>)? {
706 #[inline]
707 unsafe fn unsafe_from(t: $crate::object::ObjectRef) -> Self {
708 $name {
709 inner: $crate::object::TypedObjectRef::new(t),
710 phantom: std::marker::PhantomData,
711 }
712 }
713 }
714
715 #[doc(hidden)]
716 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::GlibPtrDefault for $name $(<$($generic),+>)? {
717 type GlibType = *mut $ffi_name;
718 }
719
720 #[doc(hidden)]
721 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::TransparentPtrType for $name $(<$($generic),+>)? {}
722
723 #[doc(hidden)]
724 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectType for $name $(<$($generic),+>)? {
725 type GlibType = $ffi_name;
726 type GlibClassType = $ffi_class_name;
727
728 #[inline]
729 fn as_object_ref(&self) -> &$crate::object::ObjectRef {
730 &self.inner
731 }
732
733 #[inline]
734 fn as_ptr(&self) -> *mut Self::GlibType {
735 unsafe { *(self as *const Self as *const *const $ffi_name) as *mut $ffi_name }
736 }
737
738 #[inline]
739 unsafe fn from_glib_ptr_borrow(ptr: &*mut Self::GlibType) -> &Self {
740 debug_assert_eq!(
741 std::mem::size_of::<Self>(),
742 std::mem::size_of::<$crate::ffi::gpointer>()
743 );
744 debug_assert!(!ptr.is_null());
745 debug_assert_ne!((*(*ptr as *const $crate::gobject_ffi::GObject)).ref_count, 0);
746 &*(ptr as *const *mut $ffi_name as *const Self)
747 }
748 }
749
750 #[doc(hidden)]
751 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::ObjectRef> for $name $(<$($generic),+>)? {
752 #[inline]
753 fn as_ref(&self) -> &$crate::object::ObjectRef {
754 &self.inner
755 }
756 }
757
758 #[doc(hidden)]
759 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<Self> for $name $(<$($generic),+>)? {
760 #[inline]
761 fn as_ref(&self) -> &Self {
762 self
763 }
764 }
765
766 #[doc(hidden)]
767 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<Self> for $name $(<$($generic),+>)? { }
768
769 #[doc(hidden)]
770 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::subclass::types::FromObject for $name $(<$($generic),+>)? {
771 type FromObjectType = Self;
772
773 #[inline]
774 fn from_object(obj: &Self::FromObjectType) -> &Self {
775 obj
776 }
777 }
778
779 #[doc(hidden)]
780 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name $(<$($generic),+>)? {
781 type Storage = <$crate::object::ObjectRef as
782 $crate::translate::ToGlibPtr<'a, *mut $crate::gobject_ffi::GObject>>::Storage;
783
784 #[inline]
785 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
786 let stash = $crate::translate::ToGlibPtr::to_glib_none(&*self.inner);
787 $crate::translate::Stash(stash.0 as *const _, stash.1)
788 }
789
790 #[inline]
791 fn to_glib_full(&self) -> *const $ffi_name {
792 $crate::translate::ToGlibPtr::to_glib_full(&*self.inner) as *const _
793 }
794 }
795
796 #[doc(hidden)]
797 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name $(<$($generic),+>)? {
798 type Storage = <$crate::object::ObjectRef as
799 $crate::translate::ToGlibPtr<'a, *mut $crate::gobject_ffi::GObject>>::Storage;
800
801 #[inline]
802 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
803 let stash = $crate::translate::ToGlibPtr::to_glib_none(&*self.inner);
804 $crate::translate::Stash(stash.0 as *mut _, stash.1)
805 }
806
807 #[inline]
808 fn to_glib_full(&self) -> *mut $ffi_name {
809 $crate::translate::ToGlibPtr::to_glib_full(&*self.inner) as *mut _
810 }
811 }
812
813 #[doc(hidden)]
814 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*mut $ffi_name> for $name $(<$($generic),+>)? {
815 #[inline]
816 unsafe fn into_glib_ptr(self) -> *mut $ffi_name {
817 let s = std::mem::ManuallyDrop::new(self);
818 $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *mut _
819 }
820 }
821
822 #[doc(hidden)]
823 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*const $ffi_name> for $name $(<$($generic),+>)? {
824 #[inline]
825 unsafe fn into_glib_ptr(self) -> *const $ffi_name {
826 let s = std::mem::ManuallyDrop::new(self);
827 $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *const _
828 }
829 }
830
831 #[doc(hidden)]
832 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
833 type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*mut $ffi_name>>);
834
835 fn to_glib_none_from_slice(t: &'a [Self]) -> (*mut *mut $ffi_name, Self::Storage) {
836 let mut v_ptr = Vec::with_capacity(t.len() + 1);
837 unsafe {
838 let ptr = v_ptr.as_mut_ptr();
839 std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *mut $ffi_name, ptr, t.len());
840 std::ptr::write(ptr.add(t.len()), std::ptr::null_mut());
841 v_ptr.set_len(t.len() + 1);
842 }
843
844 (v_ptr.as_ptr() as *mut *mut $ffi_name, (std::marker::PhantomData, Some(v_ptr)))
845 }
846
847 fn to_glib_container_from_slice(t: &'a [Self]) -> (*mut *mut $ffi_name, Self::Storage) {
848 let v_ptr = unsafe {
849 let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
850
851 std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *mut $ffi_name, v_ptr, t.len());
852 std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut());
853
854 v_ptr
855 };
856
857 (v_ptr, (std::marker::PhantomData, None))
858 }
859
860 fn to_glib_full_from_slice(t: &[Self]) -> *mut *mut $ffi_name {
861 unsafe {
862 let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
863
864 for (i, s) in t.iter().enumerate() {
865 std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
866 }
867 std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut());
868
869 v_ptr
870 }
871 }
872 }
873
874 #[doc(hidden)]
875 impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
876 type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*mut $ffi_name>>);
877
878 fn to_glib_none_from_slice(t: &'a [Self]) -> (*const *mut $ffi_name, Self::Storage) {
879 let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *mut $ffi_name>::to_glib_none_from_slice(t);
880 (ptr as *const *mut $ffi_name, stash)
881 }
882
883 fn to_glib_container_from_slice(_: &'a [Self]) -> (*const *mut $ffi_name, Self::Storage) {
884 unimplemented!()
886 }
887
888 fn to_glib_full_from_slice(_: &[Self]) -> *const *mut $ffi_name {
889 unimplemented!()
891 }
892 }
893
894 #[doc(hidden)]
895 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name $(<$($generic),+>)? {
896 #[inline]
897 #[allow(clippy::cast_ptr_alignment)]
898 unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
899 debug_assert!(!ptr.is_null());
900 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
901 $name {
902 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_none(ptr as *mut _)),
903 phantom: std::marker::PhantomData,
904 }
905 }
906 }
907
908 #[doc(hidden)]
909 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name $(<$($generic),+>)? {
910 #[inline]
911 #[allow(clippy::cast_ptr_alignment)]
912 unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
913 debug_assert!(!ptr.is_null());
914 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
915 $name {
916 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_none(ptr as *mut _)),
917 phantom: std::marker::PhantomData,
918 }
919 }
920 }
921
922 #[doc(hidden)]
923 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name $(<$($generic),+>)? {
924 #[inline]
925 #[allow(clippy::cast_ptr_alignment)]
926 unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
927 debug_assert!(!ptr.is_null());
928 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
929 $name {
930 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_full(ptr as *mut _)),
931 phantom: std::marker::PhantomData,
932 }
933 }
934 }
935
936 #[doc(hidden)]
937 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name $(<$($generic),+>)? {
938 #[inline]
939 #[allow(clippy::cast_ptr_alignment)]
940 unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> $crate::translate::Borrowed<Self> {
941 debug_assert!(!ptr.is_null());
942 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
943 $crate::translate::Borrowed::new(
944 $name {
945 inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_borrow::<_, $crate::object::ObjectRef>(ptr as *mut _).into_inner()),
946 phantom: std::marker::PhantomData,
947 }
948 )
949 }
950 }
951
952 #[doc(hidden)]
953 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name $(<$($generic),+>)? {
954 #[inline]
955 #[allow(clippy::cast_ptr_alignment)]
956 unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> $crate::translate::Borrowed<Self> {
957 $crate::translate::from_glib_borrow::<_, Self>(ptr as *mut $ffi_name)
958 }
959 }
960
961 #[doc(hidden)]
962 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
963 unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
964 if num == 0 || ptr.is_null() {
965 return Vec::new();
966 }
967
968 let mut res = Vec::<Self>::with_capacity(num);
969 let res_ptr = res.as_mut_ptr();
970 for i in 0..num {
971 ::std::ptr::write(res_ptr.add(i), $crate::translate::from_glib_none(std::ptr::read(ptr.add(i))));
972 }
973 res.set_len(num);
974 res
975 }
976
977 unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
978 let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
979 $crate::ffi::g_free(ptr as *mut _);
980 res
981 }
982
983 unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
984 if num == 0 || ptr.is_null() {
985 $crate::ffi::g_free(ptr as *mut _);
986 return Vec::new();
987 }
988
989 let mut res = Vec::with_capacity(num);
990 let res_ptr = res.as_mut_ptr();
991 ::std::ptr::copy_nonoverlapping(ptr as *mut Self, res_ptr, num);
992 res.set_len(num);
993 $crate::ffi::g_free(ptr as *mut _);
994 res
995 }
996 }
997
998 #[doc(hidden)]
999 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
1000 unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1001 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1002 }
1003
1004 unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1005 $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1006 }
1007
1008 unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1009 $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1010 }
1011 }
1012
1013 #[doc(hidden)]
1014 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
1015 unsafe fn from_glib_none_num_as_vec(ptr: *const *mut $ffi_name, num: usize) -> Vec<Self> {
1016 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
1017 }
1018
1019 unsafe fn from_glib_container_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1020 unimplemented!()
1022 }
1023
1024 unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1025 unimplemented!()
1027 }
1028 }
1029
1030 #[doc(hidden)]
1031 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
1032 unsafe fn from_glib_none_as_vec(ptr: *const *mut $ffi_name) -> Vec<Self> {
1033 $crate::translate::FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
1034 }
1035
1036 unsafe fn from_glib_container_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1037 unimplemented!()
1039 }
1040
1041 unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1042 unimplemented!()
1044 }
1045 }
1046
1047 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::StaticType for $name $(<$($generic),+>)? {
1048 #[inline]
1049 fn static_type() -> $crate::types::Type {
1050 #[allow(unused_unsafe)]
1051 #[allow(clippy::macro_metavars_in_unsafe)]
1052 unsafe { $crate::translate::from_glib($get_type_expr) }
1053 }
1054 }
1055
1056 #[doc(hidden)]
1057 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueType for $name $(<$($generic),+>)? {
1058 type Type = $name $(<$($generic),+>)?;
1059 }
1060
1061 #[doc(hidden)]
1062 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueTypeOptional for $name $(<$($generic),+>)? { }
1063
1064 #[doc(hidden)]
1065 unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for $name $(<$($generic),+>)? {
1066 type Checker = $crate::object::ObjectValueTypeChecker<Self>;
1067
1068 #[inline]
1069 unsafe fn from_value(value: &'a $crate::Value) -> Self {
1070 let ptr = $crate::gobject_ffi::g_value_dup_object($crate::translate::ToGlibPtr::to_glib_none(value).0);
1071 debug_assert!(!ptr.is_null());
1072 debug_assert_ne!((*ptr).ref_count, 0);
1073 <Self as $crate::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(ptr as *mut $ffi_name)
1074 }
1075 }
1076
1077 #[doc(hidden)]
1078 unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for &'a $name $(<$($generic),+>)? {
1079 type Checker = $crate::object::ObjectValueTypeChecker<Self>;
1080
1081 #[inline]
1082 unsafe fn from_value(value: &'a $crate::Value) -> Self {
1083 let value = &*(value as *const $crate::Value as *const $crate::gobject_ffi::GValue);
1084 <$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))
1085 }
1086 }
1087
1088 #[doc(hidden)]
1089 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValue for $name $(<$($generic),+>)? {
1090 #[inline]
1091 fn to_value(&self) -> $crate::Value {
1092 unsafe {
1093 let mut value = $crate::Value::from_type_unchecked(<Self as $crate::prelude::StaticType>::static_type());
1094 $crate::gobject_ffi::g_value_take_object(
1095 $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1096 $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(self) as *mut _,
1097 );
1098 value
1099 }
1100 }
1101
1102 #[inline]
1103 fn value_type(&self) -> $crate::Type {
1104 <Self as $crate::prelude::StaticType>::static_type()
1105 }
1106 }
1107
1108 #[doc(hidden)]
1109 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? ::std::convert::From<$name $(<$($generic),+>)?> for $crate::Value {
1110 #[inline]
1111 fn from(o: $name $(<$($generic),+>)?) -> Self {
1112 unsafe {
1113 let mut value = $crate::Value::from_type_unchecked(<$name $(<$($generic),+>)? as $crate::prelude::StaticType>::static_type());
1114 $crate::gobject_ffi::g_value_take_object(
1115 $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1116 $crate::translate::IntoGlibPtr::<*mut $ffi_name>::into_glib_ptr(o) as *mut _,
1117 );
1118 value
1119 }
1120 }
1121 }
1122
1123 #[doc(hidden)]
1124 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValueOptional for $name $(<$($generic),+>)? {
1125 #[inline]
1126 fn to_value_optional(s: Option<&Self>) -> $crate::Value {
1127 let mut value = $crate::Value::for_value_type::<Self>();
1128 unsafe {
1129 $crate::gobject_ffi::g_value_take_object(
1130 $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1131 $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(&s) as *mut _,
1132 );
1133 }
1134
1135 value
1136 }
1137 }
1138
1139 $crate::glib_object_wrapper!(@weak_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?);
1140
1141 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::HasParamSpec for $name $(<$($generic),+>)? {
1142 type ParamSpec = $crate::ParamSpecObject;
1143 type SetValue = Self;
1144 type BuilderFn = fn(&str) -> $crate::ParamSpecObjectBuilder<Self>;
1145
1146 fn param_spec_builder() -> Self::BuilderFn {
1147 |name| Self::ParamSpec::builder(name)
1148 }
1149 }
1150 };
1151
1152 (@weak_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?) => {
1153 #[doc(hidden)]
1154 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::clone::Downgrade for $name $(<$($generic),+>)? {
1155 type Weak = $crate::object::WeakRef<Self>;
1156
1157 #[inline]
1158 fn downgrade(&self) -> Self::Weak {
1159 <Self as $crate::object::ObjectExt>::downgrade(&self)
1160 }
1161 }
1162 };
1163
1164 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => { };
1165
1166 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1167 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$super_name> for $name $(<$($generic),+>)? { }
1168
1169 #[doc(hidden)]
1170 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $super_name {
1171 #[inline]
1172 fn from(v: $name $(<$($generic),+>)?) -> Self {
1173 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1174 }
1175 }
1176
1177 #[doc(hidden)]
1178 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$super_name> for $name $(<$($generic),+>)? {
1179 #[inline]
1180 fn as_ref(&self) -> &$super_name {
1181 $crate::object::Cast::upcast_ref(self)
1182 }
1183 }
1184
1185 #[doc(hidden)]
1186 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$super_name> for $name $(<$($generic),+>)? {
1187 #[inline]
1188 fn borrow(&self) -> &$super_name {
1189 $crate::object::Cast::upcast_ref(self)
1190 }
1191 }
1192 };
1193
1194 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1195 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1196 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1197 };
1198
1199 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => {
1201 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, );
1202 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1203 type Parent = $crate::object::Object;
1204 }
1205 };
1206
1207 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1209 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1210 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1211 type Parent = $super_name;
1212 }
1213 };
1214
1215 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1217 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1218 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1219 type Parent = $super_name;
1220 }
1221 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1222 };
1223
1224 (@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) => {
1227 $crate::glib_object_wrapper!(
1228 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1229 @type_ $get_type_expr);
1230
1231 #[doc(hidden)]
1232 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1233 };
1234
1235 (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty,
1236 @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1237 $crate::glib_object_wrapper!(
1238 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, @ffi_class std::os::raw::c_void,
1239 @type_ $get_type_expr, @extends [$($extends)*], @implements [$($implements)*]
1240 );
1241 };
1242
1243 (@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,
1244 @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1245 $crate::glib_object_wrapper!(
1246 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1247 @type_ $get_type_expr
1248 );
1249
1250 $crate::glib_object_wrapper!(@munch_first_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($extends)*);
1251
1252 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1253
1254 #[doc(hidden)]
1255 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1256 #[inline]
1257 fn as_ref(&self) -> &$crate::object::Object {
1258 $crate::object::Cast::upcast_ref(self)
1259 }
1260 }
1261
1262 #[doc(hidden)]
1263 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1264 #[inline]
1265 fn borrow(&self) -> &$crate::object::Object {
1266 $crate::object::Cast::upcast_ref(self)
1267 }
1268 }
1269
1270 #[doc(hidden)]
1271 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1272 #[inline]
1273 fn from(v: $name $(<$($generic),+>)?) -> Self {
1274 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1275 }
1276 }
1277
1278 #[doc(hidden)]
1279 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1280
1281 #[doc(hidden)]
1282 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1283 };
1284
1285 (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1288 @extends [], @implements [$($implements:tt)*]) => {
1289 $crate::glib_object_wrapper!(
1290 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1291 $subclass, (),
1292 <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1293 @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1294 @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1295 @extends [], @implements [$($implements)*]
1296 );
1297
1298 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1299 type Subclass = $subclass;
1300 }
1301 };
1302
1303 (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1304 @extends [$($extends:tt)+], @implements [$($implements:tt)*]) => {
1305 $crate::glib_object_wrapper!(
1306 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1307 $subclass, <$subclass as $crate::subclass::types::ObjectSubclass>::ParentType,
1308 <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1309 @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1310 @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1311 @extends [$($extends)*], @implements [$($implements)*]
1312 );
1313
1314 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1315 type Subclass = $subclass;
1316 }
1317 };
1318
1319 (@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty,
1320 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1321 $crate::glib_object_wrapper!(
1322 @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $ffi_name, @ffi_class std::os::raw::c_void,
1323 @type_ $get_type_expr, @requires [$($requires)*]
1324 );
1325 };
1326
1327 (@object_interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $iface:ty,
1328 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1329 $crate::glib_object_wrapper!(
1330 @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $iface, <$iface as $crate::subclass::interface::ObjectInterface>::Instance,
1331 @ffi_class <$iface as $crate::subclass::interface::ObjectInterface>::Interface,
1332 @type_ $get_type_expr, @requires [$($requires)*]
1333 );
1334 };
1335
1336 (@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,
1337 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1338 $crate::glib_object_wrapper!(
1339 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, (), $ffi_name, $ffi_class_name,
1340 @type_ $get_type_expr
1341 );
1342 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($requires)*);
1343
1344 #[doc(hidden)]
1345 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1346 #[inline]
1347 fn as_ref(&self) -> &$crate::object::Object {
1348 $crate::object::Cast::upcast_ref(self)
1349 }
1350 }
1351
1352 #[doc(hidden)]
1353 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1354 #[inline]
1355 fn borrow(&self) -> &$crate::object::Object {
1356 $crate::object::Cast::upcast_ref(self)
1357 }
1358 }
1359
1360 #[doc(hidden)]
1361 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1362 #[inline]
1363 fn from(v: $name $(<$($generic),+>)?) -> Self {
1364 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1365 }
1366 }
1367
1368 #[doc(hidden)]
1369 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1370
1371 #[doc(hidden)]
1372 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsInterface for $name $(<$($generic),+>)? { }
1373 };
1374}
1375
1376glib_object_wrapper!(@object
1377 [doc = "The base class in the object hierarchy."]
1378 pub Object, *mut std::os::raw::c_void, (), gobject_ffi::GObject, @ffi_class gobject_ffi::GObjectClass, @type_ gobject_ffi::g_object_get_type()
1379);
1380pub type ObjectClass = Class<Object>;
1381
1382impl Object {
1383 pub const NONE: Option<&'static Object> = None;
1384
1385 #[track_caller]
1392 #[allow(clippy::new_ret_no_self)]
1393 pub fn new<T: IsA<Object> + IsClass>() -> T {
1394 let object = Object::with_type(T::static_type());
1395 unsafe { object.unsafe_cast() }
1396 }
1397
1398 #[track_caller]
1405 pub fn with_type(type_: Type) -> Object {
1406 Object::with_mut_values(type_, &mut [])
1407 }
1408
1409 #[track_caller]
1418 pub fn with_mut_values(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1419 #[cfg(feature = "gio")]
1420 unsafe {
1421 let iface_type = from_glib(gio_sys::g_initable_get_type());
1422 if type_.is_a(iface_type) {
1423 panic!("Can't instantiate type '{type_}' implementing `gio::Initable`. Use `gio::Initable::new()`");
1424 }
1425 let iface_type = from_glib(gio_sys::g_async_initable_get_type());
1426 if type_.is_a(iface_type) {
1427 panic!("Can't instantiate type '{type_}' implementing `gio::AsyncInitable`. Use `gio::AsyncInitable::new()`");
1428 }
1429 }
1430
1431 unsafe { Object::new_internal(type_, properties) }
1432 }
1433
1434 #[track_caller]
1446 pub unsafe fn new_internal(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1447 if !type_.is_a(Object::static_type()) {
1448 panic!("Can't instantiate non-GObject type '{type_}'");
1449 }
1450
1451 if gobject_ffi::g_type_test_flags(
1452 type_.into_glib(),
1453 gobject_ffi::G_TYPE_FLAG_INSTANTIATABLE,
1454 ) == ffi::GFALSE
1455 {
1456 panic!("Can't instantiate type '{type_}'");
1457 }
1458
1459 if gobject_ffi::g_type_test_flags(type_.into_glib(), gobject_ffi::G_TYPE_FLAG_ABSTRACT)
1460 != ffi::GFALSE
1461 {
1462 panic!("Can't instantiate abstract type '{type_}'");
1463 }
1464
1465 let mut property_names = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1466 let mut property_values = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1467
1468 if !properties.is_empty() {
1469 let klass = ObjectClass::from_type(type_)
1470 .unwrap_or_else(|| panic!("Can't retrieve class for type '{type_}'"));
1471
1472 for (idx, (name, value)) in properties.iter_mut().enumerate() {
1473 let pspec = klass
1474 .find_property(name)
1475 .unwrap_or_else(|| panic!("Can't find property '{name}' for type '{type_}'"));
1476
1477 if (pspec.flags().contains(crate::ParamFlags::CONSTRUCT)
1478 || pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
1479 && property_names[0..idx]
1480 .iter()
1481 .any(|other_name| pspec.name().as_ptr() == *other_name)
1482 {
1483 panic!("Can't set construct property '{name}' for type '{type_}' twice");
1484 }
1485
1486 validate_property_type(type_, true, &pspec, value);
1490
1491 property_names.push(pspec.name().as_ptr());
1492 property_values.push(*value.to_glib_none().0);
1493 }
1494 }
1495
1496 let ptr = gobject_ffi::g_object_new_with_properties(
1497 type_.into_glib(),
1498 properties.len() as u32,
1499 mut_override(property_names.as_ptr() as *const *const _),
1500 property_values.as_ptr(),
1501 );
1502
1503 if ptr.is_null() {
1504 panic!("Can't instantiate object for type '{type_}'");
1505 } else if type_.is_a(InitiallyUnowned::static_type()) {
1506 from_glib_none(ptr)
1508 } else {
1509 from_glib_full(ptr)
1510 }
1511 }
1512
1513 pub fn builder<'a, O: IsA<Object> + IsClass>() -> ObjectBuilder<'a, O> {
1516 ObjectBuilder::new(O::static_type())
1517 }
1518
1519 pub fn builder_with_type<'a>(type_: Type) -> ObjectBuilder<'a, Object> {
1522 ObjectBuilder::new(type_)
1523 }
1524}
1525
1526#[must_use = "builder doesn't do anything unless built"]
1527pub struct ObjectBuilder<'a, O> {
1528 type_: Type,
1529 properties: smallvec::SmallVec<[(&'a str, Value); 16]>,
1530 phantom: PhantomData<O>,
1531}
1532
1533impl<'a, O: IsA<Object> + IsClass> ObjectBuilder<'a, O> {
1534 #[inline]
1535 fn new(type_: Type) -> Self {
1536 ObjectBuilder {
1537 type_,
1538 properties: smallvec::SmallVec::new(),
1539 phantom: PhantomData,
1540 }
1541 }
1542
1543 #[inline]
1546 pub fn type_(&self) -> Type {
1547 self.type_
1548 }
1549
1550 pub fn property(self, name: &'a str, value: impl Into<Value>) -> Self {
1555 let ObjectBuilder {
1556 type_,
1557 mut properties,
1558 ..
1559 } = self;
1560 properties.push((name, value.into()));
1561
1562 ObjectBuilder {
1563 type_,
1564 properties,
1565 phantom: PhantomData,
1566 }
1567 }
1568
1569 #[inline]
1575 pub fn property_if(self, name: &'a str, value: impl Into<Value>, predicate: bool) -> Self {
1576 if predicate {
1577 self.property(name, value)
1578 } else {
1579 self
1580 }
1581 }
1582
1583 #[inline]
1588 pub fn property_if_some(self, name: &'a str, value: Option<impl Into<Value>>) -> Self {
1589 if let Some(value) = value {
1590 self.property(name, value)
1591 } else {
1592 self
1593 }
1594 }
1595
1596 #[inline]
1601 pub fn property_from_iter<V: ValueType + Into<Value> + FromIterator<Value>>(
1602 self,
1603 name: &'a str,
1604 iter: impl IntoIterator<Item = impl Into<Value>>,
1605 ) -> Self {
1606 let iter = iter.into_iter().map(|item| item.into());
1607 self.property(name, V::from_iter(iter))
1608 }
1609
1610 #[inline]
1616 pub fn property_if_not_empty<V: ValueType + Into<Value> + FromIterator<Value>>(
1617 self,
1618 name: &'a str,
1619 iter: impl IntoIterator<Item = impl Into<Value>>,
1620 ) -> Self {
1621 let mut iter = iter.into_iter().peekable();
1622 if iter.peek().is_some() {
1623 let iter = iter.map(|item| item.into());
1624 self.property(name, V::from_iter(iter))
1625 } else {
1626 self
1627 }
1628 }
1629
1630 #[track_caller]
1638 #[inline]
1639 pub fn build(mut self) -> O {
1640 let object = Object::with_mut_values(self.type_, &mut self.properties);
1641 unsafe { object.unsafe_cast::<O>() }
1642 }
1643}
1644
1645#[must_use = "if unused the property notifications will immediately be thawed"]
1646pub struct PropertyNotificationFreezeGuard(ObjectRef);
1647
1648impl Drop for PropertyNotificationFreezeGuard {
1649 #[doc(alias = "g_object_thaw_notify")]
1650 #[inline]
1651 fn drop(&mut self) {
1652 unsafe { gobject_ffi::g_object_thaw_notify(self.0.to_glib_none().0) }
1653 }
1654}
1655
1656pub trait ObjectExt: ObjectType {
1657 fn is<T: StaticType>(&self) -> bool;
1660
1661 #[doc(alias = "get_type")]
1664 fn type_(&self) -> Type;
1665
1666 #[doc(alias = "get_object_class")]
1671 fn object_class(&self) -> &ObjectClass;
1672
1673 #[doc(alias = "get_class")]
1675 fn class(&self) -> &Class<Self>
1676 where
1677 Self: IsClass;
1678
1679 #[doc(alias = "get_class_of")]
1684 fn class_of<T: IsClass>(&self) -> Option<&Class<T>>;
1685
1686 #[doc(alias = "get_interface")]
1691 fn interface<T: IsInterface>(&self) -> Option<InterfaceRef<T>>;
1692
1693 #[doc(alias = "g_object_set_property")]
1701 fn set_property(&self, property_name: &str, value: impl Into<Value>);
1702
1703 #[doc(alias = "g_object_set_property")]
1711 fn set_property_from_value(&self, property_name: &str, value: &Value);
1712
1713 #[doc(alias = "g_object_set")]
1721 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]);
1722
1723 #[doc(alias = "g_object_set")]
1731 fn set_properties_from_value(&self, property_values: &[(&str, Value)]);
1732
1733 #[doc(alias = "get_property")]
1740 #[doc(alias = "g_object_get_property")]
1741 fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V;
1742
1743 #[doc(alias = "get_property")]
1750 #[doc(alias = "g_object_get_property")]
1751 fn property_value(&self, property_name: &str) -> Value;
1752
1753 fn has_property(&self, property_name: &str) -> bool;
1756
1757 fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool;
1760
1761 #[doc(alias = "get_property_type")]
1766 fn property_type(&self, property_name: &str) -> Option<Type>;
1767
1768 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec>;
1771
1772 fn list_properties(&self) -> PtrSlice<crate::ParamSpec>;
1775
1776 #[doc(alias = "g_object_freeze_notify")]
1781 fn freeze_notify(&self) -> PropertyNotificationFreezeGuard;
1782
1783 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD);
1790
1791 #[doc(alias = "get_qdata")]
1801 unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>>;
1802
1803 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>;
1812
1813 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD);
1820
1821 #[doc(alias = "get_data")]
1831 unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>>;
1832
1833 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD>;
1842
1843 #[doc(alias = "g_signal_handler_block")]
1848 fn block_signal(&self, handler_id: &SignalHandlerId);
1849
1850 #[doc(alias = "g_signal_handler_unblock")]
1853 fn unblock_signal(&self, handler_id: &SignalHandlerId);
1854
1855 #[doc(alias = "g_signal_stop_emission")]
1858 fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>);
1859
1860 #[doc(alias = "g_signal_stop_emission_by_name")]
1863 fn stop_signal_emission_by_name(&self, signal_name: &str);
1864
1865 fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1875 where
1876 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1877
1878 fn connect_id<F>(
1890 &self,
1891 signal_id: SignalId,
1892 details: Option<Quark>,
1893 after: bool,
1894 callback: F,
1895 ) -> SignalHandlerId
1896 where
1897 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1898
1899 fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1912 where
1913 F: Fn(&[Value]) -> Option<Value> + 'static;
1914
1915 fn connect_local_id<F>(
1928 &self,
1929 signal_id: SignalId,
1930 details: Option<Quark>,
1931 after: bool,
1932 callback: F,
1933 ) -> SignalHandlerId
1934 where
1935 F: Fn(&[Value]) -> Option<Value> + 'static;
1936
1937 unsafe fn connect_unsafe<F>(
1955 &self,
1956 signal_name: &str,
1957 after: bool,
1958 callback: F,
1959 ) -> SignalHandlerId
1960 where
1961 F: Fn(&[Value]) -> Option<Value>;
1962
1963 unsafe fn connect_unsafe_id<F>(
1982 &self,
1983 signal_id: SignalId,
1984 details: Option<Quark>,
1985 after: bool,
1986 callback: F,
1987 ) -> SignalHandlerId
1988 where
1989 F: Fn(&[Value]) -> Option<Value>;
1990
1991 #[doc(alias = "g_signal_connect_closure")]
2006 #[doc(alias = "g_signal_connect_object")]
2007 fn connect_closure(
2008 &self,
2009 signal_name: &str,
2010 after: bool,
2011 closure: RustClosure,
2012 ) -> SignalHandlerId;
2013
2014 #[doc(alias = "g_signal_connect_closure_by_id")]
2025 fn connect_closure_id(
2026 &self,
2027 signal_id: SignalId,
2028 details: Option<Quark>,
2029 after: bool,
2030 closure: RustClosure,
2031 ) -> SignalHandlerId;
2032
2033 #[doc(alias = "g_object_watch_closure")]
2040 fn watch_closure(&self, closure: &impl AsRef<Closure>);
2041
2042 #[doc(alias = "g_signal_emitv")]
2052 fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R;
2053
2054 fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value>;
2057
2058 #[doc(alias = "g_signal_emit_by_name")]
2068 fn emit_by_name<R: TryFromClosureReturnValue>(
2069 &self,
2070 signal_name: &str,
2071 args: &[&dyn ToValue],
2072 ) -> R;
2073
2074 fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value>;
2084
2085 fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2095 &self,
2096 signal_name: &str,
2097 details: Quark,
2098 args: &[&dyn ToValue],
2099 ) -> R;
2100
2101 fn emit_by_name_with_details_and_values(
2111 &self,
2112 signal_name: &str,
2113 details: Quark,
2114 args: &[Value],
2115 ) -> Option<Value>;
2116
2117 fn emit_with_details<R: TryFromClosureReturnValue>(
2127 &self,
2128 signal_id: SignalId,
2129 details: Quark,
2130 args: &[&dyn ToValue],
2131 ) -> R;
2132
2133 fn emit_with_details_and_values(
2143 &self,
2144 signal_id: SignalId,
2145 details: Quark,
2146 args: &[Value],
2147 ) -> Option<Value>;
2148
2149 #[doc(alias = "g_signal_handler_disconnect")]
2152 fn disconnect(&self, handler_id: SignalHandlerId);
2153
2154 fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
2160 &self,
2161 name: Option<&str>,
2162 f: F,
2163 ) -> SignalHandlerId;
2164
2165 fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
2174 &self,
2175 name: Option<&str>,
2176 f: F,
2177 ) -> SignalHandlerId;
2178
2179 unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
2193 &self,
2194 name: Option<&str>,
2195 f: F,
2196 ) -> SignalHandlerId;
2197
2198 #[doc(alias = "g_object_notify")]
2203 fn notify(&self, property_name: &str);
2204
2205 #[doc(alias = "g_object_notify_by_pspec")]
2210 fn notify_by_pspec(&self, pspec: &crate::ParamSpec);
2211
2212 fn downgrade(&self) -> WeakRef<Self>;
2215
2216 #[doc(alias = "g_object_weak_ref")]
2219 #[doc(alias = "connect_drop")]
2220 fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2221
2222 #[doc(alias = "g_object_weak_ref")]
2228 #[doc(alias = "connect_drop")]
2229 fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2230
2231 fn bind_property<'a, 'f, 't, O: ObjectType>(
2239 &'a self,
2240 source_property: &'a str,
2241 target: &'a O,
2242 target_property: &'a str,
2243 ) -> BindingBuilder<'a, 'f, 't>;
2244
2245 fn ref_count(&self) -> u32;
2248
2249 #[doc(alias = "g_object_run_dispose")]
2261 unsafe fn run_dispose(&self);
2262}
2263
2264impl<T: ObjectType> ObjectExt for T {
2265 #[inline]
2266 fn is<U: StaticType>(&self) -> bool {
2267 self.type_().is_a(U::static_type())
2268 }
2269
2270 #[inline]
2271 fn type_(&self) -> Type {
2272 self.object_class().type_()
2273 }
2274
2275 #[inline]
2276 fn object_class(&self) -> &ObjectClass {
2277 unsafe {
2278 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2279 let klass = (*obj).g_type_instance.g_class as *const ObjectClass;
2280 &*klass
2281 }
2282 }
2283
2284 #[inline]
2285 fn class(&self) -> &Class<Self>
2286 where
2287 Self: IsClass,
2288 {
2289 unsafe {
2290 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2291 let klass = (*obj).g_type_instance.g_class as *const Class<Self>;
2292 &*klass
2293 }
2294 }
2295
2296 #[inline]
2297 fn class_of<U: IsClass>(&self) -> Option<&Class<U>> {
2298 if !self.is::<U>() {
2299 return None;
2300 }
2301
2302 unsafe {
2303 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2304 let klass = (*obj).g_type_instance.g_class as *const Class<U>;
2305 Some(&*klass)
2306 }
2307 }
2308
2309 #[inline]
2310 fn interface<U: IsInterface>(&self) -> Option<InterfaceRef<U>> {
2311 Interface::from_class(self.object_class())
2312 }
2313
2314 #[track_caller]
2315 fn set_property(&self, property_name: &str, value: impl Into<Value>) {
2316 let pspec = self.find_property(property_name).unwrap_or_else(|| {
2317 panic!(
2318 "property '{property_name}' of type '{}' not found",
2319 self.type_()
2320 )
2321 });
2322
2323 let mut property_value = value.into();
2324 validate_property_type(self.type_(), false, &pspec, &mut property_value);
2325 unsafe {
2326 gobject_ffi::g_object_set_property(
2327 self.as_object_ref().to_glib_none().0,
2328 pspec.name().as_ptr() as *const _,
2329 property_value.to_glib_none().0,
2330 );
2331 }
2332 }
2333
2334 #[track_caller]
2335 fn set_property_from_value(&self, property_name: &str, value: &Value) {
2336 let pspec = match self.find_property(property_name) {
2337 Some(pspec) => pspec,
2338 None => {
2339 panic!(
2340 "property '{property_name}' of type '{}' not found",
2341 self.type_()
2342 );
2343 }
2344 };
2345
2346 let mut property_value = value.clone();
2350 validate_property_type(self.type_(), false, &pspec, &mut property_value);
2351 unsafe {
2352 gobject_ffi::g_object_set_property(
2353 self.as_object_ref().to_glib_none().0,
2354 pspec.name().as_ptr() as *const _,
2355 property_value.to_glib_none().0,
2356 );
2357 }
2358 }
2359
2360 #[track_caller]
2361 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]) {
2362 let params = property_values
2363 .iter()
2364 .map(|&(name, value)| {
2365 let pspec = self.find_property(name).unwrap_or_else(|| {
2366 panic!("Can't find property '{name}' for type '{}'", self.type_());
2367 });
2368
2369 let mut value = value.to_value();
2370 validate_property_type(self.type_(), false, &pspec, &mut value);
2371 (pspec.name().as_ptr(), value)
2372 })
2373 .collect::<smallvec::SmallVec<[_; 10]>>();
2374
2375 let _guard = self.freeze_notify();
2376 for (name, value) in params {
2377 unsafe {
2378 gobject_ffi::g_object_set_property(
2379 self.as_object_ref().to_glib_none().0,
2380 name as *const _,
2381 value.to_glib_none().0,
2382 );
2383 }
2384 }
2385 }
2386
2387 #[track_caller]
2388 fn set_properties_from_value(&self, property_values: &[(&str, Value)]) {
2389 let params = property_values
2390 .iter()
2391 .map(|(name, value)| {
2392 let pspec = self.find_property(name).unwrap_or_else(|| {
2393 panic!("Can't find property '{name}' for type '{}'", self.type_());
2394 });
2395
2396 let mut value = value.clone();
2397 validate_property_type(self.type_(), false, &pspec, &mut value);
2398 (pspec.name().as_ptr(), value)
2399 })
2400 .collect::<smallvec::SmallVec<[_; 10]>>();
2401
2402 let _guard = self.freeze_notify();
2403 for (name, value) in params {
2404 unsafe {
2405 gobject_ffi::g_object_set_property(
2406 self.as_object_ref().to_glib_none().0,
2407 name as *const _,
2408 value.to_glib_none().0,
2409 );
2410 }
2411 }
2412 }
2413
2414 #[track_caller]
2415 fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V {
2416 let prop = self.property_value(property_name);
2417 let v = prop
2418 .get_owned::<V>()
2419 .unwrap_or_else(|e| panic!("Failed to get cast value to a different type {e}"));
2420
2421 v
2422 }
2423
2424 #[track_caller]
2425 fn property_value(&self, property_name: &str) -> Value {
2426 let pspec = self.find_property(property_name).unwrap_or_else(|| {
2427 panic!(
2428 "property '{property_name}' of type '{}' not found",
2429 self.type_()
2430 )
2431 });
2432
2433 if !pspec.flags().contains(crate::ParamFlags::READABLE) {
2434 panic!(
2435 "property '{property_name}' of type '{}' is not readable",
2436 self.type_()
2437 );
2438 }
2439
2440 unsafe {
2441 let mut value = Value::from_type_unchecked(pspec.value_type());
2442 gobject_ffi::g_object_get_property(
2443 self.as_object_ref().to_glib_none().0,
2444 pspec.name().as_ptr() as *const _,
2445 value.to_glib_none_mut().0,
2446 );
2447
2448 if !value.type_().is_valid() {
2450 panic!(
2451 "Failed to get property value for property '{property_name}' of type '{}'",
2452 self.type_()
2453 )
2454 }
2455
2456 value
2457 }
2458 }
2459
2460 fn has_property(&self, property_name: &str) -> bool {
2461 self.object_class().has_property(property_name)
2462 }
2463
2464 fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool {
2465 self.object_class()
2466 .has_property_with_type(property_name, type_)
2467 }
2468
2469 fn property_type(&self, property_name: &str) -> Option<Type> {
2470 self.object_class().property_type(property_name)
2471 }
2472
2473 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
2474 self.object_class().find_property(property_name)
2475 }
2476
2477 fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
2478 self.object_class().list_properties()
2479 }
2480
2481 #[inline]
2482 fn freeze_notify(&self) -> PropertyNotificationFreezeGuard {
2483 unsafe { gobject_ffi::g_object_freeze_notify(self.as_object_ref().to_glib_none().0) };
2484 PropertyNotificationFreezeGuard(self.as_object_ref().clone())
2485 }
2486
2487 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD) {
2488 unsafe extern "C" fn drop_value<QD>(ptr: ffi::gpointer) {
2489 debug_assert!(!ptr.is_null());
2490 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2491 drop(value)
2492 }
2493
2494 let ptr = Box::into_raw(Box::new(value)) as ffi::gpointer;
2495 gobject_ffi::g_object_set_qdata_full(
2496 self.as_object_ref().to_glib_none().0,
2497 key.into_glib(),
2498 ptr,
2499 Some(drop_value::<QD>),
2500 );
2501 }
2502
2503 unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>> {
2504 ptr::NonNull::new(gobject_ffi::g_object_get_qdata(
2505 self.as_object_ref().to_glib_none().0,
2506 key.into_glib(),
2507 ) as *mut QD)
2508 }
2509
2510 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD> {
2511 let ptr = gobject_ffi::g_object_steal_qdata(
2512 self.as_object_ref().to_glib_none().0,
2513 key.into_glib(),
2514 );
2515 if ptr.is_null() {
2516 None
2517 } else {
2518 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2519 Some(*value)
2520 }
2521 }
2522
2523 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD) {
2524 self.set_qdata::<QD>(Quark::from_str(key), value)
2525 }
2526
2527 unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>> {
2528 self.qdata::<QD>(Quark::from_str(key))
2529 }
2530
2531 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD> {
2532 self.steal_qdata::<QD>(Quark::from_str(key))
2533 }
2534
2535 fn block_signal(&self, handler_id: &SignalHandlerId) {
2536 unsafe {
2537 gobject_ffi::g_signal_handler_block(
2538 self.as_object_ref().to_glib_none().0,
2539 handler_id.as_raw(),
2540 );
2541 }
2542 }
2543
2544 fn unblock_signal(&self, handler_id: &SignalHandlerId) {
2545 unsafe {
2546 gobject_ffi::g_signal_handler_unblock(
2547 self.as_object_ref().to_glib_none().0,
2548 handler_id.as_raw(),
2549 );
2550 }
2551 }
2552
2553 fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>) {
2554 unsafe {
2555 gobject_ffi::g_signal_stop_emission(
2556 self.as_object_ref().to_glib_none().0,
2557 signal_id.into_glib(),
2558 detail.into_glib(),
2559 );
2560 }
2561 }
2562
2563 fn stop_signal_emission_by_name(&self, signal_name: &str) {
2564 unsafe {
2565 signal_name.run_with_gstr(|signal_name| {
2566 gobject_ffi::g_signal_stop_emission_by_name(
2567 self.as_object_ref().to_glib_none().0,
2568 signal_name.as_ptr(),
2569 )
2570 });
2571 }
2572 }
2573
2574 #[track_caller]
2575 fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2576 where
2577 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2578 {
2579 unsafe { self.connect_unsafe(signal_name, after, callback) }
2580 }
2581
2582 #[track_caller]
2583 fn connect_id<F>(
2584 &self,
2585 signal_id: SignalId,
2586 details: Option<Quark>,
2587 after: bool,
2588 callback: F,
2589 ) -> SignalHandlerId
2590 where
2591 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2592 {
2593 unsafe { self.connect_unsafe_id(signal_id, details, after, callback) }
2594 }
2595
2596 #[track_caller]
2597 fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2598 where
2599 F: Fn(&[Value]) -> Option<Value> + 'static,
2600 {
2601 let callback = crate::thread_guard::ThreadGuard::new(callback);
2602
2603 unsafe {
2604 self.connect_unsafe(signal_name, after, move |values| {
2605 (callback.get_ref())(values)
2606 })
2607 }
2608 }
2609
2610 #[track_caller]
2611 fn connect_local_id<F>(
2612 &self,
2613 signal_id: SignalId,
2614 details: Option<Quark>,
2615 after: bool,
2616 callback: F,
2617 ) -> SignalHandlerId
2618 where
2619 F: Fn(&[Value]) -> Option<Value> + 'static,
2620 {
2621 let callback = crate::thread_guard::ThreadGuard::new(callback);
2622
2623 unsafe {
2624 self.connect_unsafe_id(signal_id, details, after, move |values| {
2625 (callback.get_ref())(values)
2626 })
2627 }
2628 }
2629
2630 #[track_caller]
2631 unsafe fn connect_unsafe<F>(
2632 &self,
2633 signal_name: &str,
2634 after: bool,
2635 callback: F,
2636 ) -> SignalHandlerId
2637 where
2638 F: Fn(&[Value]) -> Option<Value>,
2639 {
2640 let type_ = self.type_();
2641 let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2642 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2643 self.connect_unsafe_id(signal_id, details, after, callback)
2644 }
2645
2646 #[track_caller]
2647 unsafe fn connect_unsafe_id<F>(
2648 &self,
2649 signal_id: SignalId,
2650 details: Option<Quark>,
2651 after: bool,
2652 callback: F,
2653 ) -> SignalHandlerId
2654 where
2655 F: Fn(&[Value]) -> Option<Value>,
2656 {
2657 let signal_query = signal_id.query();
2658 let type_ = self.type_();
2659 let return_type: Type = signal_query.return_type().into();
2660 let signal_name = signal_id.name();
2661 let signal_query_type = signal_query.type_();
2662
2663 let closure = if return_type == Type::UNIT {
2664 Closure::new_unsafe(move |values| {
2665 let ret = callback(values);
2666 if let Some(ret) = ret {
2667 panic!(
2668 "Signal '{signal_name}' of type '{type_}' required no return value but got value of type '{}'",
2669 ret.type_()
2670 );
2671 }
2672 None
2673 })
2674 } else {
2675 Closure::new_unsafe(move |values| {
2676 let mut ret = callback(values).unwrap_or_else(|| {
2677 panic!(
2678 "Signal '{signal_name}' of type '{type_}' required return value of type '{}' but got None",
2679 return_type.name()
2680 );
2681 });
2682 let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
2683 mut_override(ret.to_glib_none().0),
2684 return_type.into_glib(),
2685 ));
2686
2687 if valid_type {
2688 return Some(ret);
2689 }
2690
2691 if let Err(got) = coerce_object_type(&mut ret, return_type) {
2692 panic!(
2693 "Signal '{signal_name}' of type '{type_}' required return value of type '{return_type}' but got '{got}'",
2694 );
2695 };
2696 Some(ret)
2697 })
2698 };
2699
2700 assert!(
2701 type_.is_a(signal_query_type),
2702 "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2703 );
2704
2705 let handler = gobject_ffi::g_signal_connect_closure_by_id(
2706 self.as_object_ref().to_glib_none().0,
2707 signal_id.into_glib(),
2708 details.into_glib(),
2709 closure.as_ref().to_glib_none().0,
2710 after.into_glib(),
2711 );
2712
2713 if handler == 0 {
2714 panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2715 }
2716
2717 from_glib(handler)
2718 }
2719
2720 #[track_caller]
2721 fn connect_closure(
2722 &self,
2723 signal_name: &str,
2724 after: bool,
2725 closure: RustClosure,
2726 ) -> SignalHandlerId {
2727 let type_ = self.type_();
2728 let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2729 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2730 self.connect_closure_id(signal_id, details, after, closure)
2731 }
2732
2733 #[track_caller]
2734 fn connect_closure_id(
2735 &self,
2736 signal_id: SignalId,
2737 details: Option<Quark>,
2738 after: bool,
2739 closure: RustClosure,
2740 ) -> SignalHandlerId {
2741 let signal_query = signal_id.query();
2742 let type_ = self.type_();
2743 let signal_name = signal_id.name();
2744
2745 let signal_query_type = signal_query.type_();
2746 assert!(
2747 type_.is_a(signal_query_type),
2748 "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2749 );
2750
2751 unsafe {
2752 let handler = gobject_ffi::g_signal_connect_closure_by_id(
2753 self.as_object_ref().to_glib_none().0,
2754 signal_id.into_glib(),
2755 details.into_glib(),
2756 closure.as_ref().to_glib_none().0,
2757 after.into_glib(),
2758 );
2759
2760 if handler == 0 {
2761 panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2762 }
2763
2764 from_glib(handler)
2765 }
2766 }
2767
2768 #[inline]
2769 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
2770 let closure = closure.as_ref();
2771 unsafe {
2772 gobject_ffi::g_object_watch_closure(
2773 self.as_object_ref().to_glib_none().0,
2774 closure.to_glib_none().0,
2775 );
2776 }
2777 }
2778
2779 #[track_caller]
2780 fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R {
2781 let signal_query = signal_id.query();
2782 unsafe {
2783 let type_ = self.type_();
2784
2785 let self_v = {
2786 let mut v = Value::uninitialized();
2787 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2788 gobject_ffi::g_value_set_object(
2789 v.to_glib_none_mut().0,
2790 self.as_object_ref().to_glib_none().0,
2791 );
2792 v
2793 };
2794
2795 let mut args = Iterator::chain(
2796 std::iter::once(self_v),
2797 args.iter().copied().map(ToValue::to_value),
2798 )
2799 .collect::<smallvec::SmallVec<[_; 10]>>();
2800
2801 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2802
2803 let mut return_value = if signal_query.return_type() != Type::UNIT {
2804 Value::from_type_unchecked(signal_query.return_type().into())
2805 } else {
2806 Value::uninitialized()
2807 };
2808 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2809 return_value.to_glib_none_mut().0
2810 } else {
2811 ptr::null_mut()
2812 };
2813
2814 gobject_ffi::g_signal_emitv(
2815 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2816 signal_id.into_glib(),
2817 0,
2818 return_value_ptr,
2819 );
2820
2821 R::try_from_closure_return_value(
2822 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2823 )
2824 .unwrap()
2825 }
2826 }
2827
2828 #[track_caller]
2829 fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value> {
2830 unsafe {
2831 let type_ = self.type_();
2832
2833 let signal_query = signal_id.query();
2834
2835 let self_v = {
2836 let mut v = Value::uninitialized();
2837 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2838 gobject_ffi::g_value_set_object(
2839 v.to_glib_none_mut().0,
2840 self.as_object_ref().to_glib_none().0,
2841 );
2842 v
2843 };
2844
2845 let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
2846 .collect::<smallvec::SmallVec<[_; 10]>>();
2847
2848 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2849
2850 let mut return_value = if signal_query.return_type() != Type::UNIT {
2851 Value::from_type_unchecked(signal_query.return_type().into())
2852 } else {
2853 Value::uninitialized()
2854 };
2855 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2856 return_value.to_glib_none_mut().0
2857 } else {
2858 ptr::null_mut()
2859 };
2860
2861 gobject_ffi::g_signal_emitv(
2862 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2863 signal_id.into_glib(),
2864 0,
2865 return_value_ptr,
2866 );
2867
2868 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
2869 }
2870 }
2871
2872 #[track_caller]
2873 fn emit_by_name<R: TryFromClosureReturnValue>(
2874 &self,
2875 signal_name: &str,
2876 args: &[&dyn ToValue],
2877 ) -> R {
2878 let type_ = self.type_();
2879 let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2880 panic!("Signal '{signal_name}' of type '{type_}' not found");
2881 });
2882 self.emit(signal_id, args)
2883 }
2884
2885 #[track_caller]
2886 fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value> {
2887 let type_ = self.type_();
2888 let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2889 panic!("Signal '{signal_name}' of type '{type_}' not found");
2890 });
2891 self.emit_with_values(signal_id, args)
2892 }
2893
2894 #[track_caller]
2895 fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2896 &self,
2897 signal_name: &str,
2898 details: Quark,
2899 args: &[&dyn ToValue],
2900 ) -> R {
2901 let type_ = self.type_();
2902 let signal_id = SignalId::lookup(signal_name, type_)
2903 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2904 self.emit_with_details(signal_id, details, args)
2905 }
2906
2907 #[track_caller]
2908 fn emit_by_name_with_details_and_values(
2909 &self,
2910 signal_name: &str,
2911 details: Quark,
2912 args: &[Value],
2913 ) -> Option<Value> {
2914 let type_ = self.type_();
2915 let signal_id = SignalId::lookup(signal_name, type_)
2916 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2917 self.emit_with_details_and_values(signal_id, details, args)
2918 }
2919
2920 #[track_caller]
2921 fn emit_with_details<R: TryFromClosureReturnValue>(
2922 &self,
2923 signal_id: SignalId,
2924 details: Quark,
2925 args: &[&dyn ToValue],
2926 ) -> R {
2927 let signal_query = signal_id.query();
2928 assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2929
2930 unsafe {
2931 let type_ = self.type_();
2932
2933 let self_v = {
2934 let mut v = Value::uninitialized();
2935 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2936 gobject_ffi::g_value_set_object(
2937 v.to_glib_none_mut().0,
2938 self.as_object_ref().to_glib_none().0,
2939 );
2940 v
2941 };
2942
2943 let mut args = Iterator::chain(
2944 std::iter::once(self_v),
2945 args.iter().copied().map(ToValue::to_value),
2946 )
2947 .collect::<smallvec::SmallVec<[_; 10]>>();
2948
2949 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2950
2951 let mut return_value = if signal_query.return_type() != Type::UNIT {
2952 Value::from_type_unchecked(signal_query.return_type().into())
2953 } else {
2954 Value::uninitialized()
2955 };
2956 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2957 return_value.to_glib_none_mut().0
2958 } else {
2959 ptr::null_mut()
2960 };
2961
2962 gobject_ffi::g_signal_emitv(
2963 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2964 signal_id.into_glib(),
2965 details.into_glib(),
2966 return_value_ptr,
2967 );
2968
2969 R::try_from_closure_return_value(
2970 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2971 )
2972 .unwrap()
2973 }
2974 }
2975
2976 #[track_caller]
2977 fn emit_with_details_and_values(
2978 &self,
2979 signal_id: SignalId,
2980 details: Quark,
2981 args: &[Value],
2982 ) -> Option<Value> {
2983 let signal_query = signal_id.query();
2984 assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2985
2986 unsafe {
2987 let type_ = self.type_();
2988
2989 let self_v = {
2990 let mut v = Value::uninitialized();
2991 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2992 gobject_ffi::g_value_set_object(
2993 v.to_glib_none_mut().0,
2994 self.as_object_ref().to_glib_none().0,
2995 );
2996 v
2997 };
2998
2999 let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
3000 .collect::<smallvec::SmallVec<[_; 10]>>();
3001
3002 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
3003
3004 let mut return_value = if signal_query.return_type() != Type::UNIT {
3005 Value::from_type_unchecked(signal_query.return_type().into())
3006 } else {
3007 Value::uninitialized()
3008 };
3009 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
3010 return_value.to_glib_none_mut().0
3011 } else {
3012 ptr::null_mut()
3013 };
3014
3015 gobject_ffi::g_signal_emitv(
3016 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
3017 signal_id.into_glib(),
3018 details.into_glib(),
3019 return_value_ptr,
3020 );
3021
3022 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
3023 }
3024 }
3025
3026 #[inline]
3027 fn disconnect(&self, handler_id: SignalHandlerId) {
3028 unsafe {
3029 gobject_ffi::g_signal_handler_disconnect(
3030 self.as_object_ref().to_glib_none().0,
3031 handler_id.as_raw(),
3032 );
3033 }
3034 }
3035
3036 fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
3037 &self,
3038 name: Option<&str>,
3039 f: F,
3040 ) -> SignalHandlerId {
3041 unsafe { self.connect_notify_unsafe(name, f) }
3042 }
3043
3044 fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
3045 &self,
3046 name: Option<&str>,
3047 f: F,
3048 ) -> SignalHandlerId {
3049 let f = crate::thread_guard::ThreadGuard::new(f);
3050
3051 unsafe {
3052 self.connect_notify_unsafe(name, move |s, pspec| {
3053 (f.get_ref())(s, pspec);
3054 })
3055 }
3056 }
3057
3058 unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
3059 &self,
3060 name: Option<&str>,
3061 f: F,
3062 ) -> SignalHandlerId {
3063 unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &crate::ParamSpec)>(
3064 this: *mut gobject_ffi::GObject,
3065 param_spec: *mut gobject_ffi::GParamSpec,
3066 f: ffi::gpointer,
3067 ) where
3068 P: ObjectType,
3069 {
3070 let f: &F = &*(f as *const F);
3071 f(
3072 Object::from_glib_borrow(this).unsafe_cast_ref(),
3073 &from_glib_borrow(param_spec),
3074 )
3075 }
3076
3077 let signal_name = if let Some(name) = name {
3078 format!("notify::{name}\0")
3079 } else {
3080 "notify\0".into()
3081 };
3082
3083 let f: Box<F> = Box::new(f);
3084 crate::signal::connect_raw(
3085 self.as_object_ref().to_glib_none().0,
3086 signal_name.as_ptr() as *const _,
3087 Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
3088 notify_trampoline::<Self, F> as *const (),
3089 )),
3090 Box::into_raw(f),
3091 )
3092 }
3093
3094 #[inline]
3095 fn notify(&self, property_name: &str) {
3096 unsafe {
3097 property_name.run_with_gstr(|property_name| {
3098 gobject_ffi::g_object_notify(
3099 self.as_object_ref().to_glib_none().0,
3100 property_name.as_ptr(),
3101 )
3102 });
3103 }
3104 }
3105
3106 #[inline]
3107 fn notify_by_pspec(&self, pspec: &crate::ParamSpec) {
3108 unsafe {
3109 gobject_ffi::g_object_notify_by_pspec(
3110 self.as_object_ref().to_glib_none().0,
3111 pspec.to_glib_none().0,
3112 );
3113 }
3114 }
3115
3116 #[inline]
3117 fn downgrade(&self) -> WeakRef<T> {
3118 unsafe {
3119 let w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3120 gobject_ffi::g_weak_ref_init(
3121 mut_override(&*w.0),
3122 self.as_object_ref().to_glib_none().0,
3123 );
3124 w
3125 }
3126 }
3127
3128 fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<T> {
3129 WeakRefNotify::new(self, f)
3130 }
3131
3132 fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<T> {
3133 let callback = crate::thread_guard::ThreadGuard::new(f);
3134
3135 WeakRefNotify::new(self, move || callback.into_inner()())
3136 }
3137
3138 fn bind_property<'a, 'f, 't, O: ObjectType>(
3139 &'a self,
3140 source_property: &'a str,
3141 target: &'a O,
3142 target_property: &'a str,
3143 ) -> BindingBuilder<'a, 'f, 't> {
3144 BindingBuilder::new(self, source_property, target, target_property)
3145 }
3146
3147 #[inline]
3148 fn ref_count(&self) -> u32 {
3149 let stash = self.as_object_ref().to_glib_none();
3150 let ptr: *mut gobject_ffi::GObject = stash.0;
3151
3152 unsafe { ffi::g_atomic_int_get(&(*ptr).ref_count as *const u32 as *const i32) as u32 }
3153 }
3154
3155 #[inline]
3156 unsafe fn run_dispose(&self) {
3157 gobject_ffi::g_object_run_dispose(self.as_ptr() as *mut _);
3158 }
3159}
3160
3161#[doc(hidden)]
3164pub struct WatchedObject<T: ObjectType>(ptr::NonNull<T::GlibType>);
3165
3166#[doc(hidden)]
3167unsafe impl<T: ObjectType + Send + Sync> Send for WatchedObject<T> {}
3168
3169#[doc(hidden)]
3170unsafe impl<T: ObjectType + Send + Sync> Sync for WatchedObject<T> {}
3171
3172#[doc(hidden)]
3173impl<T: ObjectType> WatchedObject<T> {
3174 pub fn new(obj: &T) -> Self {
3175 Self(unsafe { ptr::NonNull::new_unchecked(obj.as_ptr()) })
3176 }
3177 #[inline]
3183 pub unsafe fn borrow(&self) -> Borrowed<T>
3184 where
3185 T: FromGlibPtrBorrow<*mut <T as ObjectType>::GlibType>,
3186 {
3187 from_glib_borrow(self.0.as_ptr())
3188 }
3189}
3190
3191#[doc(hidden)]
3192pub trait Watchable<T: ObjectType> {
3193 fn watched_object(&self) -> WatchedObject<T>;
3194 fn watch_closure(&self, closure: &impl AsRef<Closure>);
3195}
3196
3197#[doc(hidden)]
3198impl<T: ObjectType> Watchable<T> for T {
3199 fn watched_object(&self) -> WatchedObject<T> {
3200 WatchedObject::new(self)
3201 }
3202 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3203 ObjectExt::watch_closure(self, closure)
3204 }
3205}
3206
3207#[doc(hidden)]
3208impl<T: ObjectType> Watchable<T> for BorrowedObject<'_, T> {
3209 fn watched_object(&self) -> WatchedObject<T> {
3210 WatchedObject::new(self)
3211 }
3212 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3213 ObjectExt::watch_closure(&**self, closure)
3214 }
3215}
3216
3217#[doc(hidden)]
3218impl<T: ObjectType> Watchable<T> for &T {
3219 fn watched_object(&self) -> WatchedObject<T> {
3220 WatchedObject::new(*self)
3221 }
3222 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3223 ObjectExt::watch_closure(*self, closure)
3224 }
3225}
3226
3227#[track_caller]
3230fn validate_property_type(
3231 type_: Type,
3232 allow_construct_only: bool,
3233 pspec: &crate::ParamSpec,
3234 property_value: &mut Value,
3235) {
3236 if !pspec.flags().contains(crate::ParamFlags::WRITABLE)
3237 || (!allow_construct_only && pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
3238 {
3239 panic!(
3240 "property '{}' of type '{type_}' is not writable",
3241 pspec.name(),
3242 );
3243 }
3244
3245 unsafe {
3246 let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
3251 mut_override(property_value.to_glib_none().0),
3252 pspec.value_type().into_glib(),
3253 ));
3254
3255 if !valid_type {
3256 if let Err(got) = coerce_object_type(property_value, pspec.value_type()) {
3257 panic!(
3258 "property '{}' of type '{type_}' can't be set from the given type (expected: '{}', got: '{got}')",
3259 pspec.name(),
3260 pspec.value_type(),
3261 );
3262 }
3263 }
3264
3265 let changed: bool = from_glib(gobject_ffi::g_param_value_validate(
3266 pspec.to_glib_none().0,
3267 property_value.to_glib_none_mut().0,
3268 ));
3269 let change_allowed = pspec.flags().contains(crate::ParamFlags::LAX_VALIDATION);
3270 if changed && !change_allowed {
3271 panic!(
3272 "property '{}' of type '{type_}' can't be set from given value, it is invalid or out of range",
3273 pspec.name(),
3274 );
3275 }
3276 }
3277}
3278
3279fn coerce_object_type(property_value: &mut Value, type_: Type) -> Result<(), Type> {
3285 match property_value.get::<Option<Object>>() {
3287 Ok(Some(obj)) if !(obj.type_().is_a(type_)) => Err(obj.type_()),
3288 Ok(_) => {
3289 property_value.inner.g_type = type_.into_glib();
3290 Ok(())
3291 }
3292 Err(_) => Err(property_value.type_()),
3293 }
3294}
3295
3296#[track_caller]
3297fn validate_signal_arguments(type_: Type, signal_query: &SignalQuery, args: &mut [Value]) {
3298 let signal_name = signal_query.signal_name();
3299
3300 if signal_query.n_params() != args.len() as u32 {
3301 panic!(
3302 "Incompatible number of arguments for signal '{signal_name}' of type '{type_}' (expected {}, got {})",
3303 signal_query.n_params(),
3304 args.len(),
3305 );
3306 }
3307
3308 let param_types = Iterator::zip(args.iter_mut(), signal_query.param_types());
3309
3310 for (i, (arg, param_type)) in param_types.enumerate() {
3311 let param_type: Type = (*param_type).into();
3312 if param_type != arg.type_() {
3313 coerce_object_type(arg, param_type).unwrap_or_else(|got|
3314 panic!(
3315 "Incompatible argument type in argument {i} for signal '{signal_name}' of type '{type_}' (expected {param_type}, got {got})",
3316 )
3317 );
3318 }
3319 }
3320}
3321
3322pub unsafe trait ObjectClassExt {
3324 fn has_property(&self, property_name: &str) -> bool {
3327 self.find_property(property_name).is_some()
3328 }
3329
3330 fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool {
3334 self.property_type(property_name)
3335 .is_some_and(|ptype| ptype.is_a(type_))
3336 }
3337
3338 #[doc(alias = "get_property_type")]
3343 fn property_type(&self, property_name: &str) -> Option<Type> {
3344 self.find_property(property_name)
3345 .map(|pspec| pspec.value_type())
3346 }
3347
3348 #[doc(alias = "g_object_class_find_property")]
3351 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
3352 unsafe {
3353 let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3354
3355 property_name.run_with_gstr(|property_name| {
3356 from_glib_none(gobject_ffi::g_object_class_find_property(
3357 klass as *mut _,
3358 property_name.as_ptr(),
3359 ))
3360 })
3361 }
3362 }
3363
3364 #[doc(alias = "g_object_class_list_properties")]
3367 fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
3368 unsafe {
3369 let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3370
3371 let mut n_properties = 0;
3372
3373 let props =
3374 gobject_ffi::g_object_class_list_properties(klass as *mut _, &mut n_properties);
3375 PtrSlice::from_glib_container_num(props, n_properties as usize, true)
3376 }
3377 }
3378}
3379
3380unsafe impl<T: ObjectType + IsClass> ObjectClassExt for Class<T> {}
3381
3382wrapper! {
3383 #[doc(alias = "GInitiallyUnowned")]
3384 pub struct InitiallyUnowned(Object<gobject_ffi::GInitiallyUnowned, gobject_ffi::GInitiallyUnownedClass>);
3385
3386 match fn {
3387 type_ => || gobject_ffi::g_initially_unowned_get_type(),
3388 }
3389}
3390
3391type WeakRefNotifyData = ManuallyDrop<Pin<Box<Box<dyn FnOnce() + 'static>>>>;
3396
3397pub struct WeakRefNotify<T: ObjectType> {
3400 object: WeakRef<T>,
3401 data: WeakRefNotifyData,
3402}
3403
3404unsafe extern "C" fn notify_func(data: ffi::gpointer, _obj: *mut gobject_ffi::GObject) {
3405 let callback: Box<Box<dyn FnOnce()>> = Box::from_raw(data as *mut _);
3408
3409 (*callback)()
3412}
3413
3414impl<T: ObjectType> WeakRefNotify<T> {
3415 fn new<F: FnOnce() + 'static>(obj: &T, f: F) -> WeakRefNotify<T> {
3416 let data: WeakRefNotifyData = ManuallyDrop::new(Box::pin(Box::new(f)));
3417 let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&data).get_ref();
3418
3419 unsafe {
3420 gobject_ffi::g_object_weak_ref(
3422 obj.as_ptr() as *mut gobject_ffi::GObject,
3423 Some(notify_func),
3424 data_ptr as *mut _,
3425 );
3426 }
3427
3428 let object = obj.downgrade();
3429
3430 WeakRefNotify { object, data }
3431 }
3432
3433 pub fn upgrade(&self) -> Option<T> {
3438 self.object.upgrade()
3439 }
3440
3441 #[doc(alias = "g_object_weak_unref")]
3442 pub fn disconnect(mut self) {
3443 if let Some(obj) = self.object.upgrade() {
3445 let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&self.data).get_ref();
3446
3447 unsafe {
3448 gobject_ffi::g_object_weak_unref(
3450 obj.as_ptr() as *mut gobject_ffi::GObject,
3451 Some(notify_func),
3452 data_ptr as *mut _,
3453 );
3454
3455 ManuallyDrop::drop(&mut self.data);
3459 }
3460 }
3461 }
3462}
3463
3464#[derive(Debug)]
3467#[doc(alias = "GWeakRef")]
3468pub struct WeakRef<T: ObjectType>(Pin<Box<gobject_ffi::GWeakRef>>, PhantomData<*mut T>);
3469
3470impl<T: ObjectType> WeakRef<T> {
3471 #[inline]
3476 pub fn new() -> WeakRef<T> {
3477 unsafe {
3478 let mut w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3479 gobject_ffi::g_weak_ref_init(
3480 Pin::as_mut(&mut w.0).get_unchecked_mut(),
3481 ptr::null_mut(),
3482 );
3483 w
3484 }
3485 }
3486
3487 #[doc(alias = "g_weak_ref_set")]
3490 #[inline]
3491 pub fn set(&self, obj: Option<&T>) {
3492 unsafe {
3493 gobject_ffi::g_weak_ref_set(
3494 mut_override(Pin::as_ref(&self.0).get_ref()),
3495 obj.map_or(std::ptr::null_mut(), |obj| {
3496 obj.as_object_ref().to_glib_none().0
3497 }),
3498 );
3499 }
3500 }
3501
3502 #[inline]
3508 pub fn upgrade(&self) -> Option<T> {
3509 unsafe {
3510 let ptr = gobject_ffi::g_weak_ref_get(mut_override(Pin::as_ref(&self.0).get_ref()));
3511 if ptr.is_null() {
3512 None
3513 } else {
3514 let obj: Object = from_glib_full(ptr);
3515 Some(T::unsafe_from(obj.into()))
3516 }
3517 }
3518 }
3519}
3520
3521impl<T: ObjectType> Drop for WeakRef<T> {
3522 #[inline]
3523 fn drop(&mut self) {
3524 unsafe {
3525 gobject_ffi::g_weak_ref_clear(Pin::as_mut(&mut self.0).get_unchecked_mut());
3526 }
3527 }
3528}
3529
3530impl<T: ObjectType> Clone for WeakRef<T> {
3531 #[inline]
3532 fn clone(&self) -> Self {
3533 unsafe {
3534 let o = self.upgrade();
3535
3536 let mut c = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3537 gobject_ffi::g_weak_ref_init(
3538 Pin::as_mut(&mut c.0).get_unchecked_mut(),
3539 o.to_glib_none().0 as *mut gobject_ffi::GObject,
3540 );
3541
3542 c
3543 }
3544 }
3545}
3546
3547impl<T: ObjectType> Default for WeakRef<T> {
3548 #[inline]
3549 fn default() -> Self {
3550 Self::new()
3551 }
3552}
3553
3554unsafe impl<T: ObjectType + Sync + Sync> Sync for WeakRef<T> {}
3555unsafe impl<T: ObjectType + Send + Sync> Send for WeakRef<T> {}
3556
3557impl<T: ObjectType> PartialEq for WeakRef<T> {
3558 #[inline]
3559 fn eq(&self, other: &Self) -> bool {
3560 unsafe { self.0.priv_.p == other.0.priv_.p }
3561 }
3562}
3563
3564impl<T: ObjectType> PartialEq<T> for WeakRef<T> {
3565 #[inline]
3566 fn eq(&self, other: &T) -> bool {
3567 unsafe { self.0.priv_.p == other.as_ptr() as *mut std::os::raw::c_void }
3568 }
3569}
3570
3571impl<T: ObjectType> PartialOrd for WeakRef<T> {
3572 #[inline]
3573 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
3574 unsafe { self.0.priv_.p.partial_cmp(&other.0.priv_.p) }
3575 }
3576}
3577
3578#[derive(Debug)]
3586pub struct SendWeakRef<T: ObjectType>(WeakRef<T>, usize);
3587
3588impl<T: ObjectType> SendWeakRef<T> {
3589 #[inline]
3590 pub fn into_weak_ref(self) -> WeakRef<T> {
3591 assert!(
3592 self.1 == thread_id(),
3593 "SendWeakRef dereferenced on a different thread",
3594 );
3595
3596 self.0
3597 }
3598}
3599
3600impl<T: ObjectType> ops::Deref for SendWeakRef<T> {
3601 type Target = WeakRef<T>;
3602
3603 #[inline]
3604 fn deref(&self) -> &WeakRef<T> {
3605 assert!(
3606 self.1 == thread_id(),
3607 "SendWeakRef dereferenced on a different thread"
3608 );
3609
3610 &self.0
3611 }
3612}
3613
3614impl<T: ObjectType> Clone for SendWeakRef<T> {
3616 #[inline]
3617 fn clone(&self) -> Self {
3618 Self(self.0.clone(), self.1)
3619 }
3620}
3621
3622impl<T: ObjectType> Default for SendWeakRef<T> {
3623 #[inline]
3624 fn default() -> Self {
3625 Self::from(WeakRef::new())
3626 }
3627}
3628
3629impl<T: ObjectType> From<WeakRef<T>> for SendWeakRef<T> {
3630 #[inline]
3631 fn from(v: WeakRef<T>) -> SendWeakRef<T> {
3632 SendWeakRef(v, thread_id())
3633 }
3634}
3635
3636unsafe impl<T: ObjectType> Sync for SendWeakRef<T> {}
3637unsafe impl<T: ObjectType> Send for SendWeakRef<T> {}
3638
3639type TransformFn<'b> =
3640 Option<Box<dyn Fn(&'b crate::Binding, &'b Value) -> Option<Value> + Send + Sync + 'static>>;
3641
3642#[must_use = "The builder must be built to be used"]
3645pub struct BindingBuilder<'a, 'f, 't> {
3646 source: &'a ObjectRef,
3647 source_property: &'a str,
3648 target: &'a ObjectRef,
3649 target_property: &'a str,
3650 flags: crate::BindingFlags,
3651 transform_from: TransformFn<'f>,
3652 transform_to: TransformFn<'t>,
3653}
3654
3655impl fmt::Debug for BindingBuilder<'_, '_, '_> {
3656 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3657 f.debug_struct("BindingBuilder")
3658 .field("source", &self.source)
3659 .field("source_property", &self.source_property)
3660 .field("target", &self.target)
3661 .field("target_property", &self.target_property)
3662 .field("flags", &self.flags)
3663 .finish()
3664 }
3665}
3666
3667impl<'a, 'f, 't> BindingBuilder<'a, 'f, 't> {
3668 fn new(
3669 source: &'a impl ObjectType,
3670 source_property: &'a str,
3671 target: &'a impl ObjectType,
3672 target_property: &'a str,
3673 ) -> Self {
3674 Self {
3675 source: source.as_object_ref(),
3676 source_property,
3677 target: target.as_object_ref(),
3678 target_property,
3679 flags: crate::BindingFlags::DEFAULT,
3680 transform_to: None,
3681 transform_from: None,
3682 }
3683 }
3684
3685 pub fn transform_from_with_values<
3691 F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3692 >(
3693 self,
3694 func: F,
3695 ) -> Self {
3696 Self {
3697 transform_from: Some(Box::new(func)),
3698 ..self
3699 }
3700 }
3701
3702 pub fn transform_from<
3708 S: FromValue<'f>,
3709 T: Into<Value>,
3710 F: Fn(&'f crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3711 >(
3712 self,
3713 func: F,
3714 ) -> Self {
3715 Self {
3716 transform_from: Some(Box::new(move |binding, from_value| {
3717 let from_value = from_value.get().expect("Wrong value type");
3718 func(binding, from_value).map(|r| r.into())
3719 })),
3720 ..self
3721 }
3722 }
3723
3724 pub fn transform_to_with_values<
3730 F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3731 >(
3732 self,
3733 func: F,
3734 ) -> Self {
3735 Self {
3736 transform_to: Some(Box::new(func)),
3737 ..self
3738 }
3739 }
3740
3741 pub fn transform_to<
3747 S: FromValue<'t>,
3748 T: Into<Value>,
3749 F: Fn(&'t crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3750 >(
3751 self,
3752 func: F,
3753 ) -> Self {
3754 Self {
3755 transform_to: Some(Box::new(move |binding, from_value| {
3756 let from_value = from_value.get().expect("Wrong value type");
3757 func(binding, from_value).map(|r| r.into())
3758 })),
3759 ..self
3760 }
3761 }
3762
3763 pub fn flags(self, flags: crate::BindingFlags) -> Self {
3766 Self { flags, ..self }
3767 }
3768
3769 pub fn bidirectional(mut self) -> Self {
3772 self.flags |= crate::BindingFlags::BIDIRECTIONAL;
3773 self
3774 }
3775
3776 pub fn sync_create(mut self) -> Self {
3779 self.flags |= crate::BindingFlags::SYNC_CREATE;
3780 self
3781 }
3782
3783 pub fn invert_boolean(mut self) -> Self {
3786 self.flags |= crate::BindingFlags::INVERT_BOOLEAN;
3787 self
3788 }
3789
3790 #[track_caller]
3796 pub fn build(self) -> crate::Binding {
3797 unsafe extern "C" fn transform_to_trampoline(
3798 binding: *mut gobject_ffi::GBinding,
3799 from_value: *const gobject_ffi::GValue,
3800 to_value: *mut gobject_ffi::GValue,
3801 user_data: ffi::gpointer,
3802 ) -> ffi::gboolean {
3803 let transform_data = &*(user_data
3804 as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3805
3806 match (transform_data.0.as_ref().unwrap())(
3807 &from_glib_borrow(binding),
3808 &*(from_value as *const Value),
3809 ) {
3810 None => false,
3811 Some(res) => {
3812 assert!(
3813 res.type_().is_a(transform_data.3.value_type()),
3814 "Target property {} expected type {} but transform_to function returned {}",
3815 transform_data.3.name(),
3816 transform_data.3.value_type(),
3817 res.type_()
3818 );
3819 *to_value = res.into_raw();
3820 true
3821 }
3822 }
3823 .into_glib()
3824 }
3825
3826 unsafe extern "C" fn transform_from_trampoline(
3827 binding: *mut gobject_ffi::GBinding,
3828 from_value: *const gobject_ffi::GValue,
3829 to_value: *mut gobject_ffi::GValue,
3830 user_data: ffi::gpointer,
3831 ) -> ffi::gboolean {
3832 let transform_data = &*(user_data
3833 as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3834
3835 match (transform_data.1.as_ref().unwrap())(
3836 &from_glib_borrow(binding),
3837 &*(from_value as *const Value),
3838 ) {
3839 None => false,
3840 Some(res) => {
3841 assert!(
3842 res.type_().is_a(transform_data.2.value_type()),
3843 "Source property {} expected type {} but transform_from function returned {}",
3844 transform_data.2.name(),
3845 transform_data.2.value_type(),
3846 res.type_()
3847 );
3848 *to_value = res.into_raw();
3849 true
3850 }
3851 }
3852 .into_glib()
3853 }
3854
3855 unsafe extern "C" fn free_transform_data(data: ffi::gpointer) {
3856 let _ = Box::from_raw(
3857 data as *mut (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec),
3858 );
3859 }
3860
3861 unsafe {
3862 let source = Object {
3863 inner: TypedObjectRef::new(self.source.clone()),
3864 phantom: std::marker::PhantomData,
3865 };
3866 let target = Object {
3867 inner: TypedObjectRef::new(self.target.clone()),
3868 phantom: std::marker::PhantomData,
3869 };
3870
3871 let source_property = source
3872 .find_property(self.source_property)
3873 .unwrap_or_else(|| {
3874 panic!(
3875 "Source property {} on type {} not found",
3876 self.source_property,
3877 source.type_()
3878 );
3879 });
3880 let target_property = target
3881 .find_property(self.target_property)
3882 .unwrap_or_else(|| {
3883 panic!(
3884 "Target property {} on type {} not found",
3885 self.target_property,
3886 target.type_()
3887 );
3888 });
3889
3890 let source_property_name = source_property.name().as_ptr();
3891 let target_property_name = target_property.name().as_ptr();
3892
3893 let have_transform_to = self.transform_to.is_some();
3894 let have_transform_from = self.transform_from.is_some();
3895 let transform_data = if have_transform_to || have_transform_from {
3896 Box::into_raw(Box::new((
3897 self.transform_to,
3898 self.transform_from,
3899 source_property,
3900 target_property,
3901 )))
3902 } else {
3903 ptr::null_mut()
3904 };
3905
3906 from_glib_none(gobject_ffi::g_object_bind_property_full(
3907 source.to_glib_none().0,
3908 source_property_name as *const _,
3909 target.to_glib_none().0,
3910 target_property_name as *const _,
3911 self.flags.into_glib(),
3912 if have_transform_to {
3913 Some(transform_to_trampoline)
3914 } else {
3915 None
3916 },
3917 if have_transform_from {
3918 Some(transform_from_trampoline)
3919 } else {
3920 None
3921 },
3922 transform_data as ffi::gpointer,
3923 if transform_data.is_null() {
3924 None
3925 } else {
3926 Some(free_transform_data)
3927 },
3928 ))
3929 }
3930 }
3931}
3932
3933#[repr(transparent)]
3936pub struct Class<T: IsClass>(T::GlibClassType);
3937
3938impl<T: IsClass> Class<T> {
3939 #[doc(alias = "get_type")]
3945 #[inline]
3946 pub fn type_(&self) -> Type {
3947 unsafe {
3948 let klass = self as *const _ as *const gobject_ffi::GTypeClass;
3951 from_glib((*klass).g_type)
3952 }
3953 }
3954
3955 #[inline]
3958 pub fn upcast_ref<U: IsClass>(&self) -> &Class<U>
3959 where
3960 T: IsA<U>,
3961 {
3962 unsafe {
3963 let klass = self as *const _ as *const Class<U>;
3964 &*klass
3965 }
3966 }
3967
3968 #[inline]
3971 pub fn upcast_ref_mut<U: IsClass>(&mut self) -> &mut Class<U>
3972 where
3973 T: IsA<U>,
3974 {
3975 unsafe {
3976 let klass = self as *mut _ as *mut Class<U>;
3977 &mut *klass
3978 }
3979 }
3980
3981 #[inline]
3985 pub fn downcast_ref<U: IsClass + IsA<T>>(&self) -> Option<&Class<U>> {
3986 if !self.type_().is_a(U::static_type()) {
3987 return None;
3988 }
3989
3990 unsafe {
3991 let klass = self as *const _ as *const Class<U>;
3992 Some(&*klass)
3993 }
3994 }
3995
3996 #[inline]
4000 pub fn downcast_ref_mut<U: IsClass + IsA<T>>(&mut self) -> Option<&mut Class<U>> {
4001 if !self.type_().is_a(U::static_type()) {
4002 return None;
4003 }
4004
4005 unsafe {
4006 let klass = self as *mut _ as *mut Class<U>;
4007 Some(&mut *klass)
4008 }
4009 }
4010
4011 #[doc(alias = "g_type_class_ref")]
4016 #[inline]
4017 pub fn from_type(type_: Type) -> Option<ClassRef<'static, T>> {
4018 if !type_.is_a(T::static_type()) {
4019 return None;
4020 }
4021
4022 unsafe {
4023 let ptr = gobject_ffi::g_type_class_ref(type_.into_glib());
4024 if ptr.is_null() {
4025 None
4026 } else {
4027 Some(ClassRef(
4028 ptr::NonNull::new_unchecked(ptr as *mut Self),
4029 true,
4030 PhantomData,
4031 ))
4032 }
4033 }
4034 }
4035
4036 #[doc(alias = "g_type_class_peek_parent")]
4039 #[inline]
4040 pub fn parent(&self) -> Option<ClassRef<T>> {
4041 unsafe {
4042 let ptr = gobject_ffi::g_type_class_peek_parent(&self.0 as *const _ as *mut _);
4043 if ptr.is_null() {
4044 None
4045 } else {
4046 Some(ClassRef(
4047 ptr::NonNull::new_unchecked(ptr as *mut Self),
4048 false,
4049 PhantomData,
4050 ))
4051 }
4052 }
4053 }
4054}
4055
4056unsafe impl<T: IsClass> Send for Class<T> {}
4057unsafe impl<T: IsClass> Sync for Class<T> {}
4058
4059impl<T: IsClass> AsRef<T::GlibClassType> for Class<T> {
4060 #[inline]
4061 fn as_ref(&self) -> &T::GlibClassType {
4062 &self.0
4063 }
4064}
4065
4066impl<T: IsClass> AsMut<T::GlibClassType> for Class<T> {
4067 #[inline]
4068 fn as_mut(&mut self) -> &mut T::GlibClassType {
4069 &mut self.0
4070 }
4071}
4072
4073#[derive(Debug)]
4076pub struct ClassRef<'a, T: IsClass>(ptr::NonNull<Class<T>>, bool, PhantomData<&'a ()>);
4077
4078impl<T: IsClass> ops::Deref for ClassRef<'_, T> {
4079 type Target = Class<T>;
4080
4081 #[inline]
4082 fn deref(&self) -> &Class<T> {
4083 unsafe { self.0.as_ref() }
4084 }
4085}
4086
4087impl<T: IsClass> Drop for ClassRef<'_, T> {
4088 #[inline]
4089 fn drop(&mut self) {
4090 if self.1 {
4091 unsafe {
4092 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
4093 }
4094 }
4095 }
4096}
4097
4098unsafe impl<T: IsClass> Send for ClassRef<'_, T> {}
4099unsafe impl<T: IsClass> Sync for ClassRef<'_, T> {}
4100
4101pub unsafe trait ParentClassIs: IsClass {
4103 type Parent: IsClass;
4104}
4105
4106pub unsafe trait ObjectSubclassIs: IsClass {
4110 type Subclass: ObjectSubclass;
4111}
4112
4113impl<T: ParentClassIs> ops::Deref for Class<T> {
4114 type Target = Class<T::Parent>;
4115
4116 #[inline]
4117 fn deref(&self) -> &Self::Target {
4118 unsafe {
4119 let klass = self as *const _ as *const Self::Target;
4120 &*klass
4121 }
4122 }
4123}
4124
4125impl<T: ParentClassIs> ops::DerefMut for Class<T> {
4126 #[inline]
4127 fn deref_mut(&mut self) -> &mut Self::Target {
4128 unsafe {
4129 let klass = self as *mut _ as *mut Self::Target;
4130 &mut *klass
4131 }
4132 }
4133}
4134
4135pub unsafe trait IsClass: ObjectType {}
4138
4139#[repr(transparent)]
4142pub struct Interface<T: IsInterface>(T::GlibClassType);
4143
4144impl<T: IsInterface> Interface<T> {
4145 #[doc(alias = "get_type")]
4150 #[inline]
4151 pub fn type_(&self) -> Type {
4152 unsafe {
4153 let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4154 from_glib((*klass).g_type)
4155 }
4156 }
4157
4158 #[doc(alias = "get_instance_type")]
4164 #[inline]
4165 pub fn instance_type(&self) -> Type {
4166 unsafe {
4167 let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4170 from_glib((*klass).g_instance_type)
4171 }
4172 }
4173
4174 #[inline]
4179 pub fn from_class<U: IsClass>(klass: &Class<U>) -> Option<InterfaceRef<T>> {
4180 if !klass.type_().is_a(T::static_type()) {
4181 return None;
4182 }
4183
4184 unsafe {
4185 let ptr = gobject_ffi::g_type_interface_peek(
4186 &klass.0 as *const _ as *mut _,
4187 T::static_type().into_glib(),
4188 );
4189 if ptr.is_null() {
4190 None
4191 } else {
4192 Some(InterfaceRef(
4193 ptr::NonNull::new_unchecked(ptr as *mut Self),
4194 false,
4195 PhantomData,
4196 ))
4197 }
4198 }
4199 }
4200
4201 #[inline]
4206 pub fn from_type(type_: Type) -> Option<InterfaceRef<'static, T>> {
4207 if !type_.is_a(Type::INTERFACE) {
4208 return None;
4209 }
4210
4211 unsafe {
4212 let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4213 if ptr.is_null() {
4214 None
4215 } else {
4216 Some(InterfaceRef(
4217 ptr::NonNull::new_unchecked(ptr as *mut Self),
4218 true,
4219 PhantomData,
4220 ))
4221 }
4222 }
4223 }
4224
4225 #[doc(alias = "g_type_default_interface_ref")]
4228 #[allow(clippy::should_implement_trait)]
4229 #[inline]
4230 pub fn default() -> InterfaceRef<'static, T> {
4231 unsafe {
4232 let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4233 debug_assert!(!ptr.is_null());
4234 InterfaceRef(
4235 ptr::NonNull::new_unchecked(ptr as *mut Self),
4236 true,
4237 PhantomData,
4238 )
4239 }
4240 }
4241
4242 #[doc(alias = "g_type_interface_peek_parent")]
4248 #[inline]
4249 pub fn parent(&self) -> Option<InterfaceRef<T>> {
4250 unsafe {
4251 let ptr = gobject_ffi::g_type_interface_peek_parent(&self.0 as *const _ as *mut _);
4252 if ptr.is_null() {
4253 None
4254 } else {
4255 Some(InterfaceRef(
4256 ptr::NonNull::new_unchecked(ptr as *mut Self),
4257 false,
4258 PhantomData,
4259 ))
4260 }
4261 }
4262 }
4263}
4264
4265impl<T: IsA<Object> + IsInterface> Interface<T> {
4266 pub fn has_property(&self, property_name: &str) -> bool {
4269 self.find_property(property_name).is_some()
4270 }
4271
4272 pub fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool {
4276 self.property_type(property_name)
4277 .is_some_and(|ptype| ptype.is_a(type_))
4278 }
4279
4280 #[doc(alias = "get_property_type")]
4285 pub fn property_type(&self, property_name: &str) -> Option<Type> {
4286 self.find_property(property_name)
4287 .map(|pspec| pspec.value_type())
4288 }
4289
4290 #[doc(alias = "g_object_interface_find_property")]
4293 pub fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
4294 unsafe {
4295 let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4296
4297 from_glib_none(gobject_ffi::g_object_interface_find_property(
4298 interface as *mut _,
4299 property_name.to_glib_none().0,
4300 ))
4301 }
4302 }
4303
4304 #[doc(alias = "g_object_interface_list_properties")]
4307 pub fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
4308 unsafe {
4309 let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4310
4311 let mut n_properties = 0;
4312
4313 let props = gobject_ffi::g_object_interface_list_properties(
4314 interface as *mut _,
4315 &mut n_properties,
4316 );
4317 PtrSlice::from_glib_container_num(props, n_properties as usize, true)
4318 }
4319 }
4320}
4321
4322unsafe impl<T: IsInterface> Send for Interface<T> {}
4323unsafe impl<T: IsInterface> Sync for Interface<T> {}
4324
4325impl<T: IsInterface> AsRef<T::GlibClassType> for Interface<T> {
4326 #[inline]
4327 fn as_ref(&self) -> &T::GlibClassType {
4328 &self.0
4329 }
4330}
4331
4332impl<T: IsInterface> AsMut<T::GlibClassType> for Interface<T> {
4333 #[inline]
4334 fn as_mut(&mut self) -> &mut T::GlibClassType {
4335 &mut self.0
4336 }
4337}
4338
4339#[derive(Debug)]
4342pub struct InterfaceRef<'a, T: IsInterface>(ptr::NonNull<Interface<T>>, bool, PhantomData<&'a ()>);
4343
4344impl<T: IsInterface> Drop for InterfaceRef<'_, T> {
4345 #[inline]
4346 fn drop(&mut self) {
4347 if self.1 {
4348 unsafe {
4349 gobject_ffi::g_type_default_interface_unref(self.0.as_ptr() as *mut _);
4350 }
4351 }
4352 }
4353}
4354
4355impl<T: IsInterface> ops::Deref for InterfaceRef<'_, T> {
4356 type Target = Interface<T>;
4357
4358 #[inline]
4359 fn deref(&self) -> &Interface<T> {
4360 unsafe { self.0.as_ref() }
4361 }
4362}
4363
4364unsafe impl<T: IsInterface> Send for InterfaceRef<'_, T> {}
4365unsafe impl<T: IsInterface> Sync for InterfaceRef<'_, T> {}
4366
4367pub unsafe trait IsInterface: ObjectType {}
4370
4371pub struct ObjectValueTypeChecker<T>(std::marker::PhantomData<T>);
4374
4375unsafe impl<T: StaticType> crate::value::ValueTypeChecker for ObjectValueTypeChecker<T> {
4376 type Error = crate::value::ValueTypeMismatchOrNoneError<crate::value::ValueTypeMismatchError>;
4377
4378 fn check(value: &Value) -> Result<(), Self::Error> {
4379 unsafe {
4384 let requested_type = T::static_type().into_glib();
4385 let type_ = value.inner.g_type;
4386
4387 if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4389 let obj = gobject_ffi::g_value_get_object(&value.inner);
4390 if obj.is_null() {
4391 return Err(Self::Error::UnexpectedNone);
4392 } else {
4393 return Ok(());
4394 }
4395 }
4396
4397 if gobject_ffi::g_type_is_a(type_, gobject_ffi::G_TYPE_OBJECT) == ffi::GFALSE {
4399 return Err(crate::value::ValueTypeMismatchError::new(
4400 Type::from_glib(type_),
4401 T::static_type(),
4402 )
4403 .into());
4404 }
4405
4406 let obj = gobject_ffi::g_value_get_object(&value.inner);
4408
4409 if obj.is_null() {
4411 return Err(Self::Error::UnexpectedNone);
4412 }
4413
4414 let type_ = (*(*obj).g_type_instance.g_class).g_type;
4415 if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4417 Ok(())
4418 } else {
4419 Err(crate::value::ValueTypeMismatchError::new(
4420 Type::from_glib(type_),
4421 T::static_type(),
4422 )
4423 .into())
4424 }
4425 }
4426 }
4427}
4428
4429#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4434#[repr(transparent)]
4435pub struct BorrowedObject<'a, T> {
4436 ptr: ptr::NonNull<gobject_ffi::GObject>,
4437 phantom: PhantomData<&'a T>,
4438}
4439
4440unsafe impl<T: Send + Sync> Send for BorrowedObject<'_, T> {}
4441unsafe impl<T: Send + Sync> Sync for BorrowedObject<'_, T> {}
4442
4443impl<'a, T: ObjectType> BorrowedObject<'a, T> {
4444 #[inline]
4451 pub unsafe fn new(ptr: *mut T::GlibType) -> BorrowedObject<'a, T> {
4452 BorrowedObject {
4453 ptr: ptr::NonNull::new_unchecked(ptr as *mut _),
4454 phantom: PhantomData,
4455 }
4456 }
4457
4458 #[inline]
4461 pub fn downgrade(&self) -> <Self as crate::clone::Downgrade>::Weak
4462 where
4463 T: crate::clone::Downgrade,
4464 {
4465 <T as crate::clone::Downgrade>::downgrade(self)
4466 }
4467}
4468
4469impl<T> ops::Deref for BorrowedObject<'_, T> {
4470 type Target = T;
4471
4472 #[inline]
4473 fn deref(&self) -> &T {
4474 unsafe { &*(&self.ptr as *const _ as *const T) }
4475 }
4476}
4477
4478impl<T> AsRef<T> for BorrowedObject<'_, T> {
4479 #[inline]
4480 fn as_ref(&self) -> &T {
4481 unsafe { &*(&self.ptr as *const _ as *const T) }
4482 }
4483}
4484
4485impl<T: PartialEq> PartialEq<T> for BorrowedObject<'_, T> {
4486 #[inline]
4487 fn eq(&self, other: &T) -> bool {
4488 <T as PartialEq>::eq(self, other)
4489 }
4490}
4491
4492impl<T: PartialOrd> PartialOrd<T> for BorrowedObject<'_, T> {
4493 #[inline]
4494 fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
4495 <T as PartialOrd>::partial_cmp(self, other)
4496 }
4497}
4498
4499impl<T: crate::clone::Downgrade + ObjectType> crate::clone::Downgrade for BorrowedObject<'_, T> {
4500 type Weak = <T as crate::clone::Downgrade>::Weak;
4501
4502 #[inline]
4503 fn downgrade(&self) -> Self::Weak {
4504 <T as crate::clone::Downgrade>::downgrade(self)
4505 }
4506}
4507
4508#[cfg(test)]
4509mod tests {
4510 use std::{
4511 cell::Cell,
4512 rc::Rc,
4513 sync::{
4514 atomic::{AtomicBool, Ordering},
4515 Arc,
4516 },
4517 };
4518
4519 use super::*;
4520
4521 #[test]
4522 fn new() {
4523 let obj: Object = Object::new();
4524 drop(obj);
4525 }
4526
4527 #[test]
4528 fn data() {
4529 let obj: Object = Object::new();
4530 unsafe {
4531 obj.set_data::<String>("foo", "hello".into());
4532 let data = obj.data::<String>("foo").unwrap();
4533 assert_eq!(data.as_ref(), "hello");
4534 let data2 = obj.steal_data::<String>("foo").unwrap();
4535 assert_eq!(data2, "hello");
4536 }
4537 }
4538
4539 #[test]
4540 fn weak_ref() {
4541 let obj: Object = Object::new();
4542
4543 let weakref: WeakRef<Object> = WeakRef::new();
4544 weakref.set(Some(&obj));
4545 assert!(weakref.upgrade().is_some());
4546 weakref.set(None);
4547 assert!(weakref.upgrade().is_none());
4548
4549 let weakref = WeakRef::new();
4550 weakref.set(Some(&obj));
4551 assert!(weakref.upgrade().is_some());
4552
4553 drop(obj);
4554 assert!(weakref.upgrade().is_none());
4555 }
4556
4557 #[test]
4558 fn weak_ref_notify() {
4559 let obj: Object = Object::new();
4560
4561 let handle = obj.add_weak_ref_notify(|| {
4562 unreachable!();
4563 });
4564
4565 handle.disconnect();
4566
4567 let called = Arc::new(AtomicBool::new(false));
4568 let called_weak = Arc::downgrade(&called);
4569 let handle = obj.add_weak_ref_notify(move || {
4570 called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4571 });
4572
4573 drop(obj);
4574 assert!(called.load(Ordering::SeqCst));
4575 handle.disconnect();
4576
4577 let obj: Object = Object::new();
4578
4579 let called = Arc::new(AtomicBool::new(false));
4580 let called_weak = Arc::downgrade(&called);
4581 obj.add_weak_ref_notify(move || {
4582 called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4583 });
4584
4585 drop(obj);
4586 assert!(called.load(Ordering::SeqCst));
4587
4588 let obj: Object = Object::new();
4589
4590 let called = Rc::new(Cell::new(false));
4591 let called_weak = Rc::downgrade(&called);
4592 obj.add_weak_ref_notify_local(move || {
4593 called_weak.upgrade().unwrap().set(true);
4594 });
4595
4596 drop(obj);
4597 assert!(called.get());
4598 }
4599
4600 #[test]
4601 fn test_value() {
4602 let obj1: Object = Object::new();
4603 let v = obj1.to_value();
4604 let obj2 = v.get::<&Object>().unwrap();
4605
4606 assert_eq!(obj1.as_ptr(), obj2.as_ptr());
4607 }
4608
4609 #[test]
4610 fn test_borrow_hashing() {
4611 let mut m = std::collections::HashSet::new();
4612 let boxed_object = crate::BoxedAnyObject::new("");
4613
4614 m.insert(boxed_object.clone());
4615
4616 let object: &Object = std::borrow::Borrow::borrow(&boxed_object);
4617 assert_eq!(m.get(object), Some(&boxed_object));
4618 }
4619}