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