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 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$super_name> for $name $(<$($generic),+>)? { }
1180
1181 #[doc(hidden)]
1182 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $super_name {
1183 #[inline]
1184 fn from(v: $name $(<$($generic),+>)?) -> Self {
1185 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1186 }
1187 }
1188
1189 #[doc(hidden)]
1190 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$super_name> for $name $(<$($generic),+>)? {
1191 #[inline]
1192 fn as_ref(&self) -> &$super_name {
1193 $crate::object::Cast::upcast_ref(self)
1194 }
1195 }
1196
1197 #[doc(hidden)]
1198 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$super_name> for $name $(<$($generic),+>)? {
1199 #[inline]
1200 fn borrow(&self) -> &$super_name {
1201 $crate::object::Cast::upcast_ref(self)
1202 }
1203 }
1204 };
1205
1206 (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1207 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1208 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1209 };
1210
1211 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => {
1213 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, );
1214 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1215 type Parent = $crate::object::Object;
1216 }
1217 };
1218
1219 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1221 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1222 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1223 type Parent = $super_name;
1224 }
1225 };
1226
1227 (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1229 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1230 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1231 type Parent = $super_name;
1232 }
1233 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1234 };
1235
1236 (@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) => {
1239 $crate::glib_object_wrapper!(
1240 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1241 @type_ $get_type_expr);
1242
1243 #[doc(hidden)]
1244 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1245 };
1246
1247 (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty,
1248 @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1249 $crate::glib_object_wrapper!(
1250 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, @ffi_class std::os::raw::c_void,
1251 @type_ $get_type_expr, @extends [$($extends)*], @implements [$($implements)*]
1252 );
1253 };
1254
1255 (@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,
1256 @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1257 $crate::glib_object_wrapper!(
1258 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1259 @type_ $get_type_expr
1260 );
1261
1262 $crate::glib_object_wrapper!(@munch_first_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($extends)*);
1263
1264 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1265
1266 #[doc(hidden)]
1267 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1268 #[inline]
1269 fn as_ref(&self) -> &$crate::object::Object {
1270 $crate::object::Cast::upcast_ref(self)
1271 }
1272 }
1273
1274 #[doc(hidden)]
1275 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1276 #[inline]
1277 fn borrow(&self) -> &$crate::object::Object {
1278 $crate::object::Cast::upcast_ref(self)
1279 }
1280 }
1281
1282 #[doc(hidden)]
1283 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1284 #[inline]
1285 fn from(v: $name $(<$($generic),+>)?) -> Self {
1286 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1287 }
1288 }
1289
1290 #[doc(hidden)]
1291 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1292
1293 #[doc(hidden)]
1294 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1295 };
1296
1297 (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1300 @extends [], @implements [$($implements:tt)*]) => {
1301 $crate::glib_object_wrapper!(
1302 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1303 $subclass, (),
1304 <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1305 @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1306 @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1307 @extends [], @implements [$($implements)*]
1308 );
1309
1310 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1311 type Subclass = $subclass;
1312 }
1313 };
1314
1315 (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1316 @extends [$($extends:tt)+], @implements [$($implements:tt)*]) => {
1317 $crate::glib_object_wrapper!(
1318 @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1319 $subclass, <$subclass as $crate::subclass::types::ObjectSubclass>::ParentType,
1320 <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1321 @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1322 @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1323 @extends [$($extends)*], @implements [$($implements)*]
1324 );
1325
1326 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1327 type Subclass = $subclass;
1328 }
1329 };
1330
1331 (@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty,
1332 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1333 $crate::glib_object_wrapper!(
1334 @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $ffi_name, @ffi_class std::os::raw::c_void,
1335 @type_ $get_type_expr, @requires [$($requires)*]
1336 );
1337 };
1338
1339 (@object_interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $iface:ty,
1340 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1341 $crate::glib_object_wrapper!(
1342 @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $iface, <$iface as $crate::subclass::interface::ObjectInterface>::Instance,
1343 @ffi_class <$iface as $crate::subclass::interface::ObjectInterface>::Interface,
1344 @type_ $get_type_expr, @requires [$($requires)*]
1345 );
1346 };
1347
1348 (@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,
1349 @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1350 $crate::glib_object_wrapper!(
1351 @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, (), $ffi_name, $ffi_class_name,
1352 @type_ $get_type_expr
1353 );
1354 $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($requires)*);
1355
1356 #[doc(hidden)]
1357 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1358 #[inline]
1359 fn as_ref(&self) -> &$crate::object::Object {
1360 $crate::object::Cast::upcast_ref(self)
1361 }
1362 }
1363
1364 #[doc(hidden)]
1365 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1366 #[inline]
1367 fn borrow(&self) -> &$crate::object::Object {
1368 $crate::object::Cast::upcast_ref(self)
1369 }
1370 }
1371
1372 #[doc(hidden)]
1373 impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1374 #[inline]
1375 fn from(v: $name $(<$($generic),+>)?) -> Self {
1376 <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1377 }
1378 }
1379
1380 #[doc(hidden)]
1381 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1382
1383 #[doc(hidden)]
1384 unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsInterface for $name $(<$($generic),+>)? { }
1385 };
1386}
1387
1388glib_object_wrapper!(@object
1389 [doc = "The base class in the object hierarchy."]
1390 pub Object, *mut std::os::raw::c_void, (), gobject_ffi::GObject, @ffi_class gobject_ffi::GObjectClass, @type_ gobject_ffi::g_object_get_type()
1391);
1392pub type ObjectClass = Class<Object>;
1393
1394impl Object {
1395 pub const NONE: Option<&'static Object> = None;
1396
1397 #[track_caller]
1404 #[allow(clippy::new_ret_no_self)]
1405 pub fn new<T: IsA<Object> + IsClass>() -> T {
1406 let object = Object::with_type(T::static_type());
1407 unsafe { object.unsafe_cast() }
1408 }
1409
1410 #[track_caller]
1417 pub fn with_type(type_: Type) -> Object {
1418 Object::with_mut_values(type_, &mut [])
1419 }
1420
1421 #[track_caller]
1430 pub fn with_mut_values(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1431 #[cfg(feature = "gio")]
1432 unsafe {
1433 let iface_type = from_glib(gio_sys::g_initable_get_type());
1434 if type_.is_a(iface_type) {
1435 panic!(
1436 "Can't instantiate type '{type_}' implementing `gio::Initable`. Use `gio::Initable::new()`"
1437 );
1438 }
1439 let iface_type = from_glib(gio_sys::g_async_initable_get_type());
1440 if type_.is_a(iface_type) {
1441 panic!(
1442 "Can't instantiate type '{type_}' implementing `gio::AsyncInitable`. Use `gio::AsyncInitable::new()`"
1443 );
1444 }
1445 }
1446
1447 unsafe { Object::new_internal(type_, properties) }
1448 }
1449
1450 #[track_caller]
1462 pub unsafe fn new_internal(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1463 unsafe {
1464 if !type_.is_a(Object::static_type()) {
1465 panic!("Can't instantiate non-GObject type '{type_}'");
1466 }
1467
1468 if gobject_ffi::g_type_test_flags(
1469 type_.into_glib(),
1470 gobject_ffi::G_TYPE_FLAG_INSTANTIATABLE,
1471 ) == ffi::GFALSE
1472 {
1473 panic!("Can't instantiate type '{type_}'");
1474 }
1475
1476 if gobject_ffi::g_type_test_flags(type_.into_glib(), gobject_ffi::G_TYPE_FLAG_ABSTRACT)
1477 != ffi::GFALSE
1478 {
1479 panic!("Can't instantiate abstract type '{type_}'");
1480 }
1481
1482 let mut property_names = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1483 let mut property_values =
1484 smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1485
1486 if !properties.is_empty() {
1487 let klass = ObjectClass::from_type(type_)
1488 .unwrap_or_else(|| panic!("Can't retrieve class for type '{type_}'"));
1489
1490 for (idx, (name, value)) in properties.iter_mut().enumerate() {
1491 let pspec = klass.find_property(name).unwrap_or_else(|| {
1492 panic!("Can't find property '{name}' for type '{type_}'")
1493 });
1494
1495 if (pspec.flags().contains(crate::ParamFlags::CONSTRUCT)
1496 || pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
1497 && property_names[0..idx]
1498 .iter()
1499 .any(|other_name| pspec.name().as_ptr() == *other_name)
1500 {
1501 panic!("Can't set construct property '{name}' for type '{type_}' twice");
1502 }
1503
1504 validate_property_type(type_, true, &pspec, value);
1508
1509 property_names.push(pspec.name().as_ptr());
1510 property_values.push(*value.to_glib_none().0);
1511 }
1512 }
1513
1514 let ptr = gobject_ffi::g_object_new_with_properties(
1515 type_.into_glib(),
1516 properties.len() as u32,
1517 mut_override(property_names.as_ptr() as *const *const _),
1518 property_values.as_ptr(),
1519 );
1520
1521 if ptr.is_null() {
1522 panic!("Can't instantiate object for type '{type_}'");
1523 } else if type_.is_a(InitiallyUnowned::static_type()) {
1524 from_glib_none(ptr)
1526 } else {
1527 from_glib_full(ptr)
1528 }
1529 }
1530 }
1531
1532 pub fn builder<'a, O: IsA<Object> + IsClass>() -> ObjectBuilder<'a, O> {
1535 ObjectBuilder::new(O::static_type())
1536 }
1537
1538 pub fn builder_with_type<'a>(type_: Type) -> ObjectBuilder<'a, Object> {
1541 ObjectBuilder::new(type_)
1542 }
1543}
1544
1545#[must_use = "builder doesn't do anything unless built"]
1546pub struct ObjectBuilder<'a, O> {
1547 type_: Type,
1548 properties: smallvec::SmallVec<[(&'a str, Value); 16]>,
1549 phantom: PhantomData<O>,
1550}
1551
1552impl<'a, O: IsA<Object> + IsClass> ObjectBuilder<'a, O> {
1553 #[inline]
1554 fn new(type_: Type) -> Self {
1555 ObjectBuilder {
1556 type_,
1557 properties: smallvec::SmallVec::new(),
1558 phantom: PhantomData,
1559 }
1560 }
1561
1562 #[inline]
1565 pub fn type_(&self) -> Type {
1566 self.type_
1567 }
1568
1569 pub fn property(self, name: &'a str, value: impl Into<Value>) -> Self {
1574 let ObjectBuilder {
1575 type_,
1576 mut properties,
1577 ..
1578 } = self;
1579 properties.push((name, value.into()));
1580
1581 ObjectBuilder {
1582 type_,
1583 properties,
1584 phantom: PhantomData,
1585 }
1586 }
1587
1588 #[inline]
1594 pub fn property_if(self, name: &'a str, value: impl Into<Value>, predicate: bool) -> Self {
1595 if predicate {
1596 self.property(name, value)
1597 } else {
1598 self
1599 }
1600 }
1601
1602 #[inline]
1607 pub fn property_if_some(self, name: &'a str, value: Option<impl Into<Value>>) -> Self {
1608 if let Some(value) = value {
1609 self.property(name, value)
1610 } else {
1611 self
1612 }
1613 }
1614
1615 #[inline]
1620 pub fn property_from_iter<V: ValueType + Into<Value> + FromIterator<Value>>(
1621 self,
1622 name: &'a str,
1623 iter: impl IntoIterator<Item = impl Into<Value>>,
1624 ) -> Self {
1625 let iter = iter.into_iter().map(|item| item.into());
1626 self.property(name, V::from_iter(iter))
1627 }
1628
1629 #[inline]
1635 pub fn property_if_not_empty<V: ValueType + Into<Value> + FromIterator<Value>>(
1636 self,
1637 name: &'a str,
1638 iter: impl IntoIterator<Item = impl Into<Value>>,
1639 ) -> Self {
1640 let mut iter = iter.into_iter().peekable();
1641 if iter.peek().is_some() {
1642 let iter = iter.map(|item| item.into());
1643 self.property(name, V::from_iter(iter))
1644 } else {
1645 self
1646 }
1647 }
1648
1649 #[track_caller]
1657 #[inline]
1658 pub fn build(mut self) -> O {
1659 let object = Object::with_mut_values(self.type_, &mut self.properties);
1660 unsafe { object.unsafe_cast::<O>() }
1661 }
1662}
1663
1664#[must_use = "if unused the property notifications will immediately be thawed"]
1665pub struct PropertyNotificationFreezeGuard(ObjectRef);
1666
1667impl Drop for PropertyNotificationFreezeGuard {
1668 #[doc(alias = "g_object_thaw_notify")]
1669 #[inline]
1670 fn drop(&mut self) {
1671 unsafe { gobject_ffi::g_object_thaw_notify(self.0.to_glib_none().0) }
1672 }
1673}
1674
1675pub trait ObjectExt: ObjectType {
1676 fn is<T: StaticType>(&self) -> bool;
1679
1680 #[doc(alias = "get_type")]
1683 fn type_(&self) -> Type;
1684
1685 #[doc(alias = "get_object_class")]
1690 fn object_class(&self) -> &ObjectClass;
1691
1692 #[doc(alias = "get_class")]
1694 fn class(&self) -> &Class<Self>
1695 where
1696 Self: IsClass;
1697
1698 #[doc(alias = "get_class_of")]
1703 fn class_of<T: IsClass>(&self) -> Option<&Class<T>>;
1704
1705 #[doc(alias = "get_interface")]
1710 fn interface<T: IsInterface>(&self) -> Option<InterfaceRef<'_, T>>;
1711
1712 #[doc(alias = "g_object_set_property")]
1720 fn set_property(&self, property_name: &str, value: impl Into<Value>);
1721
1722 #[doc(alias = "g_object_set_property")]
1730 fn set_property_from_value(&self, property_name: &str, value: &Value);
1731
1732 #[doc(alias = "g_object_set")]
1740 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]);
1741
1742 #[doc(alias = "g_object_set")]
1750 fn set_properties_from_value(&self, property_values: &[(&str, Value)]);
1751
1752 #[doc(alias = "get_property")]
1759 #[doc(alias = "g_object_get_property")]
1760 fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V;
1761
1762 #[doc(alias = "get_property")]
1769 #[doc(alias = "g_object_get_property")]
1770 fn property_value(&self, property_name: &str) -> Value;
1771
1772 fn has_property(&self, property_name: &str) -> bool;
1775
1776 fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool;
1779
1780 #[doc(alias = "get_property_type")]
1785 fn property_type(&self, property_name: &str) -> Option<Type>;
1786
1787 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec>;
1790
1791 fn list_properties(&self) -> PtrSlice<crate::ParamSpec>;
1794
1795 #[doc(alias = "g_object_freeze_notify")]
1800 fn freeze_notify(&self) -> PropertyNotificationFreezeGuard;
1801
1802 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD);
1809
1810 #[doc(alias = "get_qdata")]
1820 unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>>;
1821
1822 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>;
1831
1832 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD);
1839
1840 #[doc(alias = "get_data")]
1850 unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>>;
1851
1852 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD>;
1861
1862 #[doc(alias = "g_signal_handler_block")]
1867 fn block_signal(&self, handler_id: &SignalHandlerId);
1868
1869 #[doc(alias = "g_signal_handler_unblock")]
1872 fn unblock_signal(&self, handler_id: &SignalHandlerId);
1873
1874 #[doc(alias = "g_signal_stop_emission")]
1877 fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>);
1878
1879 #[doc(alias = "g_signal_stop_emission_by_name")]
1882 fn stop_signal_emission_by_name(&self, signal_name: &str);
1883
1884 fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1894 where
1895 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1896
1897 fn connect_id<F>(
1909 &self,
1910 signal_id: SignalId,
1911 details: Option<Quark>,
1912 after: bool,
1913 callback: F,
1914 ) -> SignalHandlerId
1915 where
1916 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1917
1918 fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1931 where
1932 F: Fn(&[Value]) -> Option<Value> + 'static;
1933
1934 fn connect_local_id<F>(
1947 &self,
1948 signal_id: SignalId,
1949 details: Option<Quark>,
1950 after: bool,
1951 callback: F,
1952 ) -> SignalHandlerId
1953 where
1954 F: Fn(&[Value]) -> Option<Value> + 'static;
1955
1956 unsafe fn connect_unsafe<F>(
1974 &self,
1975 signal_name: &str,
1976 after: bool,
1977 callback: F,
1978 ) -> SignalHandlerId
1979 where
1980 F: Fn(&[Value]) -> Option<Value>;
1981
1982 unsafe fn connect_unsafe_id<F>(
2001 &self,
2002 signal_id: SignalId,
2003 details: Option<Quark>,
2004 after: bool,
2005 callback: F,
2006 ) -> SignalHandlerId
2007 where
2008 F: Fn(&[Value]) -> Option<Value>;
2009
2010 #[doc(alias = "g_signal_connect_closure")]
2025 #[doc(alias = "g_signal_connect_object")]
2026 fn connect_closure(
2027 &self,
2028 signal_name: &str,
2029 after: bool,
2030 closure: RustClosure,
2031 ) -> SignalHandlerId;
2032
2033 #[doc(alias = "g_signal_connect_closure_by_id")]
2044 fn connect_closure_id(
2045 &self,
2046 signal_id: SignalId,
2047 details: Option<Quark>,
2048 after: bool,
2049 closure: RustClosure,
2050 ) -> SignalHandlerId;
2051
2052 #[doc(alias = "g_object_watch_closure")]
2059 fn watch_closure(&self, closure: &impl AsRef<Closure>);
2060
2061 #[doc(alias = "g_signal_emitv")]
2071 fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R;
2072
2073 fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value>;
2076
2077 #[doc(alias = "g_signal_emit_by_name")]
2087 fn emit_by_name<R: TryFromClosureReturnValue>(
2088 &self,
2089 signal_name: &str,
2090 args: &[&dyn ToValue],
2091 ) -> R;
2092
2093 fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value>;
2103
2104 fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2114 &self,
2115 signal_name: &str,
2116 details: Quark,
2117 args: &[&dyn ToValue],
2118 ) -> R;
2119
2120 fn emit_by_name_with_details_and_values(
2130 &self,
2131 signal_name: &str,
2132 details: Quark,
2133 args: &[Value],
2134 ) -> Option<Value>;
2135
2136 fn emit_with_details<R: TryFromClosureReturnValue>(
2146 &self,
2147 signal_id: SignalId,
2148 details: Quark,
2149 args: &[&dyn ToValue],
2150 ) -> R;
2151
2152 fn emit_with_details_and_values(
2162 &self,
2163 signal_id: SignalId,
2164 details: Quark,
2165 args: &[Value],
2166 ) -> Option<Value>;
2167
2168 #[doc(alias = "g_signal_handler_disconnect")]
2171 fn disconnect(&self, handler_id: SignalHandlerId);
2172
2173 fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
2179 &self,
2180 name: Option<&str>,
2181 f: F,
2182 ) -> SignalHandlerId;
2183
2184 fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
2193 &self,
2194 name: Option<&str>,
2195 f: F,
2196 ) -> SignalHandlerId;
2197
2198 unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
2212 &self,
2213 name: Option<&str>,
2214 f: F,
2215 ) -> SignalHandlerId;
2216
2217 #[doc(alias = "g_object_notify")]
2222 fn notify(&self, property_name: &str);
2223
2224 #[doc(alias = "g_object_notify_by_pspec")]
2229 fn notify_by_pspec(&self, pspec: &crate::ParamSpec);
2230
2231 fn downgrade(&self) -> WeakRef<Self>;
2234
2235 #[doc(alias = "g_object_weak_ref")]
2238 #[doc(alias = "connect_drop")]
2239 fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2240
2241 #[doc(alias = "g_object_weak_ref")]
2247 #[doc(alias = "connect_drop")]
2248 fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2249
2250 fn bind_property<'a, 'f, 't, O: ObjectType>(
2258 &'a self,
2259 source_property: &'a str,
2260 target: &'a O,
2261 target_property: &'a str,
2262 ) -> BindingBuilder<'a, 'f, 't>;
2263
2264 fn ref_count(&self) -> u32;
2267
2268 #[doc(alias = "g_object_run_dispose")]
2280 unsafe fn run_dispose(&self);
2281}
2282
2283impl<T: ObjectType> ObjectExt for T {
2284 #[inline]
2285 fn is<U: StaticType>(&self) -> bool {
2286 self.type_().is_a(U::static_type())
2287 }
2288
2289 #[inline]
2290 fn type_(&self) -> Type {
2291 self.object_class().type_()
2292 }
2293
2294 #[inline]
2295 fn object_class(&self) -> &ObjectClass {
2296 unsafe {
2297 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2298 let klass = (*obj).g_type_instance.g_class as *const ObjectClass;
2299 &*klass
2300 }
2301 }
2302
2303 #[inline]
2304 fn class(&self) -> &Class<Self>
2305 where
2306 Self: IsClass,
2307 {
2308 unsafe {
2309 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2310 let klass = (*obj).g_type_instance.g_class as *const Class<Self>;
2311 &*klass
2312 }
2313 }
2314
2315 #[inline]
2316 fn class_of<U: IsClass>(&self) -> Option<&Class<U>> {
2317 if !self.is::<U>() {
2318 return None;
2319 }
2320
2321 unsafe {
2322 let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2323 let klass = (*obj).g_type_instance.g_class as *const Class<U>;
2324 Some(&*klass)
2325 }
2326 }
2327
2328 #[inline]
2329 fn interface<U: IsInterface>(&self) -> Option<InterfaceRef<'_, U>> {
2330 Interface::from_class(self.object_class())
2331 }
2332
2333 #[track_caller]
2334 fn set_property(&self, property_name: &str, value: impl Into<Value>) {
2335 let pspec = self.find_property(property_name).unwrap_or_else(|| {
2336 panic!(
2337 "property '{property_name}' of type '{}' not found",
2338 self.type_()
2339 )
2340 });
2341
2342 let mut property_value = value.into();
2343 validate_property_type(self.type_(), false, &pspec, &mut property_value);
2344 unsafe {
2345 gobject_ffi::g_object_set_property(
2346 self.as_object_ref().to_glib_none().0,
2347 pspec.name().as_ptr() as *const _,
2348 property_value.to_glib_none().0,
2349 );
2350 }
2351 }
2352
2353 #[track_caller]
2354 fn set_property_from_value(&self, property_name: &str, value: &Value) {
2355 let pspec = match self.find_property(property_name) {
2356 Some(pspec) => pspec,
2357 None => {
2358 panic!(
2359 "property '{property_name}' of type '{}' not found",
2360 self.type_()
2361 );
2362 }
2363 };
2364
2365 let mut property_value = value.clone();
2369 validate_property_type(self.type_(), false, &pspec, &mut property_value);
2370 unsafe {
2371 gobject_ffi::g_object_set_property(
2372 self.as_object_ref().to_glib_none().0,
2373 pspec.name().as_ptr() as *const _,
2374 property_value.to_glib_none().0,
2375 );
2376 }
2377 }
2378
2379 #[track_caller]
2380 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]) {
2381 let params = property_values
2382 .iter()
2383 .map(|&(name, value)| {
2384 let pspec = self.find_property(name).unwrap_or_else(|| {
2385 panic!("Can't find property '{name}' for type '{}'", self.type_());
2386 });
2387
2388 let mut value = value.to_value();
2389 validate_property_type(self.type_(), false, &pspec, &mut value);
2390 (pspec.name().as_ptr(), value)
2391 })
2392 .collect::<smallvec::SmallVec<[_; 10]>>();
2393
2394 let _guard = self.freeze_notify();
2395 for (name, value) in params {
2396 unsafe {
2397 gobject_ffi::g_object_set_property(
2398 self.as_object_ref().to_glib_none().0,
2399 name as *const _,
2400 value.to_glib_none().0,
2401 );
2402 }
2403 }
2404 }
2405
2406 #[track_caller]
2407 fn set_properties_from_value(&self, property_values: &[(&str, Value)]) {
2408 let params = property_values
2409 .iter()
2410 .map(|(name, value)| {
2411 let pspec = self.find_property(name).unwrap_or_else(|| {
2412 panic!("Can't find property '{name}' for type '{}'", self.type_());
2413 });
2414
2415 let mut value = value.clone();
2416 validate_property_type(self.type_(), false, &pspec, &mut value);
2417 (pspec.name().as_ptr(), value)
2418 })
2419 .collect::<smallvec::SmallVec<[_; 10]>>();
2420
2421 let _guard = self.freeze_notify();
2422 for (name, value) in params {
2423 unsafe {
2424 gobject_ffi::g_object_set_property(
2425 self.as_object_ref().to_glib_none().0,
2426 name as *const _,
2427 value.to_glib_none().0,
2428 );
2429 }
2430 }
2431 }
2432
2433 #[track_caller]
2434 fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V {
2435 let prop = self.property_value(property_name);
2436
2437 prop.get_owned::<V>()
2438 .unwrap_or_else(|e| panic!("Failed to get cast value to a different type {e}"))
2439 }
2440
2441 #[track_caller]
2442 fn property_value(&self, property_name: &str) -> Value {
2443 let pspec = self.find_property(property_name).unwrap_or_else(|| {
2444 panic!(
2445 "property '{property_name}' of type '{}' not found",
2446 self.type_()
2447 )
2448 });
2449
2450 if !pspec.flags().contains(crate::ParamFlags::READABLE) {
2451 panic!(
2452 "property '{property_name}' of type '{}' is not readable",
2453 self.type_()
2454 );
2455 }
2456
2457 unsafe {
2458 let mut value = Value::from_type_unchecked(pspec.value_type());
2459 gobject_ffi::g_object_get_property(
2460 self.as_object_ref().to_glib_none().0,
2461 pspec.name().as_ptr() as *const _,
2462 value.to_glib_none_mut().0,
2463 );
2464
2465 if !value.type_().is_valid() {
2467 panic!(
2468 "Failed to get property value for property '{property_name}' of type '{}'",
2469 self.type_()
2470 )
2471 }
2472
2473 value
2474 }
2475 }
2476
2477 fn has_property(&self, property_name: &str) -> bool {
2478 self.object_class().has_property(property_name)
2479 }
2480
2481 fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool {
2482 self.object_class()
2483 .has_property_with_type(property_name, type_)
2484 }
2485
2486 fn property_type(&self, property_name: &str) -> Option<Type> {
2487 self.object_class().property_type(property_name)
2488 }
2489
2490 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
2491 self.object_class().find_property(property_name)
2492 }
2493
2494 fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
2495 self.object_class().list_properties()
2496 }
2497
2498 #[inline]
2499 fn freeze_notify(&self) -> PropertyNotificationFreezeGuard {
2500 unsafe { gobject_ffi::g_object_freeze_notify(self.as_object_ref().to_glib_none().0) };
2501 PropertyNotificationFreezeGuard(self.as_object_ref().clone())
2502 }
2503
2504 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD) {
2505 unsafe {
2506 unsafe extern "C" fn drop_value<QD>(ptr: ffi::gpointer) {
2507 unsafe {
2508 debug_assert!(!ptr.is_null());
2509 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2510 drop(value)
2511 }
2512 }
2513
2514 let ptr = Box::into_raw(Box::new(value)) as ffi::gpointer;
2515 gobject_ffi::g_object_set_qdata_full(
2516 self.as_object_ref().to_glib_none().0,
2517 key.into_glib(),
2518 ptr,
2519 Some(drop_value::<QD>),
2520 );
2521 }
2522 }
2523
2524 unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>> {
2525 unsafe {
2526 ptr::NonNull::new(gobject_ffi::g_object_get_qdata(
2527 self.as_object_ref().to_glib_none().0,
2528 key.into_glib(),
2529 ) as *mut QD)
2530 }
2531 }
2532
2533 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD> {
2534 unsafe {
2535 let ptr = gobject_ffi::g_object_steal_qdata(
2536 self.as_object_ref().to_glib_none().0,
2537 key.into_glib(),
2538 );
2539 if ptr.is_null() {
2540 None
2541 } else {
2542 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2543 Some(*value)
2544 }
2545 }
2546 }
2547
2548 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD) {
2549 unsafe { self.set_qdata::<QD>(Quark::from_str(key), value) }
2550 }
2551
2552 unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>> {
2553 unsafe { self.qdata::<QD>(Quark::from_str(key)) }
2554 }
2555
2556 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD> {
2557 unsafe { self.steal_qdata::<QD>(Quark::from_str(key)) }
2558 }
2559
2560 fn block_signal(&self, handler_id: &SignalHandlerId) {
2561 unsafe {
2562 gobject_ffi::g_signal_handler_block(
2563 self.as_object_ref().to_glib_none().0,
2564 handler_id.as_raw(),
2565 );
2566 }
2567 }
2568
2569 fn unblock_signal(&self, handler_id: &SignalHandlerId) {
2570 unsafe {
2571 gobject_ffi::g_signal_handler_unblock(
2572 self.as_object_ref().to_glib_none().0,
2573 handler_id.as_raw(),
2574 );
2575 }
2576 }
2577
2578 fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>) {
2579 unsafe {
2580 gobject_ffi::g_signal_stop_emission(
2581 self.as_object_ref().to_glib_none().0,
2582 signal_id.into_glib(),
2583 detail.into_glib(),
2584 );
2585 }
2586 }
2587
2588 fn stop_signal_emission_by_name(&self, signal_name: &str) {
2589 unsafe {
2590 signal_name.run_with_gstr(|signal_name| {
2591 gobject_ffi::g_signal_stop_emission_by_name(
2592 self.as_object_ref().to_glib_none().0,
2593 signal_name.as_ptr(),
2594 )
2595 });
2596 }
2597 }
2598
2599 #[track_caller]
2600 fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2601 where
2602 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2603 {
2604 unsafe { self.connect_unsafe(signal_name, after, callback) }
2605 }
2606
2607 #[track_caller]
2608 fn connect_id<F>(
2609 &self,
2610 signal_id: SignalId,
2611 details: Option<Quark>,
2612 after: bool,
2613 callback: F,
2614 ) -> SignalHandlerId
2615 where
2616 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2617 {
2618 unsafe { self.connect_unsafe_id(signal_id, details, after, callback) }
2619 }
2620
2621 #[track_caller]
2622 fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2623 where
2624 F: Fn(&[Value]) -> Option<Value> + 'static,
2625 {
2626 let callback = crate::thread_guard::ThreadGuard::new(callback);
2627
2628 unsafe {
2629 self.connect_unsafe(signal_name, after, move |values| {
2630 (callback.get_ref())(values)
2631 })
2632 }
2633 }
2634
2635 #[track_caller]
2636 fn connect_local_id<F>(
2637 &self,
2638 signal_id: SignalId,
2639 details: Option<Quark>,
2640 after: bool,
2641 callback: F,
2642 ) -> SignalHandlerId
2643 where
2644 F: Fn(&[Value]) -> Option<Value> + 'static,
2645 {
2646 let callback = crate::thread_guard::ThreadGuard::new(callback);
2647
2648 unsafe {
2649 self.connect_unsafe_id(signal_id, details, after, move |values| {
2650 (callback.get_ref())(values)
2651 })
2652 }
2653 }
2654
2655 #[track_caller]
2656 unsafe fn connect_unsafe<F>(
2657 &self,
2658 signal_name: &str,
2659 after: bool,
2660 callback: F,
2661 ) -> SignalHandlerId
2662 where
2663 F: Fn(&[Value]) -> Option<Value>,
2664 {
2665 unsafe {
2666 let type_ = self.type_();
2667 let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2668 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2669 self.connect_unsafe_id(signal_id, details, after, callback)
2670 }
2671 }
2672
2673 #[track_caller]
2674 unsafe fn connect_unsafe_id<F>(
2675 &self,
2676 signal_id: SignalId,
2677 details: Option<Quark>,
2678 after: bool,
2679 callback: F,
2680 ) -> SignalHandlerId
2681 where
2682 F: Fn(&[Value]) -> Option<Value>,
2683 {
2684 unsafe {
2685 let signal_query = signal_id.query();
2686 let type_ = self.type_();
2687 let return_type: Type = signal_query.return_type().into();
2688 let signal_name = signal_id.name();
2689 let signal_query_type = signal_query.type_();
2690
2691 let closure = if return_type == Type::UNIT {
2692 Closure::new_unsafe(move |values| {
2693 let ret = callback(values);
2694 if let Some(ret) = ret {
2695 panic!(
2696 "Signal '{signal_name}' of type '{type_}' required no return value but got value of type '{}'",
2697 ret.type_()
2698 );
2699 }
2700 None
2701 })
2702 } else {
2703 Closure::new_unsafe(move |values| {
2704 let mut ret = callback(values).unwrap_or_else(|| {
2705 panic!(
2706 "Signal '{signal_name}' of type '{type_}' required return value of type '{}' but got None",
2707 return_type.name()
2708 );
2709 });
2710 let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
2711 mut_override(ret.to_glib_none().0),
2712 return_type.into_glib(),
2713 ));
2714
2715 if valid_type {
2716 return Some(ret);
2717 }
2718
2719 if let Err(got) = coerce_object_type(&mut ret, return_type) {
2720 panic!(
2721 "Signal '{signal_name}' of type '{type_}' required return value of type '{return_type}' but got '{got}'",
2722 );
2723 };
2724 Some(ret)
2725 })
2726 };
2727
2728 assert!(
2729 type_.is_a(signal_query_type),
2730 "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2731 );
2732
2733 let handler = gobject_ffi::g_signal_connect_closure_by_id(
2734 self.as_object_ref().to_glib_none().0,
2735 signal_id.into_glib(),
2736 details.into_glib(),
2737 closure.as_ref().to_glib_none().0,
2738 after.into_glib(),
2739 );
2740
2741 if handler == 0 {
2742 panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2743 }
2744
2745 from_glib(handler)
2746 }
2747 }
2748
2749 #[track_caller]
2750 fn connect_closure(
2751 &self,
2752 signal_name: &str,
2753 after: bool,
2754 closure: RustClosure,
2755 ) -> SignalHandlerId {
2756 let type_ = self.type_();
2757 let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2758 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2759 self.connect_closure_id(signal_id, details, after, closure)
2760 }
2761
2762 #[track_caller]
2763 fn connect_closure_id(
2764 &self,
2765 signal_id: SignalId,
2766 details: Option<Quark>,
2767 after: bool,
2768 closure: RustClosure,
2769 ) -> SignalHandlerId {
2770 let signal_query = signal_id.query();
2771 let type_ = self.type_();
2772 let signal_name = signal_id.name();
2773
2774 let signal_query_type = signal_query.type_();
2775 assert!(
2776 type_.is_a(signal_query_type),
2777 "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2778 );
2779
2780 unsafe {
2781 let handler = gobject_ffi::g_signal_connect_closure_by_id(
2782 self.as_object_ref().to_glib_none().0,
2783 signal_id.into_glib(),
2784 details.into_glib(),
2785 closure.as_ref().to_glib_none().0,
2786 after.into_glib(),
2787 );
2788
2789 if handler == 0 {
2790 panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2791 }
2792
2793 from_glib(handler)
2794 }
2795 }
2796
2797 #[inline]
2798 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
2799 let closure = closure.as_ref();
2800 unsafe {
2801 gobject_ffi::g_object_watch_closure(
2802 self.as_object_ref().to_glib_none().0,
2803 closure.to_glib_none().0,
2804 );
2805 }
2806 }
2807
2808 #[track_caller]
2809 fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R {
2810 let signal_query = signal_id.query();
2811 unsafe {
2812 let type_ = self.type_();
2813
2814 let self_v = {
2815 let mut v = Value::uninitialized();
2816 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2817 gobject_ffi::g_value_set_object(
2818 v.to_glib_none_mut().0,
2819 self.as_object_ref().to_glib_none().0,
2820 );
2821 v
2822 };
2823
2824 let mut args = Iterator::chain(
2825 std::iter::once(self_v),
2826 args.iter().copied().map(ToValue::to_value),
2827 )
2828 .collect::<smallvec::SmallVec<[_; 10]>>();
2829
2830 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2831
2832 let mut return_value = if signal_query.return_type() != Type::UNIT {
2833 Value::from_type_unchecked(signal_query.return_type().into())
2834 } else {
2835 Value::uninitialized()
2836 };
2837 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2838 return_value.to_glib_none_mut().0
2839 } else {
2840 ptr::null_mut()
2841 };
2842
2843 gobject_ffi::g_signal_emitv(
2844 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2845 signal_id.into_glib(),
2846 0,
2847 return_value_ptr,
2848 );
2849
2850 R::try_from_closure_return_value(
2851 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2852 )
2853 .unwrap()
2854 }
2855 }
2856
2857 #[track_caller]
2858 fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value> {
2859 unsafe {
2860 let type_ = self.type_();
2861
2862 let signal_query = signal_id.query();
2863
2864 let self_v = {
2865 let mut v = Value::uninitialized();
2866 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2867 gobject_ffi::g_value_set_object(
2868 v.to_glib_none_mut().0,
2869 self.as_object_ref().to_glib_none().0,
2870 );
2871 v
2872 };
2873
2874 let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
2875 .collect::<smallvec::SmallVec<[_; 10]>>();
2876
2877 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2878
2879 let mut return_value = if signal_query.return_type() != Type::UNIT {
2880 Value::from_type_unchecked(signal_query.return_type().into())
2881 } else {
2882 Value::uninitialized()
2883 };
2884 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2885 return_value.to_glib_none_mut().0
2886 } else {
2887 ptr::null_mut()
2888 };
2889
2890 gobject_ffi::g_signal_emitv(
2891 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2892 signal_id.into_glib(),
2893 0,
2894 return_value_ptr,
2895 );
2896
2897 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
2898 }
2899 }
2900
2901 #[track_caller]
2902 fn emit_by_name<R: TryFromClosureReturnValue>(
2903 &self,
2904 signal_name: &str,
2905 args: &[&dyn ToValue],
2906 ) -> R {
2907 let type_ = self.type_();
2908 let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2909 panic!("Signal '{signal_name}' of type '{type_}' not found");
2910 });
2911 self.emit(signal_id, args)
2912 }
2913
2914 #[track_caller]
2915 fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value> {
2916 let type_ = self.type_();
2917 let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2918 panic!("Signal '{signal_name}' of type '{type_}' not found");
2919 });
2920 self.emit_with_values(signal_id, args)
2921 }
2922
2923 #[track_caller]
2924 fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2925 &self,
2926 signal_name: &str,
2927 details: Quark,
2928 args: &[&dyn ToValue],
2929 ) -> R {
2930 let type_ = self.type_();
2931 let signal_id = SignalId::lookup(signal_name, type_)
2932 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2933 self.emit_with_details(signal_id, details, args)
2934 }
2935
2936 #[track_caller]
2937 fn emit_by_name_with_details_and_values(
2938 &self,
2939 signal_name: &str,
2940 details: Quark,
2941 args: &[Value],
2942 ) -> Option<Value> {
2943 let type_ = self.type_();
2944 let signal_id = SignalId::lookup(signal_name, type_)
2945 .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2946 self.emit_with_details_and_values(signal_id, details, args)
2947 }
2948
2949 #[track_caller]
2950 fn emit_with_details<R: TryFromClosureReturnValue>(
2951 &self,
2952 signal_id: SignalId,
2953 details: Quark,
2954 args: &[&dyn ToValue],
2955 ) -> R {
2956 let signal_query = signal_id.query();
2957 assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2958
2959 unsafe {
2960 let type_ = self.type_();
2961
2962 let self_v = {
2963 let mut v = Value::uninitialized();
2964 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2965 gobject_ffi::g_value_set_object(
2966 v.to_glib_none_mut().0,
2967 self.as_object_ref().to_glib_none().0,
2968 );
2969 v
2970 };
2971
2972 let mut args = Iterator::chain(
2973 std::iter::once(self_v),
2974 args.iter().copied().map(ToValue::to_value),
2975 )
2976 .collect::<smallvec::SmallVec<[_; 10]>>();
2977
2978 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2979
2980 let mut return_value = if signal_query.return_type() != Type::UNIT {
2981 Value::from_type_unchecked(signal_query.return_type().into())
2982 } else {
2983 Value::uninitialized()
2984 };
2985 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2986 return_value.to_glib_none_mut().0
2987 } else {
2988 ptr::null_mut()
2989 };
2990
2991 gobject_ffi::g_signal_emitv(
2992 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2993 signal_id.into_glib(),
2994 details.into_glib(),
2995 return_value_ptr,
2996 );
2997
2998 R::try_from_closure_return_value(
2999 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
3000 )
3001 .unwrap()
3002 }
3003 }
3004
3005 #[track_caller]
3006 fn emit_with_details_and_values(
3007 &self,
3008 signal_id: SignalId,
3009 details: Quark,
3010 args: &[Value],
3011 ) -> Option<Value> {
3012 let signal_query = signal_id.query();
3013 assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
3014
3015 unsafe {
3016 let type_ = self.type_();
3017
3018 let self_v = {
3019 let mut v = Value::uninitialized();
3020 gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
3021 gobject_ffi::g_value_set_object(
3022 v.to_glib_none_mut().0,
3023 self.as_object_ref().to_glib_none().0,
3024 );
3025 v
3026 };
3027
3028 let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
3029 .collect::<smallvec::SmallVec<[_; 10]>>();
3030
3031 validate_signal_arguments(type_, &signal_query, &mut args[1..]);
3032
3033 let mut return_value = if signal_query.return_type() != Type::UNIT {
3034 Value::from_type_unchecked(signal_query.return_type().into())
3035 } else {
3036 Value::uninitialized()
3037 };
3038 let return_value_ptr = if signal_query.return_type() != Type::UNIT {
3039 return_value.to_glib_none_mut().0
3040 } else {
3041 ptr::null_mut()
3042 };
3043
3044 gobject_ffi::g_signal_emitv(
3045 mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
3046 signal_id.into_glib(),
3047 details.into_glib(),
3048 return_value_ptr,
3049 );
3050
3051 Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
3052 }
3053 }
3054
3055 #[inline]
3056 fn disconnect(&self, handler_id: SignalHandlerId) {
3057 unsafe {
3058 gobject_ffi::g_signal_handler_disconnect(
3059 self.as_object_ref().to_glib_none().0,
3060 handler_id.as_raw(),
3061 );
3062 }
3063 }
3064
3065 fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
3066 &self,
3067 name: Option<&str>,
3068 f: F,
3069 ) -> SignalHandlerId {
3070 unsafe { self.connect_notify_unsafe(name, f) }
3071 }
3072
3073 fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
3074 &self,
3075 name: Option<&str>,
3076 f: F,
3077 ) -> SignalHandlerId {
3078 let f = crate::thread_guard::ThreadGuard::new(f);
3079
3080 unsafe {
3081 self.connect_notify_unsafe(name, move |s, pspec| {
3082 (f.get_ref())(s, pspec);
3083 })
3084 }
3085 }
3086
3087 unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
3088 &self,
3089 name: Option<&str>,
3090 f: F,
3091 ) -> SignalHandlerId {
3092 unsafe {
3093 unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &crate::ParamSpec)>(
3094 this: *mut gobject_ffi::GObject,
3095 param_spec: *mut gobject_ffi::GParamSpec,
3096 f: ffi::gpointer,
3097 ) where
3098 P: ObjectType,
3099 {
3100 unsafe {
3101 let f: &F = &*(f as *const F);
3102 f(
3103 Object::from_glib_borrow(this).unsafe_cast_ref(),
3104 &from_glib_borrow(param_spec),
3105 )
3106 }
3107 }
3108
3109 let signal_name = if let Some(name) = name {
3110 format!("notify::{name}\0")
3111 } else {
3112 "notify\0".into()
3113 };
3114
3115 let f: Box<F> = Box::new(f);
3116 crate::signal::connect_raw(
3117 self.as_object_ref().to_glib_none().0,
3118 signal_name.as_ptr() as *const _,
3119 Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
3120 notify_trampoline::<Self, F> as *const (),
3121 )),
3122 Box::into_raw(f),
3123 )
3124 }
3125 }
3126
3127 #[inline]
3128 fn notify(&self, property_name: &str) {
3129 unsafe {
3130 property_name.run_with_gstr(|property_name| {
3131 gobject_ffi::g_object_notify(
3132 self.as_object_ref().to_glib_none().0,
3133 property_name.as_ptr(),
3134 )
3135 });
3136 }
3137 }
3138
3139 #[inline]
3140 fn notify_by_pspec(&self, pspec: &crate::ParamSpec) {
3141 unsafe {
3142 gobject_ffi::g_object_notify_by_pspec(
3143 self.as_object_ref().to_glib_none().0,
3144 pspec.to_glib_none().0,
3145 );
3146 }
3147 }
3148
3149 #[inline]
3150 fn downgrade(&self) -> WeakRef<T> {
3151 unsafe {
3152 let w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3153 gobject_ffi::g_weak_ref_init(
3154 mut_override(&*w.0),
3155 self.as_object_ref().to_glib_none().0,
3156 );
3157 w
3158 }
3159 }
3160
3161 fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<T> {
3162 WeakRefNotify::new(self, f)
3163 }
3164
3165 fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<T> {
3166 let callback = crate::thread_guard::ThreadGuard::new(f);
3167
3168 WeakRefNotify::new(self, move || callback.into_inner()())
3169 }
3170
3171 fn bind_property<'a, 'f, 't, O: ObjectType>(
3172 &'a self,
3173 source_property: &'a str,
3174 target: &'a O,
3175 target_property: &'a str,
3176 ) -> BindingBuilder<'a, 'f, 't> {
3177 BindingBuilder::new(self, source_property, target, target_property)
3178 }
3179
3180 #[inline]
3181 fn ref_count(&self) -> u32 {
3182 let stash = self.as_object_ref().to_glib_none();
3183 let ptr: *mut gobject_ffi::GObject = stash.0;
3184
3185 unsafe { ffi::g_atomic_int_get(&(*ptr).ref_count as *const u32 as *const i32) as u32 }
3186 }
3187
3188 #[inline]
3189 unsafe fn run_dispose(&self) {
3190 unsafe {
3191 gobject_ffi::g_object_run_dispose(self.as_ptr() as *mut _);
3192 }
3193 }
3194}
3195
3196#[doc(hidden)]
3199pub struct WatchedObject<T: ObjectType>(ptr::NonNull<T::GlibType>);
3200
3201#[doc(hidden)]
3202unsafe impl<T: ObjectType + Send + Sync> Send for WatchedObject<T> {}
3203
3204#[doc(hidden)]
3205unsafe impl<T: ObjectType + Send + Sync> Sync for WatchedObject<T> {}
3206
3207#[doc(hidden)]
3208impl<T: ObjectType> WatchedObject<T> {
3209 pub fn new(obj: &T) -> Self {
3210 Self(unsafe { ptr::NonNull::new_unchecked(obj.as_ptr()) })
3211 }
3212 #[inline]
3218 pub unsafe fn borrow(&self) -> Borrowed<T>
3219 where
3220 T: FromGlibPtrBorrow<*mut <T as ObjectType>::GlibType>,
3221 {
3222 unsafe { from_glib_borrow(self.0.as_ptr()) }
3223 }
3224}
3225
3226#[doc(hidden)]
3227pub trait Watchable<T: ObjectType> {
3228 fn watched_object(&self) -> WatchedObject<T>;
3229 fn watch_closure(&self, closure: &impl AsRef<Closure>);
3230}
3231
3232#[doc(hidden)]
3233impl<T: ObjectType> Watchable<T> for T {
3234 fn watched_object(&self) -> WatchedObject<T> {
3235 WatchedObject::new(self)
3236 }
3237 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3238 ObjectExt::watch_closure(self, closure)
3239 }
3240}
3241
3242#[doc(hidden)]
3243impl<T: ObjectType> Watchable<T> for BorrowedObject<'_, T> {
3244 fn watched_object(&self) -> WatchedObject<T> {
3245 WatchedObject::new(self)
3246 }
3247 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3248 ObjectExt::watch_closure(&**self, closure)
3249 }
3250}
3251
3252#[doc(hidden)]
3253impl<T: ObjectType> Watchable<T> for &T {
3254 fn watched_object(&self) -> WatchedObject<T> {
3255 WatchedObject::new(*self)
3256 }
3257 fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3258 ObjectExt::watch_closure(*self, closure)
3259 }
3260}
3261
3262#[track_caller]
3265fn validate_property_type(
3266 type_: Type,
3267 allow_construct_only: bool,
3268 pspec: &crate::ParamSpec,
3269 property_value: &mut Value,
3270) {
3271 if !pspec.flags().contains(crate::ParamFlags::WRITABLE)
3272 || (!allow_construct_only && pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
3273 {
3274 panic!(
3275 "property '{}' of type '{type_}' is not writable",
3276 pspec.name(),
3277 );
3278 }
3279
3280 unsafe {
3281 let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
3286 mut_override(property_value.to_glib_none().0),
3287 pspec.value_type().into_glib(),
3288 ));
3289
3290 if !valid_type && let Err(got) = coerce_object_type(property_value, pspec.value_type()) {
3291 panic!(
3292 "property '{}' of type '{type_}' can't be set from the given type (expected: '{}', got: '{got}')",
3293 pspec.name(),
3294 pspec.value_type(),
3295 );
3296 }
3297
3298 let changed: bool = from_glib(gobject_ffi::g_param_value_validate(
3299 pspec.to_glib_none().0,
3300 property_value.to_glib_none_mut().0,
3301 ));
3302 let change_allowed = pspec.flags().contains(crate::ParamFlags::LAX_VALIDATION);
3303 if changed && !change_allowed {
3304 panic!(
3305 "property '{}' of type '{type_}' can't be set from given value, it is invalid or out of range",
3306 pspec.name(),
3307 );
3308 }
3309 }
3310}
3311
3312fn coerce_object_type(property_value: &mut Value, type_: Type) -> Result<(), Type> {
3318 match property_value.get::<Option<Object>>() {
3320 Ok(Some(obj)) if !(obj.type_().is_a(type_)) => Err(obj.type_()),
3321 Ok(_) => {
3322 property_value.inner.g_type = type_.into_glib();
3323 Ok(())
3324 }
3325 Err(_) => Err(property_value.type_()),
3326 }
3327}
3328
3329#[track_caller]
3330fn validate_signal_arguments(type_: Type, signal_query: &SignalQuery, args: &mut [Value]) {
3331 let signal_name = signal_query.signal_name();
3332
3333 if signal_query.n_params() != args.len() as u32 {
3334 panic!(
3335 "Incompatible number of arguments for signal '{signal_name}' of type '{type_}' (expected {}, got {})",
3336 signal_query.n_params(),
3337 args.len(),
3338 );
3339 }
3340
3341 let param_types = Iterator::zip(args.iter_mut(), signal_query.param_types());
3342
3343 for (i, (arg, param_type)) in param_types.enumerate() {
3344 let param_type: Type = (*param_type).into();
3345 if param_type != arg.type_() {
3346 coerce_object_type(arg, param_type).unwrap_or_else(|got|
3347 panic!(
3348 "Incompatible argument type in argument {i} for signal '{signal_name}' of type '{type_}' (expected {param_type}, got {got})",
3349 )
3350 );
3351 }
3352 }
3353}
3354
3355pub unsafe trait ObjectClassExt {
3357 fn has_property(&self, property_name: &str) -> bool {
3360 self.find_property(property_name).is_some()
3361 }
3362
3363 fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool {
3367 self.property_type(property_name)
3368 .is_some_and(|ptype| ptype.is_a(type_))
3369 }
3370
3371 #[doc(alias = "get_property_type")]
3376 fn property_type(&self, property_name: &str) -> Option<Type> {
3377 self.find_property(property_name)
3378 .map(|pspec| pspec.value_type())
3379 }
3380
3381 #[doc(alias = "g_object_class_find_property")]
3384 fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
3385 unsafe {
3386 let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3387
3388 property_name.run_with_gstr(|property_name| {
3389 from_glib_none(gobject_ffi::g_object_class_find_property(
3390 klass as *mut _,
3391 property_name.as_ptr(),
3392 ))
3393 })
3394 }
3395 }
3396
3397 #[doc(alias = "g_object_class_list_properties")]
3400 fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
3401 unsafe {
3402 let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3403
3404 let mut n_properties = 0;
3405
3406 let props =
3407 gobject_ffi::g_object_class_list_properties(klass as *mut _, &mut n_properties);
3408 PtrSlice::from_glib_container_num(props, n_properties as usize, true)
3409 }
3410 }
3411}
3412
3413unsafe impl<T: ObjectType + IsClass> ObjectClassExt for Class<T> {}
3414
3415wrapper! {
3416 #[doc(alias = "GInitiallyUnowned")]
3417 pub struct InitiallyUnowned(Object<gobject_ffi::GInitiallyUnowned, gobject_ffi::GInitiallyUnownedClass>);
3418
3419 match fn {
3420 type_ => || gobject_ffi::g_initially_unowned_get_type(),
3421 }
3422}
3423
3424type WeakRefNotifyData = ManuallyDrop<Pin<Box<Box<dyn FnOnce() + 'static>>>>;
3429
3430pub struct WeakRefNotify<T: ObjectType> {
3433 object: WeakRef<T>,
3434 data: WeakRefNotifyData,
3435}
3436
3437unsafe extern "C" fn notify_func(data: ffi::gpointer, _obj: *mut gobject_ffi::GObject) {
3438 unsafe {
3439 let callback: Box<Box<dyn FnOnce()>> = Box::from_raw(data as *mut _);
3442
3443 (*callback)()
3446 }
3447}
3448
3449impl<T: ObjectType> WeakRefNotify<T> {
3450 fn new<F: FnOnce() + 'static>(obj: &T, f: F) -> WeakRefNotify<T> {
3451 let data: WeakRefNotifyData = ManuallyDrop::new(Box::pin(Box::new(f)));
3452 let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&data).get_ref();
3453
3454 unsafe {
3455 gobject_ffi::g_object_weak_ref(
3457 obj.as_ptr() as *mut gobject_ffi::GObject,
3458 Some(notify_func),
3459 data_ptr as *mut _,
3460 );
3461 }
3462
3463 let object = obj.downgrade();
3464
3465 WeakRefNotify { object, data }
3466 }
3467
3468 pub fn upgrade(&self) -> Option<T> {
3473 self.object.upgrade()
3474 }
3475
3476 #[doc(alias = "g_object_weak_unref")]
3477 pub fn disconnect(mut self) {
3478 if let Some(obj) = self.object.upgrade() {
3480 let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&self.data).get_ref();
3481
3482 unsafe {
3483 gobject_ffi::g_object_weak_unref(
3485 obj.as_ptr() as *mut gobject_ffi::GObject,
3486 Some(notify_func),
3487 data_ptr as *mut _,
3488 );
3489
3490 ManuallyDrop::drop(&mut self.data);
3494 }
3495 }
3496 }
3497}
3498
3499#[derive(Debug)]
3502#[doc(alias = "GWeakRef")]
3503pub struct WeakRef<T: ObjectType>(Pin<Box<gobject_ffi::GWeakRef>>, PhantomData<*mut T>);
3504
3505impl<T: ObjectType> WeakRef<T> {
3506 #[inline]
3511 pub fn new() -> WeakRef<T> {
3512 unsafe {
3513 let mut w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3514 gobject_ffi::g_weak_ref_init(
3515 Pin::as_mut(&mut w.0).get_unchecked_mut(),
3516 ptr::null_mut(),
3517 );
3518 w
3519 }
3520 }
3521
3522 #[doc(alias = "g_weak_ref_set")]
3525 #[inline]
3526 pub fn set(&self, obj: Option<&T>) {
3527 unsafe {
3528 gobject_ffi::g_weak_ref_set(
3529 mut_override(Pin::as_ref(&self.0).get_ref()),
3530 obj.map_or(std::ptr::null_mut(), |obj| {
3531 obj.as_object_ref().to_glib_none().0
3532 }),
3533 );
3534 }
3535 }
3536
3537 #[inline]
3543 pub fn upgrade(&self) -> Option<T> {
3544 unsafe {
3545 let ptr = gobject_ffi::g_weak_ref_get(mut_override(Pin::as_ref(&self.0).get_ref()));
3546 if ptr.is_null() {
3547 None
3548 } else {
3549 let obj: Object = from_glib_full(ptr);
3550 Some(T::unsafe_from(obj.into()))
3551 }
3552 }
3553 }
3554}
3555
3556impl<T: ObjectType> Drop for WeakRef<T> {
3557 #[inline]
3558 fn drop(&mut self) {
3559 unsafe {
3560 gobject_ffi::g_weak_ref_clear(Pin::as_mut(&mut self.0).get_unchecked_mut());
3561 }
3562 }
3563}
3564
3565impl<T: ObjectType> Clone for WeakRef<T> {
3566 #[inline]
3567 fn clone(&self) -> Self {
3568 unsafe {
3569 let o = self.upgrade();
3570
3571 let mut c = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3572 gobject_ffi::g_weak_ref_init(
3573 Pin::as_mut(&mut c.0).get_unchecked_mut(),
3574 o.to_glib_none().0 as *mut gobject_ffi::GObject,
3575 );
3576
3577 c
3578 }
3579 }
3580}
3581
3582impl<T: ObjectType> Default for WeakRef<T> {
3583 #[inline]
3584 fn default() -> Self {
3585 Self::new()
3586 }
3587}
3588
3589unsafe impl<T: ObjectType + Sync + Sync> Sync for WeakRef<T> {}
3590unsafe impl<T: ObjectType + Send + Sync> Send for WeakRef<T> {}
3591
3592impl<T: ObjectType> PartialEq for WeakRef<T> {
3593 #[inline]
3594 fn eq(&self, other: &Self) -> bool {
3595 unsafe { self.0.priv_.p == other.0.priv_.p }
3596 }
3597}
3598
3599impl<T: ObjectType> PartialEq<T> for WeakRef<T> {
3600 #[inline]
3601 fn eq(&self, other: &T) -> bool {
3602 unsafe { self.0.priv_.p == other.as_ptr() as *mut std::os::raw::c_void }
3603 }
3604}
3605
3606impl<T: ObjectType> PartialOrd for WeakRef<T> {
3607 #[inline]
3608 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
3609 unsafe { self.0.priv_.p.partial_cmp(&other.0.priv_.p) }
3610 }
3611}
3612
3613#[derive(Debug)]
3621pub struct SendWeakRef<T: ObjectType>(WeakRef<T>, usize);
3622
3623impl<T: ObjectType> SendWeakRef<T> {
3624 #[inline]
3625 pub fn into_weak_ref(self) -> WeakRef<T> {
3626 assert!(
3627 self.1 == thread_id(),
3628 "SendWeakRef dereferenced on a different thread",
3629 );
3630
3631 self.0
3632 }
3633}
3634
3635impl<T: ObjectType> ops::Deref for SendWeakRef<T> {
3636 type Target = WeakRef<T>;
3637
3638 #[inline]
3639 fn deref(&self) -> &WeakRef<T> {
3640 assert!(
3641 self.1 == thread_id(),
3642 "SendWeakRef dereferenced on a different thread"
3643 );
3644
3645 &self.0
3646 }
3647}
3648
3649impl<T: ObjectType> Clone for SendWeakRef<T> {
3651 #[inline]
3652 fn clone(&self) -> Self {
3653 Self(self.0.clone(), self.1)
3654 }
3655}
3656
3657impl<T: ObjectType> Default for SendWeakRef<T> {
3658 #[inline]
3659 fn default() -> Self {
3660 Self::from(WeakRef::new())
3661 }
3662}
3663
3664impl<T: ObjectType> From<WeakRef<T>> for SendWeakRef<T> {
3665 #[inline]
3666 fn from(v: WeakRef<T>) -> SendWeakRef<T> {
3667 SendWeakRef(v, thread_id())
3668 }
3669}
3670
3671unsafe impl<T: ObjectType> Sync for SendWeakRef<T> {}
3672unsafe impl<T: ObjectType> Send for SendWeakRef<T> {}
3673
3674type TransformFn<'b> =
3675 Option<Box<dyn Fn(&'b crate::Binding, &'b Value) -> Option<Value> + Send + Sync + 'static>>;
3676
3677#[must_use = "The builder must be built to be used"]
3680pub struct BindingBuilder<'a, 'f, 't> {
3681 source: &'a ObjectRef,
3682 source_property: &'a str,
3683 target: &'a ObjectRef,
3684 target_property: &'a str,
3685 flags: crate::BindingFlags,
3686 transform_from: TransformFn<'f>,
3687 transform_to: TransformFn<'t>,
3688}
3689
3690impl fmt::Debug for BindingBuilder<'_, '_, '_> {
3691 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3692 f.debug_struct("BindingBuilder")
3693 .field("source", &self.source)
3694 .field("source_property", &self.source_property)
3695 .field("target", &self.target)
3696 .field("target_property", &self.target_property)
3697 .field("flags", &self.flags)
3698 .finish()
3699 }
3700}
3701
3702impl<'a, 'f, 't> BindingBuilder<'a, 'f, 't> {
3703 fn new(
3704 source: &'a impl ObjectType,
3705 source_property: &'a str,
3706 target: &'a impl ObjectType,
3707 target_property: &'a str,
3708 ) -> Self {
3709 Self {
3710 source: source.as_object_ref(),
3711 source_property,
3712 target: target.as_object_ref(),
3713 target_property,
3714 flags: crate::BindingFlags::DEFAULT,
3715 transform_to: None,
3716 transform_from: None,
3717 }
3718 }
3719
3720 pub fn transform_from_with_values<
3726 F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3727 >(
3728 self,
3729 func: F,
3730 ) -> Self {
3731 Self {
3732 transform_from: Some(Box::new(func)),
3733 ..self
3734 }
3735 }
3736
3737 pub fn transform_from<
3743 S: FromValue<'f>,
3744 T: Into<Value>,
3745 F: Fn(&'f crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3746 >(
3747 self,
3748 func: F,
3749 ) -> Self {
3750 Self {
3751 transform_from: Some(Box::new(move |binding, from_value| {
3752 let from_value = from_value.get().expect("Wrong value type");
3753 func(binding, from_value).map(|r| r.into())
3754 })),
3755 ..self
3756 }
3757 }
3758
3759 pub fn transform_to_with_values<
3765 F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3766 >(
3767 self,
3768 func: F,
3769 ) -> Self {
3770 Self {
3771 transform_to: Some(Box::new(func)),
3772 ..self
3773 }
3774 }
3775
3776 pub fn transform_to<
3782 S: FromValue<'t>,
3783 T: Into<Value>,
3784 F: Fn(&'t crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3785 >(
3786 self,
3787 func: F,
3788 ) -> Self {
3789 Self {
3790 transform_to: Some(Box::new(move |binding, from_value| {
3791 let from_value = from_value.get().expect("Wrong value type");
3792 func(binding, from_value).map(|r| r.into())
3793 })),
3794 ..self
3795 }
3796 }
3797
3798 pub fn flags(self, flags: crate::BindingFlags) -> Self {
3801 Self { flags, ..self }
3802 }
3803
3804 pub fn bidirectional(mut self) -> Self {
3807 self.flags |= crate::BindingFlags::BIDIRECTIONAL;
3808 self
3809 }
3810
3811 pub fn sync_create(mut self) -> Self {
3814 self.flags |= crate::BindingFlags::SYNC_CREATE;
3815 self
3816 }
3817
3818 pub fn invert_boolean(mut self) -> Self {
3821 self.flags |= crate::BindingFlags::INVERT_BOOLEAN;
3822 self
3823 }
3824
3825 #[track_caller]
3831 pub fn build(self) -> crate::Binding {
3832 unsafe extern "C" fn transform_to_trampoline(
3833 binding: *mut gobject_ffi::GBinding,
3834 from_value: *const gobject_ffi::GValue,
3835 to_value: *mut gobject_ffi::GValue,
3836 user_data: ffi::gpointer,
3837 ) -> ffi::gboolean {
3838 unsafe {
3839 let transform_data = &*(user_data
3840 as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3841
3842 match (transform_data.0.as_ref().unwrap())(
3843 &from_glib_borrow(binding),
3844 &*(from_value as *const Value),
3845 ) {
3846 None => false,
3847 Some(res) => {
3848 assert!(
3849 res.type_().is_a(transform_data.3.value_type()),
3850 "Target property {} expected type {} but transform_to function returned {}",
3851 transform_data.3.name(),
3852 transform_data.3.value_type(),
3853 res.type_()
3854 );
3855 *to_value = res.into_raw();
3856 true
3857 }
3858 }
3859 .into_glib()
3860 }
3861 }
3862
3863 unsafe extern "C" fn transform_from_trampoline(
3864 binding: *mut gobject_ffi::GBinding,
3865 from_value: *const gobject_ffi::GValue,
3866 to_value: *mut gobject_ffi::GValue,
3867 user_data: ffi::gpointer,
3868 ) -> ffi::gboolean {
3869 unsafe {
3870 let transform_data = &*(user_data
3871 as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3872
3873 match (transform_data.1.as_ref().unwrap())(
3874 &from_glib_borrow(binding),
3875 &*(from_value as *const Value),
3876 ) {
3877 None => false,
3878 Some(res) => {
3879 assert!(
3880 res.type_().is_a(transform_data.2.value_type()),
3881 "Source property {} expected type {} but transform_from function returned {}",
3882 transform_data.2.name(),
3883 transform_data.2.value_type(),
3884 res.type_()
3885 );
3886 *to_value = res.into_raw();
3887 true
3888 }
3889 }
3890 .into_glib()
3891 }
3892 }
3893
3894 unsafe extern "C" fn free_transform_data(data: ffi::gpointer) {
3895 unsafe {
3896 let _ = Box::from_raw(
3897 data as *mut (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec),
3898 );
3899 }
3900 }
3901
3902 unsafe {
3903 let source = Object {
3904 inner: TypedObjectRef::new(self.source.clone()),
3905 phantom: std::marker::PhantomData,
3906 };
3907 let target = Object {
3908 inner: TypedObjectRef::new(self.target.clone()),
3909 phantom: std::marker::PhantomData,
3910 };
3911
3912 let source_property = source
3913 .find_property(self.source_property)
3914 .unwrap_or_else(|| {
3915 panic!(
3916 "Source property {} on type {} not found",
3917 self.source_property,
3918 source.type_()
3919 );
3920 });
3921 let target_property = target
3922 .find_property(self.target_property)
3923 .unwrap_or_else(|| {
3924 panic!(
3925 "Target property {} on type {} not found",
3926 self.target_property,
3927 target.type_()
3928 );
3929 });
3930
3931 let source_property_name = source_property.name().as_ptr();
3932 let target_property_name = target_property.name().as_ptr();
3933
3934 let have_transform_to = self.transform_to.is_some();
3935 let have_transform_from = self.transform_from.is_some();
3936 let transform_data = if have_transform_to || have_transform_from {
3937 Box::into_raw(Box::new((
3938 self.transform_to,
3939 self.transform_from,
3940 source_property,
3941 target_property,
3942 )))
3943 } else {
3944 ptr::null_mut()
3945 };
3946
3947 from_glib_none(gobject_ffi::g_object_bind_property_full(
3948 source.to_glib_none().0,
3949 source_property_name as *const _,
3950 target.to_glib_none().0,
3951 target_property_name as *const _,
3952 self.flags.into_glib(),
3953 if have_transform_to {
3954 Some(transform_to_trampoline)
3955 } else {
3956 None
3957 },
3958 if have_transform_from {
3959 Some(transform_from_trampoline)
3960 } else {
3961 None
3962 },
3963 transform_data as ffi::gpointer,
3964 if transform_data.is_null() {
3965 None
3966 } else {
3967 Some(free_transform_data)
3968 },
3969 ))
3970 }
3971 }
3972}
3973
3974#[repr(transparent)]
3977pub struct Class<T: IsClass>(T::GlibClassType);
3978
3979impl<T: IsClass> Class<T> {
3980 #[doc(alias = "get_type")]
3986 #[inline]
3987 pub fn type_(&self) -> Type {
3988 unsafe {
3989 let klass = self as *const _ as *const gobject_ffi::GTypeClass;
3992 from_glib((*klass).g_type)
3993 }
3994 }
3995
3996 #[inline]
3999 pub fn upcast_ref<U: IsClass>(&self) -> &Class<U>
4000 where
4001 T: IsA<U>,
4002 {
4003 unsafe {
4004 let klass = self as *const _ as *const Class<U>;
4005 &*klass
4006 }
4007 }
4008
4009 #[inline]
4012 pub fn upcast_ref_mut<U: IsClass>(&mut self) -> &mut Class<U>
4013 where
4014 T: IsA<U>,
4015 {
4016 unsafe {
4017 let klass = self as *mut _ as *mut Class<U>;
4018 &mut *klass
4019 }
4020 }
4021
4022 #[inline]
4026 pub fn downcast_ref<U: IsClass + IsA<T>>(&self) -> Option<&Class<U>> {
4027 if !self.type_().is_a(U::static_type()) {
4028 return None;
4029 }
4030
4031 unsafe {
4032 let klass = self as *const _ as *const Class<U>;
4033 Some(&*klass)
4034 }
4035 }
4036
4037 #[inline]
4041 pub fn downcast_ref_mut<U: IsClass + IsA<T>>(&mut self) -> Option<&mut Class<U>> {
4042 if !self.type_().is_a(U::static_type()) {
4043 return None;
4044 }
4045
4046 unsafe {
4047 let klass = self as *mut _ as *mut Class<U>;
4048 Some(&mut *klass)
4049 }
4050 }
4051
4052 #[doc(alias = "g_type_class_ref")]
4057 #[inline]
4058 pub fn from_type(type_: Type) -> Option<ClassRef<'static, T>> {
4059 if !type_.is_a(T::static_type()) {
4060 return None;
4061 }
4062
4063 unsafe {
4064 let ptr = gobject_ffi::g_type_class_ref(type_.into_glib());
4065 if ptr.is_null() {
4066 None
4067 } else {
4068 Some(ClassRef(
4069 ptr::NonNull::new_unchecked(ptr as *mut Self),
4070 true,
4071 PhantomData,
4072 ))
4073 }
4074 }
4075 }
4076
4077 #[doc(alias = "g_type_class_peek_parent")]
4080 #[inline]
4081 pub fn parent(&self) -> Option<ClassRef<'_, T>> {
4082 unsafe {
4083 let ptr = gobject_ffi::g_type_class_peek_parent(&self.0 as *const _ as *mut _);
4084 if ptr.is_null() {
4085 None
4086 } else {
4087 Some(ClassRef(
4088 ptr::NonNull::new_unchecked(ptr as *mut Self),
4089 false,
4090 PhantomData,
4091 ))
4092 }
4093 }
4094 }
4095}
4096
4097unsafe impl<T: IsClass> Send for Class<T> {}
4098unsafe impl<T: IsClass> Sync for Class<T> {}
4099
4100impl<T: IsClass> AsRef<T::GlibClassType> for Class<T> {
4101 #[inline]
4102 fn as_ref(&self) -> &T::GlibClassType {
4103 &self.0
4104 }
4105}
4106
4107impl<T: IsClass> AsMut<T::GlibClassType> for Class<T> {
4108 #[inline]
4109 fn as_mut(&mut self) -> &mut T::GlibClassType {
4110 &mut self.0
4111 }
4112}
4113
4114#[derive(Debug)]
4117pub struct ClassRef<'a, T: IsClass>(ptr::NonNull<Class<T>>, bool, PhantomData<&'a ()>);
4118
4119impl<T: IsClass> ops::Deref for ClassRef<'_, T> {
4120 type Target = Class<T>;
4121
4122 #[inline]
4123 fn deref(&self) -> &Class<T> {
4124 unsafe { self.0.as_ref() }
4125 }
4126}
4127
4128impl<T: IsClass> Drop for ClassRef<'_, T> {
4129 #[inline]
4130 fn drop(&mut self) {
4131 if self.1 {
4132 unsafe {
4133 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
4134 }
4135 }
4136 }
4137}
4138
4139unsafe impl<T: IsClass> Send for ClassRef<'_, T> {}
4140unsafe impl<T: IsClass> Sync for ClassRef<'_, T> {}
4141
4142pub unsafe trait ParentClassIs: IsClass {
4144 type Parent: IsClass;
4145}
4146
4147pub unsafe trait ObjectSubclassIs: IsClass {
4151 type Subclass: ObjectSubclass;
4152}
4153
4154impl<T: ParentClassIs> ops::Deref for Class<T> {
4155 type Target = Class<T::Parent>;
4156
4157 #[inline]
4158 fn deref(&self) -> &Self::Target {
4159 unsafe {
4160 let klass = self as *const _ as *const Self::Target;
4161 &*klass
4162 }
4163 }
4164}
4165
4166impl<T: ParentClassIs> ops::DerefMut for Class<T> {
4167 #[inline]
4168 fn deref_mut(&mut self) -> &mut Self::Target {
4169 unsafe {
4170 let klass = self as *mut _ as *mut Self::Target;
4171 &mut *klass
4172 }
4173 }
4174}
4175
4176pub unsafe trait IsClass: ObjectType {}
4179
4180#[repr(transparent)]
4183pub struct Interface<T: IsInterface>(T::GlibClassType);
4184
4185impl<T: IsInterface> Interface<T> {
4186 #[doc(alias = "get_type")]
4191 #[inline]
4192 pub fn type_(&self) -> Type {
4193 unsafe {
4194 let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4195 from_glib((*klass).g_type)
4196 }
4197 }
4198
4199 #[doc(alias = "get_instance_type")]
4205 #[inline]
4206 pub fn instance_type(&self) -> Type {
4207 unsafe {
4208 let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4211 from_glib((*klass).g_instance_type)
4212 }
4213 }
4214
4215 #[inline]
4220 pub fn from_class<U: IsClass>(klass: &Class<U>) -> Option<InterfaceRef<'_, T>> {
4221 if !klass.type_().is_a(T::static_type()) {
4222 return None;
4223 }
4224
4225 unsafe {
4226 let ptr = gobject_ffi::g_type_interface_peek(
4227 &klass.0 as *const _ as *mut _,
4228 T::static_type().into_glib(),
4229 );
4230 if ptr.is_null() {
4231 None
4232 } else {
4233 Some(InterfaceRef(
4234 ptr::NonNull::new_unchecked(ptr as *mut Self),
4235 false,
4236 PhantomData,
4237 ))
4238 }
4239 }
4240 }
4241
4242 #[inline]
4247 pub fn from_type(type_: Type) -> Option<InterfaceRef<'static, T>> {
4248 if !type_.is_a(Type::INTERFACE) {
4249 return None;
4250 }
4251
4252 unsafe {
4253 let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4254 if ptr.is_null() {
4255 None
4256 } else {
4257 Some(InterfaceRef(
4258 ptr::NonNull::new_unchecked(ptr as *mut Self),
4259 true,
4260 PhantomData,
4261 ))
4262 }
4263 }
4264 }
4265
4266 #[doc(alias = "g_type_default_interface_ref")]
4269 #[allow(clippy::should_implement_trait)]
4270 #[inline]
4271 pub fn default() -> InterfaceRef<'static, T> {
4272 unsafe {
4273 let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4274 debug_assert!(!ptr.is_null());
4275 InterfaceRef(
4276 ptr::NonNull::new_unchecked(ptr as *mut Self),
4277 true,
4278 PhantomData,
4279 )
4280 }
4281 }
4282
4283 #[doc(alias = "g_type_interface_peek_parent")]
4289 #[inline]
4290 pub fn parent(&self) -> Option<InterfaceRef<'_, T>> {
4291 unsafe {
4292 let ptr = gobject_ffi::g_type_interface_peek_parent(&self.0 as *const _ as *mut _);
4293 if ptr.is_null() {
4294 None
4295 } else {
4296 Some(InterfaceRef(
4297 ptr::NonNull::new_unchecked(ptr as *mut Self),
4298 false,
4299 PhantomData,
4300 ))
4301 }
4302 }
4303 }
4304}
4305
4306impl<T: IsA<Object> + IsInterface> Interface<T> {
4307 pub fn has_property(&self, property_name: &str) -> bool {
4310 self.find_property(property_name).is_some()
4311 }
4312
4313 pub fn has_property_with_type(&self, property_name: &str, type_: Type) -> bool {
4317 self.property_type(property_name)
4318 .is_some_and(|ptype| ptype.is_a(type_))
4319 }
4320
4321 #[doc(alias = "get_property_type")]
4326 pub fn property_type(&self, property_name: &str) -> Option<Type> {
4327 self.find_property(property_name)
4328 .map(|pspec| pspec.value_type())
4329 }
4330
4331 #[doc(alias = "g_object_interface_find_property")]
4334 pub fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
4335 unsafe {
4336 let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4337
4338 from_glib_none(gobject_ffi::g_object_interface_find_property(
4339 interface as *mut _,
4340 property_name.to_glib_none().0,
4341 ))
4342 }
4343 }
4344
4345 #[doc(alias = "g_object_interface_list_properties")]
4348 pub fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
4349 unsafe {
4350 let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4351
4352 let mut n_properties = 0;
4353
4354 let props = gobject_ffi::g_object_interface_list_properties(
4355 interface as *mut _,
4356 &mut n_properties,
4357 );
4358 PtrSlice::from_glib_container_num(props, n_properties as usize, true)
4359 }
4360 }
4361}
4362
4363unsafe impl<T: IsInterface> Send for Interface<T> {}
4364unsafe impl<T: IsInterface> Sync for Interface<T> {}
4365
4366impl<T: IsInterface> AsRef<T::GlibClassType> for Interface<T> {
4367 #[inline]
4368 fn as_ref(&self) -> &T::GlibClassType {
4369 &self.0
4370 }
4371}
4372
4373impl<T: IsInterface> AsMut<T::GlibClassType> for Interface<T> {
4374 #[inline]
4375 fn as_mut(&mut self) -> &mut T::GlibClassType {
4376 &mut self.0
4377 }
4378}
4379
4380#[derive(Debug)]
4383pub struct InterfaceRef<'a, T: IsInterface>(ptr::NonNull<Interface<T>>, bool, PhantomData<&'a ()>);
4384
4385impl<T: IsInterface> Drop for InterfaceRef<'_, T> {
4386 #[inline]
4387 fn drop(&mut self) {
4388 if self.1 {
4389 unsafe {
4390 gobject_ffi::g_type_default_interface_unref(self.0.as_ptr() as *mut _);
4391 }
4392 }
4393 }
4394}
4395
4396impl<T: IsInterface> ops::Deref for InterfaceRef<'_, T> {
4397 type Target = Interface<T>;
4398
4399 #[inline]
4400 fn deref(&self) -> &Interface<T> {
4401 unsafe { self.0.as_ref() }
4402 }
4403}
4404
4405unsafe impl<T: IsInterface> Send for InterfaceRef<'_, T> {}
4406unsafe impl<T: IsInterface> Sync for InterfaceRef<'_, T> {}
4407
4408pub unsafe trait IsInterface: ObjectType {}
4411
4412pub struct ObjectValueTypeChecker<T>(std::marker::PhantomData<T>);
4415
4416unsafe impl<T: StaticType> crate::value::ValueTypeChecker for ObjectValueTypeChecker<T> {
4417 type Error = crate::value::ValueTypeMismatchOrNoneError<crate::value::ValueTypeMismatchError>;
4418
4419 fn check(value: &Value) -> Result<(), Self::Error> {
4420 unsafe {
4425 let requested_type = T::static_type().into_glib();
4426 let type_ = value.inner.g_type;
4427
4428 if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4430 let obj = gobject_ffi::g_value_get_object(&value.inner);
4431 if obj.is_null() {
4432 return Err(Self::Error::UnexpectedNone);
4433 } else {
4434 return Ok(());
4435 }
4436 }
4437
4438 if gobject_ffi::g_type_is_a(type_, gobject_ffi::G_TYPE_OBJECT) == ffi::GFALSE {
4440 return Err(crate::value::ValueTypeMismatchError::new(
4441 Type::from_glib(type_),
4442 T::static_type(),
4443 )
4444 .into());
4445 }
4446
4447 let obj = gobject_ffi::g_value_get_object(&value.inner);
4449
4450 if obj.is_null() {
4452 return Err(Self::Error::UnexpectedNone);
4453 }
4454
4455 let type_ = (*(*obj).g_type_instance.g_class).g_type;
4456 if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4458 Ok(())
4459 } else {
4460 Err(crate::value::ValueTypeMismatchError::new(
4461 Type::from_glib(type_),
4462 T::static_type(),
4463 )
4464 .into())
4465 }
4466 }
4467 }
4468}
4469
4470#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4475#[repr(transparent)]
4476pub struct BorrowedObject<'a, T> {
4477 ptr: ptr::NonNull<gobject_ffi::GObject>,
4478 phantom: PhantomData<&'a T>,
4479}
4480
4481unsafe impl<T: Send + Sync> Send for BorrowedObject<'_, T> {}
4482unsafe impl<T: Send + Sync> Sync for BorrowedObject<'_, T> {}
4483
4484impl<'a, T: ObjectType> BorrowedObject<'a, T> {
4485 #[inline]
4492 pub unsafe fn new(ptr: *mut T::GlibType) -> BorrowedObject<'a, T> {
4493 unsafe {
4494 BorrowedObject {
4495 ptr: ptr::NonNull::new_unchecked(ptr as *mut _),
4496 phantom: PhantomData,
4497 }
4498 }
4499 }
4500
4501 #[inline]
4504 pub fn downgrade(&self) -> <Self as crate::clone::Downgrade>::Weak
4505 where
4506 T: crate::clone::Downgrade,
4507 {
4508 <T as crate::clone::Downgrade>::downgrade(self)
4509 }
4510}
4511
4512impl<T> ops::Deref for BorrowedObject<'_, T> {
4513 type Target = T;
4514
4515 #[inline]
4516 fn deref(&self) -> &T {
4517 unsafe { &*(&self.ptr as *const _ as *const T) }
4518 }
4519}
4520
4521impl<T> AsRef<T> for BorrowedObject<'_, T> {
4522 #[inline]
4523 fn as_ref(&self) -> &T {
4524 unsafe { &*(&self.ptr as *const _ as *const T) }
4525 }
4526}
4527
4528impl<T: PartialEq> PartialEq<T> for BorrowedObject<'_, T> {
4529 #[inline]
4530 fn eq(&self, other: &T) -> bool {
4531 <T as PartialEq>::eq(self, other)
4532 }
4533}
4534
4535impl<T: PartialOrd> PartialOrd<T> for BorrowedObject<'_, T> {
4536 #[inline]
4537 fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
4538 <T as PartialOrd>::partial_cmp(self, other)
4539 }
4540}
4541
4542impl<T: crate::clone::Downgrade + ObjectType> crate::clone::Downgrade for BorrowedObject<'_, T> {
4543 type Weak = <T as crate::clone::Downgrade>::Weak;
4544
4545 #[inline]
4546 fn downgrade(&self) -> Self::Weak {
4547 <T as crate::clone::Downgrade>::downgrade(self)
4548 }
4549}
4550
4551#[cfg(test)]
4552mod tests {
4553 use std::{
4554 cell::Cell,
4555 rc::Rc,
4556 sync::{
4557 Arc,
4558 atomic::{AtomicBool, Ordering},
4559 },
4560 };
4561
4562 use super::*;
4563
4564 #[test]
4565 fn new() {
4566 let obj: Object = Object::new();
4567 drop(obj);
4568 }
4569
4570 #[test]
4571 fn data() {
4572 let obj: Object = Object::new();
4573 unsafe {
4574 obj.set_data::<String>("foo", "hello".into());
4575 let data = obj.data::<String>("foo").unwrap();
4576 assert_eq!(data.as_ref(), "hello");
4577 let data2 = obj.steal_data::<String>("foo").unwrap();
4578 assert_eq!(data2, "hello");
4579 }
4580 }
4581
4582 #[test]
4583 fn weak_ref() {
4584 let obj: Object = Object::new();
4585
4586 let weakref: WeakRef<Object> = WeakRef::new();
4587 weakref.set(Some(&obj));
4588 assert!(weakref.upgrade().is_some());
4589 weakref.set(None);
4590 assert!(weakref.upgrade().is_none());
4591
4592 let weakref = WeakRef::new();
4593 weakref.set(Some(&obj));
4594 assert!(weakref.upgrade().is_some());
4595
4596 drop(obj);
4597 assert!(weakref.upgrade().is_none());
4598 }
4599
4600 #[test]
4601 fn weak_ref_notify() {
4602 let obj: Object = Object::new();
4603
4604 let handle = obj.add_weak_ref_notify(|| {
4605 unreachable!();
4606 });
4607
4608 handle.disconnect();
4609
4610 let called = Arc::new(AtomicBool::new(false));
4611 let called_weak = Arc::downgrade(&called);
4612 let handle = obj.add_weak_ref_notify(move || {
4613 called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4614 });
4615
4616 drop(obj);
4617 assert!(called.load(Ordering::SeqCst));
4618 handle.disconnect();
4619
4620 let obj: Object = Object::new();
4621
4622 let called = Arc::new(AtomicBool::new(false));
4623 let called_weak = Arc::downgrade(&called);
4624 obj.add_weak_ref_notify(move || {
4625 called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4626 });
4627
4628 drop(obj);
4629 assert!(called.load(Ordering::SeqCst));
4630
4631 let obj: Object = Object::new();
4632
4633 let called = Rc::new(Cell::new(false));
4634 let called_weak = Rc::downgrade(&called);
4635 obj.add_weak_ref_notify_local(move || {
4636 called_weak.upgrade().unwrap().set(true);
4637 });
4638
4639 drop(obj);
4640 assert!(called.get());
4641 }
4642
4643 #[test]
4644 fn test_value() {
4645 let obj1: Object = Object::new();
4646 let v = obj1.to_value();
4647 let obj2 = v.get::<&Object>().unwrap();
4648
4649 assert_eq!(obj1.as_ptr(), obj2.as_ptr());
4650 }
4651
4652 #[test]
4653 fn test_borrow_hashing() {
4654 let mut m = std::collections::HashSet::new();
4655 let boxed_object = crate::BoxedAnyObject::new("");
4656
4657 m.insert(boxed_object.clone());
4658
4659 let object: &Object = std::borrow::Borrow::borrow(&boxed_object);
4660 assert_eq!(m.get(object), Some(&boxed_object));
4661 }
4662}