glib/
object.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! `IMPL` Object wrapper implementation and `Object` binding.
5
6use std::{cmp, fmt, hash, marker::PhantomData, mem, mem::ManuallyDrop, ops, pin::Pin, ptr};
7
8use crate::{
9    closure::TryFromClosureReturnValue,
10    ffi, gobject_ffi,
11    prelude::*,
12    quark::Quark,
13    subclass::{prelude::*, SignalId, SignalQuery},
14    thread_guard::thread_id,
15    translate::*,
16    value::FromValue,
17    Closure, PtrSlice, RustClosure, SignalHandlerId, Type, Value,
18};
19
20// rustdoc-stripper-ignore-next
21/// Implemented by types representing `glib::Object` and subclasses of it.
22pub 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    // rustdoc-stripper-ignore-next
42    /// type of the FFI Instance structure.
43    type GlibType: 'static;
44    // rustdoc-stripper-ignore-next
45    /// type of the FFI Class structure.
46    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// rustdoc-stripper-ignore-next
55/// Declares the "is a" relationship.
56///
57/// `Self` is said to implement `T`.
58///
59/// For instance, since originally `GtkWidget` is a subclass of `GObject` and
60/// implements the `GtkBuildable` interface, `gtk::Widget` implements
61/// `IsA<glib::Object>` and `IsA<gtk::Buildable>`.
62///
63///
64/// The trait can only be implemented if the appropriate `ToGlibPtr`
65/// implementations exist.
66pub unsafe trait IsA<T: ObjectType>:
67    ObjectType + Into<T> + AsRef<T> + std::borrow::Borrow<T>
68{
69}
70
71// rustdoc-stripper-ignore-next
72/// Upcasting and downcasting support.
73///
74/// Provides conversions up and down the class hierarchy tree.
75pub trait Cast: ObjectType {
76    // rustdoc-stripper-ignore-next
77    /// Upcasts an object to a superclass or interface `T`.
78    ///
79    /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
80    /// known at compile-time, whether a specific object implements an interface or not, in which case
81    /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
82    /// is checking the types at runtime.
83    ///
84    /// # Example
85    ///
86    /// ```ignore
87    /// let button = gtk::Button::new();
88    /// let widget = button.upcast::<gtk::Widget>();
89    /// ```
90    #[inline]
91    fn upcast<T: ObjectType>(self) -> T
92    where
93        Self: IsA<T>,
94    {
95        unsafe { self.unsafe_cast() }
96    }
97
98    // rustdoc-stripper-ignore-next
99    /// Upcasts an object to a reference of its superclass or interface `T`.
100    ///
101    /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
102    /// known at compile-time, whether a specific object implements an interface or not, in which case
103    /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
104    /// is checking the types at runtime.
105    ///
106    /// # Example
107    ///
108    /// ```ignore
109    /// let button = gtk::Button::new();
110    /// let widget = button.upcast_ref::<gtk::Widget>();
111    /// ```
112    #[inline]
113    fn upcast_ref<T: ObjectType>(&self) -> &T
114    where
115        Self: IsA<T>,
116    {
117        unsafe { self.unsafe_cast_ref() }
118    }
119
120    // rustdoc-stripper-ignore-next
121    /// Tries to downcast to a subclass or interface implementor `T`.
122    ///
123    /// Returns `Ok(T)` if the object is an instance of `T` and `Err(self)`
124    /// otherwise.
125    ///
126    /// *NOTE*: This will check at compile-time if `T` is lower down the
127    /// inheritance tree of `Self`, but also check at runtime if downcasting
128    /// is indeed possible.
129    ///
130    /// # Example
131    ///
132    /// ```ignore
133    /// let button = gtk::Button::new();
134    /// let widget = button.upcast::<gtk::Widget>();
135    /// assert!(widget.downcast::<gtk::Button>().is_ok());
136    /// ```
137    #[inline]
138    fn downcast<T: ObjectType>(self) -> Result<T, Self>
139    where
140        Self: MayDowncastTo<T>,
141    {
142        if self.is::<T>() {
143            Ok(unsafe { self.unsafe_cast() })
144        } else {
145            Err(self)
146        }
147    }
148
149    // rustdoc-stripper-ignore-next
150    /// Tries to downcast to a reference of its subclass or interface implementor `T`.
151    ///
152    /// Returns `Some(T)` if the object is an instance of `T` and `None`
153    /// otherwise.
154    ///
155    /// *NOTE*: This will check at compile-time if `T` is lower down the
156    /// inheritance tree of `Self`, but also check at runtime if downcasting
157    /// is indeed possible.
158    ///
159    /// # Example
160    ///
161    /// ```ignore
162    /// let button = gtk::Button::new();
163    /// let widget = button.upcast::<gtk::Widget>();
164    /// assert!(widget.downcast_ref::<gtk::Button>().is_some());
165    /// ```
166    #[inline]
167    fn downcast_ref<T: ObjectType>(&self) -> Option<&T>
168    where
169        Self: MayDowncastTo<T>,
170    {
171        if self.is::<T>() {
172            Some(unsafe { self.unsafe_cast_ref() })
173        } else {
174            None
175        }
176    }
177
178    // rustdoc-stripper-ignore-next
179    /// Tries to cast to an object of type `T`. This handles upcasting, downcasting
180    /// and casting between interface and interface implementors. All checks are performed at
181    /// runtime, while `upcast` will do many checks at compile-time already. `downcast` will
182    /// perform the same checks at runtime as `dynamic_cast`, but will also ensure some amount of
183    /// compile-time safety.
184    ///
185    /// It is not always known at compile-time, whether a specific object implements an interface or
186    /// not, and checking has to be performed at runtime.
187    ///
188    /// Returns `Ok(T)` if the object is an instance of `T` and `Err(self)`
189    /// otherwise.
190    ///
191    /// # Example
192    ///
193    /// ```ignore
194    /// let button = gtk::Button::new();
195    /// let widget = button.dynamic_cast::<gtk::Widget>();
196    /// assert!(widget.is_ok());
197    /// let widget = widget.unwrap();
198    /// assert!(widget.dynamic_cast::<gtk::Button>().is_ok());
199    /// ```
200    #[inline]
201    fn dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
202        if !self.is::<T>() {
203            Err(self)
204        } else {
205            Ok(unsafe { self.unsafe_cast() })
206        }
207    }
208
209    // rustdoc-stripper-ignore-next
210    /// Tries to cast to reference to an object of type `T`. This handles upcasting, downcasting
211    /// and casting between interface and interface implementors. All checks are performed at
212    /// runtime, while `downcast` and `upcast` will do many checks at compile-time already.
213    ///
214    /// It is not always known at compile-time, whether a specific object implements an interface or
215    /// not, and checking has to be performed at runtime.
216    ///
217    /// Returns `Some(T)` if the object is an instance of `T` and `None`
218    /// otherwise.
219    ///
220    /// # Example
221    ///
222    /// ```ignore
223    /// let button = gtk::Button::new();
224    /// let widget = button.dynamic_cast_ref::<gtk::Widget>();
225    /// assert!(widget.is_some());
226    /// let widget = widget.unwrap();
227    /// assert!(widget.dynamic_cast_ref::<gtk::Button>().is_some());
228    /// ```
229    #[inline]
230    fn dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
231        if !self.is::<T>() {
232            None
233        } else {
234            // This cast is safe because all our wrapper types have the
235            // same representation except for the name and the phantom data
236            // type. IsA<> is an unsafe trait that must only be implemented
237            // if this is a valid wrapper type
238            Some(unsafe { self.unsafe_cast_ref() })
239        }
240    }
241
242    // rustdoc-stripper-ignore-next
243    /// Casts to `T` unconditionally.
244    ///
245    /// # Panics
246    ///
247    /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
248    ///
249    /// # Safety
250    ///
251    /// If not running with `debug_assertions` enabled, the caller is responsible
252    /// for ensuring that the instance implements `T`
253    #[track_caller]
254    #[inline]
255    unsafe fn unsafe_cast<T: ObjectType>(self) -> T {
256        debug_assert!(self.is::<T>());
257        T::unsafe_from(self.into())
258    }
259
260    // rustdoc-stripper-ignore-next
261    /// Casts to `&T` unconditionally.
262    ///
263    /// # Panics
264    ///
265    /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
266    ///
267    /// # Safety
268    ///
269    /// If not running with `debug_assertions` enabled, the caller is responsible
270    /// for ensuring that the instance implements `T`
271    #[track_caller]
272    #[inline]
273    unsafe fn unsafe_cast_ref<T: ObjectType>(&self) -> &T {
274        debug_assert!(self.is::<T>());
275        // This cast is safe because all our wrapper types have the
276        // same representation except for the name and the phantom data
277        // type. IsA<> is an unsafe trait that must only be implemented
278        // if this is a valid wrapper type
279        &*(self as *const Self as *const T)
280    }
281}
282
283impl<T: ObjectType> Cast for T {}
284
285// rustdoc-stripper-ignore-next
286/// Convenience trait mirroring `Cast`, implemented on `Option<Object>` types.
287///
288/// # Warning
289/// Inevitably this trait will discard information about a downcast failure:
290/// you don't know if the object was not of the expected type, or if it was `None`.
291/// If you need to handle the downcast error, use `Cast` over a `glib::Object`.
292///
293/// # Example
294/// ```ignore
295/// let widget: Option<Widget> = list_item.child();
296///
297/// // Without using `CastNone`
298/// let label = widget.unwrap().downcast::<gtk::Label>().unwrap();
299///
300/// // Using `CastNone` we can avoid the first `unwrap()` call
301/// let label = widget.and_downcast::<gtk::Label>().unwrap();
302/// ````
303pub trait CastNone: Sized {
304    type Inner;
305    fn and_downcast<T: ObjectType>(self) -> Option<T>
306    where
307        Self::Inner: MayDowncastTo<T>;
308    fn and_downcast_ref<T: ObjectType>(&self) -> Option<&T>
309    where
310        Self::Inner: MayDowncastTo<T>;
311    fn and_upcast<T: ObjectType>(self) -> Option<T>
312    where
313        Self::Inner: IsA<T>;
314    fn and_upcast_ref<T: ObjectType>(&self) -> Option<&T>
315    where
316        Self::Inner: IsA<T>;
317    fn and_dynamic_cast<T: ObjectType>(self) -> Result<T, Self>;
318    fn and_dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T>;
319}
320impl<I: ObjectType + Sized> CastNone for Option<I> {
321    type Inner = I;
322
323    #[inline]
324    fn and_downcast<T: ObjectType>(self) -> Option<T>
325    where
326        Self::Inner: MayDowncastTo<T>,
327    {
328        self.and_then(|i| i.downcast().ok())
329    }
330
331    #[inline]
332    fn and_downcast_ref<T: ObjectType>(&self) -> Option<&T>
333    where
334        Self::Inner: MayDowncastTo<T>,
335    {
336        self.as_ref().and_then(|i| i.downcast_ref())
337    }
338
339    #[inline]
340    fn and_upcast<T: ObjectType>(self) -> Option<T>
341    where
342        Self::Inner: IsA<T>,
343    {
344        self.map(|i| i.upcast())
345    }
346
347    #[inline]
348    fn and_upcast_ref<T: ObjectType>(&self) -> Option<&T>
349    where
350        Self::Inner: IsA<T>,
351    {
352        self.as_ref().map(|i| i.upcast_ref())
353    }
354
355    #[inline]
356    fn and_dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
357        self.ok_or(None)
358            .and_then(|i| i.dynamic_cast().map_err(|e| Some(e)))
359    }
360
361    #[inline]
362    fn and_dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
363        self.as_ref().and_then(|i| i.dynamic_cast_ref())
364    }
365}
366
367// rustdoc-stripper-ignore-next
368/// Marker trait for the statically known possibility of downcasting from `Self` to `T`.
369pub trait MayDowncastTo<T> {}
370
371impl<Super: IsA<Super>, Sub: IsA<Super>> MayDowncastTo<Sub> for Super {}
372
373// Manual implementation of glib_shared_wrapper! because of special cases
374#[repr(transparent)]
375pub struct ObjectRef {
376    inner: ptr::NonNull<gobject_ffi::GObject>,
377}
378
379impl Clone for ObjectRef {
380    #[inline]
381    fn clone(&self) -> Self {
382        unsafe {
383            Self {
384                inner: ptr::NonNull::new_unchecked(gobject_ffi::g_object_ref(self.inner.as_ptr())),
385            }
386        }
387    }
388}
389
390impl Drop for ObjectRef {
391    #[inline]
392    fn drop(&mut self) {
393        unsafe {
394            gobject_ffi::g_object_unref(self.inner.as_ptr());
395        }
396    }
397}
398
399impl fmt::Debug for ObjectRef {
400    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
401        let type_ = unsafe {
402            let klass = (*self.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
403            (*klass).type_()
404        };
405
406        f.debug_struct("ObjectRef")
407            .field("inner", &self.inner)
408            .field("type", &type_)
409            .finish()
410    }
411}
412
413impl PartialOrd for ObjectRef {
414    #[inline]
415    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
416        Some(self.cmp(other))
417    }
418}
419
420impl Ord for ObjectRef {
421    #[inline]
422    fn cmp(&self, other: &Self) -> cmp::Ordering {
423        self.inner.cmp(&other.inner)
424    }
425}
426
427impl PartialEq for ObjectRef {
428    #[inline]
429    fn eq(&self, other: &Self) -> bool {
430        self.inner == other.inner
431    }
432}
433
434impl Eq for ObjectRef {}
435
436impl hash::Hash for ObjectRef {
437    #[inline]
438    fn hash<H>(&self, state: &mut H)
439    where
440        H: hash::Hasher,
441    {
442        self.inner.hash(state)
443    }
444}
445
446#[doc(hidden)]
447impl GlibPtrDefault for ObjectRef {
448    type GlibType = *mut gobject_ffi::GObject;
449}
450
451#[doc(hidden)]
452impl<'a> ToGlibPtr<'a, *mut gobject_ffi::GObject> for ObjectRef {
453    type Storage = PhantomData<&'a ObjectRef>;
454
455    #[inline]
456    fn to_glib_none(&'a self) -> Stash<'a, *mut gobject_ffi::GObject, Self> {
457        Stash(self.inner.as_ptr(), PhantomData)
458    }
459
460    #[inline]
461    fn to_glib_full(&self) -> *mut gobject_ffi::GObject {
462        unsafe { gobject_ffi::g_object_ref(self.inner.as_ptr()) }
463    }
464}
465
466#[doc(hidden)]
467impl FromGlibPtrNone<*mut gobject_ffi::GObject> for ObjectRef {
468    #[inline]
469    unsafe fn from_glib_none(ptr: *mut gobject_ffi::GObject) -> Self {
470        debug_assert!(!ptr.is_null());
471        debug_assert_ne!((*ptr).ref_count, 0);
472
473        // Attention: This takes ownership of floating references!
474        Self {
475            inner: ptr::NonNull::new_unchecked(gobject_ffi::g_object_ref_sink(ptr)),
476        }
477    }
478}
479
480#[doc(hidden)]
481impl FromGlibPtrNone<*const gobject_ffi::GObject> for ObjectRef {
482    #[inline]
483    unsafe fn from_glib_none(ptr: *const gobject_ffi::GObject) -> Self {
484        // Attention: This takes ownership of floating references!
485        from_glib_none(ptr as *mut gobject_ffi::GObject)
486    }
487}
488
489#[doc(hidden)]
490impl FromGlibPtrFull<*mut gobject_ffi::GObject> for ObjectRef {
491    #[inline]
492    unsafe fn from_glib_full(ptr: *mut gobject_ffi::GObject) -> Self {
493        debug_assert!(!ptr.is_null());
494        debug_assert_ne!((*ptr).ref_count, 0);
495
496        Self {
497            inner: ptr::NonNull::new_unchecked(ptr),
498        }
499    }
500}
501
502#[doc(hidden)]
503impl FromGlibPtrBorrow<*mut gobject_ffi::GObject> for ObjectRef {
504    #[inline]
505    unsafe fn from_glib_borrow(ptr: *mut gobject_ffi::GObject) -> Borrowed<Self> {
506        debug_assert!(!ptr.is_null());
507        debug_assert_ne!((*ptr).ref_count, 0);
508
509        Borrowed::new(Self {
510            inner: ptr::NonNull::new_unchecked(ptr),
511        })
512    }
513}
514
515#[doc(hidden)]
516impl FromGlibPtrBorrow<*const gobject_ffi::GObject> for ObjectRef {
517    #[inline]
518    unsafe fn from_glib_borrow(ptr: *const gobject_ffi::GObject) -> Borrowed<Self> {
519        from_glib_borrow(ptr as *mut gobject_ffi::GObject)
520    }
521}
522
523#[repr(transparent)]
524pub struct TypedObjectRef<T, P> {
525    inner: ObjectRef,
526    imp: PhantomData<T>,
527    parent: PhantomData<P>,
528}
529
530impl<T, P> TypedObjectRef<T, P> {
531    #[inline]
532    pub unsafe fn new(obj: ObjectRef) -> Self {
533        Self {
534            inner: obj,
535            imp: PhantomData,
536            parent: PhantomData,
537        }
538    }
539
540    #[inline]
541    pub fn into_inner(self) -> ObjectRef {
542        self.inner
543    }
544}
545
546impl<T, P> Clone for TypedObjectRef<T, P> {
547    #[inline]
548    fn clone(&self) -> Self {
549        Self {
550            inner: self.inner.clone(),
551            imp: PhantomData,
552            parent: PhantomData,
553        }
554    }
555}
556
557impl<T, P> ops::Deref for TypedObjectRef<T, P> {
558    type Target = ObjectRef;
559
560    #[inline]
561    fn deref(&self) -> &Self::Target {
562        &self.inner
563    }
564}
565
566impl<T, P> fmt::Debug for TypedObjectRef<T, P> {
567    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568        let type_ = unsafe {
569            let klass = (*self.inner.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
570            (*klass).type_()
571        };
572
573        f.debug_struct("TypedObjectRef")
574            .field("inner", &self.inner.inner)
575            .field("type", &type_)
576            .finish()
577    }
578}
579
580impl<T, P> PartialOrd for TypedObjectRef<T, P> {
581    #[inline]
582    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
583        Some(self.cmp(other))
584    }
585}
586
587impl<T, P> Ord for TypedObjectRef<T, P> {
588    #[inline]
589    fn cmp(&self, other: &Self) -> cmp::Ordering {
590        self.inner.cmp(&other.inner)
591    }
592}
593
594impl<T, P> PartialEq for TypedObjectRef<T, P> {
595    #[inline]
596    fn eq(&self, other: &Self) -> bool {
597        self.inner == other.inner
598    }
599}
600
601impl<T, P> Eq for TypedObjectRef<T, P> {}
602
603impl<T, P> hash::Hash for TypedObjectRef<T, P> {
604    #[inline]
605    fn hash<H>(&self, state: &mut H)
606    where
607        H: hash::Hasher,
608    {
609        self.inner.hash(state)
610    }
611}
612
613unsafe impl<T: Send + Sync, P: Send + Sync> Send for TypedObjectRef<T, P> {}
614unsafe impl<T: Send + Sync, P: Send + Sync> Sync for TypedObjectRef<T, P> {}
615
616// rustdoc-stripper-ignore-next
617/// ObjectType implementations for Object types. See `wrapper!`.
618#[macro_export]
619macro_rules! glib_object_wrapper {
620    (@generic_impl [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty, $ffi_class_name:ty, @type_ $get_type_expr:expr) => {
621        $(#[$attr])*
622        #[doc = "\n\nGLib type: GObject with reference counted clone semantics."]
623        #[repr(transparent)]
624        $visibility struct $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? {
625            inner: $crate::object::TypedObjectRef<$impl_type, $parent_type>,
626            phantom: std::marker::PhantomData<($($($generic),+)?)>,
627        }
628
629        // Always implement Clone, Hash, PartialEq, Eq, PartialOrd, Ord, and Debug for object types.
630        // Due to inheritance and up/downcasting we must implement these by pointer or otherwise they
631        // would potentially give different results for the same object depending on the type we
632        // currently know for it.
633        // Implement them manually rather than generating #[derive] macros since so that when generics
634        // are specified, these traits are not required.
635
636        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::clone::Clone for $name $(<$($generic),+>)? {
637            #[doc = "Makes a clone of this shared reference.\n\nThis increments the strong reference count of the object. Dropping the object will decrement it again."]
638            #[inline]
639            fn clone(&self) -> Self {
640                Self {
641                    inner: std::clone::Clone::clone(&self.inner),
642                    phantom: std::marker::PhantomData,
643                }
644            }
645        }
646
647        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::hash::Hash for $name $(<$($generic),+>)? {
648            #[doc = "Hashes the memory address of this object."]
649            #[inline]
650            fn hash<H>(&self, state: &mut H)
651            where
652                H: std::hash::Hasher
653            {
654                std::hash::Hash::hash(&self.inner, state);
655            }
656        }
657
658        impl<OT: $crate::object::ObjectType $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> std::cmp::PartialEq<OT> for $name $(<$($generic),+>)? {
659            #[doc = "Equality for two GObjects.\n\nTwo GObjects are equal if their memory addresses are equal."]
660            #[inline]
661            fn eq(&self, other: &OT) -> bool {
662                std::cmp::PartialEq::eq(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
663            }
664        }
665
666        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::cmp::Eq for $name $(<$($generic),+>)? {}
667
668        impl<OT: $crate::object::ObjectType $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> std::cmp::PartialOrd<OT> for $name $(<$($generic),+>)? {
669            #[doc = "Partial comparison for two GObjects.\n\nCompares the memory addresses of the provided objects."]
670            #[inline]
671            fn partial_cmp(&self, other: &OT) -> Option<std::cmp::Ordering> {
672                std::cmp::PartialOrd::partial_cmp(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
673            }
674        }
675
676        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::cmp::Ord for $name $(<$($generic),+>)? {
677            #[doc = "Comparison for two GObjects.\n\nCompares the memory addresses of the provided objects."]
678            #[inline]
679            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
680                std::cmp::Ord::cmp(&*self.inner, $crate::object::ObjectType::as_object_ref(other))
681            }
682        }
683
684
685        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::fmt::Debug for $name $(<$($generic),+>)? {
686            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
687                f.debug_struct(stringify!($name)).field("inner", &self.inner).finish()
688            }
689        }
690
691        #[doc(hidden)]
692        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::ObjectRef {
693            #[inline]
694            fn from(s: $name $(<$($generic),+>)?) -> $crate::object::ObjectRef {
695                s.inner.into_inner()
696            }
697        }
698
699        #[doc(hidden)]
700        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::UnsafeFrom<$crate::object::ObjectRef> for $name $(<$($generic),+>)? {
701            #[inline]
702            unsafe fn unsafe_from(t: $crate::object::ObjectRef) -> Self {
703                $name {
704                    inner: $crate::object::TypedObjectRef::new(t),
705                    phantom: std::marker::PhantomData,
706                }
707            }
708        }
709
710        #[doc(hidden)]
711        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::GlibPtrDefault for $name $(<$($generic),+>)? {
712            type GlibType = *mut $ffi_name;
713        }
714
715        #[doc(hidden)]
716        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::TransparentPtrType for $name $(<$($generic),+>)? {}
717
718        #[doc(hidden)]
719        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectType for $name $(<$($generic),+>)? {
720            type GlibType = $ffi_name;
721            type GlibClassType = $ffi_class_name;
722
723            #[inline]
724            fn as_object_ref(&self) -> &$crate::object::ObjectRef {
725                &self.inner
726            }
727
728            #[inline]
729            fn as_ptr(&self) -> *mut Self::GlibType {
730                unsafe { *(self as *const Self as *const *const $ffi_name) as *mut $ffi_name }
731            }
732
733            #[inline]
734            unsafe fn from_glib_ptr_borrow(ptr: &*mut Self::GlibType) -> &Self {
735                debug_assert_eq!(
736                    std::mem::size_of::<Self>(),
737                    std::mem::size_of::<$crate::ffi::gpointer>()
738                );
739                debug_assert!(!ptr.is_null());
740                debug_assert_ne!((*(*ptr as *const $crate::gobject_ffi::GObject)).ref_count, 0);
741                &*(ptr as *const *mut $ffi_name as *const Self)
742            }
743        }
744
745        #[doc(hidden)]
746        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::ObjectRef> for $name $(<$($generic),+>)? {
747            #[inline]
748            fn as_ref(&self) -> &$crate::object::ObjectRef {
749                &self.inner
750            }
751        }
752
753        #[doc(hidden)]
754        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<Self> for $name $(<$($generic),+>)? {
755            #[inline]
756            fn as_ref(&self) -> &Self {
757                self
758            }
759        }
760
761        #[doc(hidden)]
762        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<Self> for $name $(<$($generic),+>)? { }
763
764        #[doc(hidden)]
765        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::subclass::types::FromObject for $name $(<$($generic),+>)? {
766            type FromObjectType = Self;
767
768            #[inline]
769            fn from_object(obj: &Self::FromObjectType) -> &Self {
770                obj
771            }
772        }
773
774        #[doc(hidden)]
775        impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name $(<$($generic),+>)? {
776            type Storage = <$crate::object::ObjectRef as
777                $crate::translate::ToGlibPtr<'a, *mut $crate::gobject_ffi::GObject>>::Storage;
778
779            #[inline]
780            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
781                let stash = $crate::translate::ToGlibPtr::to_glib_none(&*self.inner);
782                $crate::translate::Stash(stash.0 as *const _, stash.1)
783            }
784
785            #[inline]
786            fn to_glib_full(&self) -> *const $ffi_name {
787                $crate::translate::ToGlibPtr::to_glib_full(&*self.inner) as *const _
788            }
789        }
790
791        #[doc(hidden)]
792        impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name $(<$($generic),+>)? {
793            type Storage = <$crate::object::ObjectRef as
794                $crate::translate::ToGlibPtr<'a, *mut $crate::gobject_ffi::GObject>>::Storage;
795
796            #[inline]
797            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
798                let stash = $crate::translate::ToGlibPtr::to_glib_none(&*self.inner);
799                $crate::translate::Stash(stash.0 as *mut _, stash.1)
800            }
801
802            #[inline]
803            fn to_glib_full(&self) -> *mut $ffi_name {
804                $crate::translate::ToGlibPtr::to_glib_full(&*self.inner) as *mut _
805            }
806        }
807
808        #[doc(hidden)]
809        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*mut $ffi_name> for $name $(<$($generic),+>)? {
810            #[inline]
811            unsafe fn into_glib_ptr(self) -> *mut $ffi_name {
812                let s = std::mem::ManuallyDrop::new(self);
813                $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *mut _
814            }
815        }
816
817        #[doc(hidden)]
818        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*const $ffi_name> for $name $(<$($generic),+>)? {
819            #[inline]
820            unsafe fn into_glib_ptr(self) -> *const $ffi_name {
821                let s = std::mem::ManuallyDrop::new(self);
822                $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *const _
823            }
824        }
825
826        #[doc(hidden)]
827        impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
828            type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*mut $ffi_name>>);
829
830            fn to_glib_none_from_slice(t: &'a [Self]) -> (*mut *mut $ffi_name, Self::Storage) {
831                let mut v_ptr = Vec::with_capacity(t.len() + 1);
832                unsafe {
833                    let ptr = v_ptr.as_mut_ptr();
834                    std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *mut $ffi_name, ptr, t.len());
835                    std::ptr::write(ptr.add(t.len()), std::ptr::null_mut());
836                    v_ptr.set_len(t.len() + 1);
837                }
838
839                (v_ptr.as_ptr() as *mut *mut $ffi_name, (std::marker::PhantomData, Some(v_ptr)))
840            }
841
842            fn to_glib_container_from_slice(t: &'a [Self]) -> (*mut *mut $ffi_name, Self::Storage) {
843                let v_ptr = unsafe {
844                    let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
845
846                    std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *mut $ffi_name, v_ptr, t.len());
847                    std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut());
848
849                    v_ptr
850                };
851
852                (v_ptr, (std::marker::PhantomData, None))
853            }
854
855            fn to_glib_full_from_slice(t: &[Self]) -> *mut *mut $ffi_name {
856                unsafe {
857                    let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
858
859                    for (i, s) in t.iter().enumerate() {
860                        std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
861                    }
862                    std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut());
863
864                    v_ptr
865                }
866            }
867        }
868
869        #[doc(hidden)]
870        impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
871            type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*mut $ffi_name>>);
872
873            fn to_glib_none_from_slice(t: &'a [Self]) -> (*const *mut $ffi_name, Self::Storage) {
874                let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *mut $ffi_name>::to_glib_none_from_slice(t);
875                (ptr as *const *mut $ffi_name, stash)
876            }
877
878            fn to_glib_container_from_slice(_: &'a [Self]) -> (*const *mut $ffi_name, Self::Storage) {
879                // Can't have consumer free a *const pointer
880                unimplemented!()
881            }
882
883            fn to_glib_full_from_slice(_: &[Self]) -> *const *mut $ffi_name {
884                // Can't have consumer free a *const pointer
885                unimplemented!()
886            }
887        }
888
889        #[doc(hidden)]
890        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name $(<$($generic),+>)? {
891            #[inline]
892            #[allow(clippy::cast_ptr_alignment)]
893            unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
894                debug_assert!(!ptr.is_null());
895                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
896                $name {
897                    inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_none(ptr as *mut _)),
898                    phantom: std::marker::PhantomData,
899                }
900            }
901        }
902
903        #[doc(hidden)]
904        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name $(<$($generic),+>)? {
905            #[inline]
906            #[allow(clippy::cast_ptr_alignment)]
907            unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
908                debug_assert!(!ptr.is_null());
909                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
910                $name {
911                    inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_none(ptr as *mut _)),
912                    phantom: std::marker::PhantomData,
913                }
914            }
915        }
916
917        #[doc(hidden)]
918        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name $(<$($generic),+>)? {
919            #[inline]
920            #[allow(clippy::cast_ptr_alignment)]
921            unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
922                debug_assert!(!ptr.is_null());
923                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
924                $name {
925                    inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_full(ptr as *mut _)),
926                    phantom: std::marker::PhantomData,
927                }
928            }
929        }
930
931        #[doc(hidden)]
932        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name $(<$($generic),+>)? {
933            #[inline]
934            #[allow(clippy::cast_ptr_alignment)]
935            unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> $crate::translate::Borrowed<Self> {
936                debug_assert!(!ptr.is_null());
937                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
938                $crate::translate::Borrowed::new(
939                    $name {
940                        inner: $crate::object::TypedObjectRef::new($crate::translate::from_glib_borrow::<_, $crate::object::ObjectRef>(ptr as *mut _).into_inner()),
941                        phantom: std::marker::PhantomData,
942                    }
943                )
944            }
945        }
946
947        #[doc(hidden)]
948        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name $(<$($generic),+>)? {
949            #[inline]
950            #[allow(clippy::cast_ptr_alignment)]
951            unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> $crate::translate::Borrowed<Self> {
952                $crate::translate::from_glib_borrow::<_, Self>(ptr as *mut $ffi_name)
953            }
954        }
955
956        #[doc(hidden)]
957        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
958            unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
959                if num == 0 || ptr.is_null() {
960                    return Vec::new();
961                }
962
963                let mut res = Vec::<Self>::with_capacity(num);
964                let res_ptr = res.as_mut_ptr();
965                for i in 0..num {
966                    ::std::ptr::write(res_ptr.add(i), $crate::translate::from_glib_none(std::ptr::read(ptr.add(i))));
967                }
968                res.set_len(num);
969                res
970            }
971
972            unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
973                let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
974                $crate::ffi::g_free(ptr as *mut _);
975                res
976            }
977
978            unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
979                if num == 0 || ptr.is_null() {
980                    $crate::ffi::g_free(ptr as *mut _);
981                    return Vec::new();
982                }
983
984                let mut res = Vec::with_capacity(num);
985                let res_ptr = res.as_mut_ptr();
986                ::std::ptr::copy_nonoverlapping(ptr as *mut Self, res_ptr, num);
987                res.set_len(num);
988                $crate::ffi::g_free(ptr as *mut _);
989                res
990            }
991        }
992
993        #[doc(hidden)]
994        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? {
995            unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
996                $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
997            }
998
999            unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1000                $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1001            }
1002
1003            unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
1004                $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
1005            }
1006        }
1007
1008        #[doc(hidden)]
1009        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
1010            unsafe fn from_glib_none_num_as_vec(ptr: *const *mut $ffi_name, num: usize) -> Vec<Self> {
1011                $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
1012            }
1013
1014            unsafe fn from_glib_container_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1015                // Can't free a *const
1016                unimplemented!()
1017            }
1018
1019            unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1020                // Can't free a *const
1021                unimplemented!()
1022            }
1023        }
1024
1025        #[doc(hidden)]
1026        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name $(<$($generic),+>)? {
1027            unsafe fn from_glib_none_as_vec(ptr: *const *mut $ffi_name) -> Vec<Self> {
1028                $crate::translate::FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
1029            }
1030
1031            unsafe fn from_glib_container_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1032                // Can't free a *const
1033                unimplemented!()
1034            }
1035
1036            unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1037                // Can't free a *const
1038                unimplemented!()
1039            }
1040        }
1041
1042        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::StaticType for $name $(<$($generic),+>)? {
1043            #[inline]
1044            fn static_type() -> $crate::types::Type {
1045                #[allow(unused_unsafe)]
1046                #[allow(clippy::macro_metavars_in_unsafe)]
1047                unsafe { $crate::translate::from_glib($get_type_expr) }
1048            }
1049        }
1050
1051        #[doc(hidden)]
1052        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueType for $name $(<$($generic),+>)? {
1053            type Type = $name $(<$($generic),+>)?;
1054        }
1055
1056        #[doc(hidden)]
1057        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueTypeOptional for $name $(<$($generic),+>)? { }
1058
1059        #[doc(hidden)]
1060        unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for $name $(<$($generic),+>)? {
1061            type Checker = $crate::object::ObjectValueTypeChecker<Self>;
1062
1063            #[inline]
1064            unsafe fn from_value(value: &'a $crate::Value) -> Self {
1065                let ptr = $crate::gobject_ffi::g_value_dup_object($crate::translate::ToGlibPtr::to_glib_none(value).0);
1066                debug_assert!(!ptr.is_null());
1067                debug_assert_ne!((*ptr).ref_count, 0);
1068                <Self as $crate::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(ptr as *mut $ffi_name)
1069            }
1070        }
1071
1072        #[doc(hidden)]
1073        unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for &'a $name $(<$($generic),+>)? {
1074            type Checker = $crate::object::ObjectValueTypeChecker<Self>;
1075
1076            #[inline]
1077            unsafe fn from_value(value: &'a $crate::Value) -> Self {
1078                let value = &*(value as *const $crate::Value as *const $crate::gobject_ffi::GValue);
1079                <$name $(<$($generic),+>)? as $crate::object::ObjectType>::from_glib_ptr_borrow(&*(&value.data[0].v_pointer as *const $crate::ffi::gpointer as *const *mut $ffi_name))
1080            }
1081        }
1082
1083        #[doc(hidden)]
1084        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValue for $name $(<$($generic),+>)? {
1085            #[inline]
1086            fn to_value(&self) -> $crate::Value {
1087                unsafe {
1088                    let mut value = $crate::Value::from_type_unchecked(<Self as $crate::prelude::StaticType>::static_type());
1089                    $crate::gobject_ffi::g_value_take_object(
1090                        $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1091                        $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(self) as *mut _,
1092                    );
1093                    value
1094                }
1095            }
1096
1097            #[inline]
1098            fn value_type(&self) -> $crate::Type {
1099                <Self as $crate::prelude::StaticType>::static_type()
1100            }
1101        }
1102
1103        #[doc(hidden)]
1104        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? ::std::convert::From<$name $(<$($generic),+>)?> for $crate::Value {
1105            #[inline]
1106            fn from(o: $name $(<$($generic),+>)?) -> Self {
1107                unsafe {
1108                    let mut value = $crate::Value::from_type_unchecked(<$name $(<$($generic),+>)? as $crate::prelude::StaticType>::static_type());
1109                    $crate::gobject_ffi::g_value_take_object(
1110                        $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1111                        $crate::translate::IntoGlibPtr::<*mut $ffi_name>::into_glib_ptr(o) as *mut _,
1112                    );
1113                    value
1114                }
1115            }
1116        }
1117
1118        #[doc(hidden)]
1119        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValueOptional for $name $(<$($generic),+>)? {
1120            #[inline]
1121            fn to_value_optional(s: Option<&Self>) -> $crate::Value {
1122                let mut value = $crate::Value::for_value_type::<Self>();
1123                unsafe {
1124                    $crate::gobject_ffi::g_value_take_object(
1125                        $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
1126                        $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(&s) as *mut _,
1127                    );
1128                }
1129
1130                value
1131            }
1132        }
1133
1134        $crate::glib_object_wrapper!(@weak_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?);
1135
1136        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::HasParamSpec for $name $(<$($generic),+>)? {
1137            type ParamSpec = $crate::ParamSpecObject;
1138            type SetValue = Self;
1139            type BuilderFn = fn(&str) -> $crate::ParamSpecObjectBuilder<Self>;
1140
1141            fn param_spec_builder() -> Self::BuilderFn {
1142                |name| Self::ParamSpec::builder(name)
1143            }
1144        }
1145    };
1146
1147    (@weak_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?) => {
1148        #[doc(hidden)]
1149        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::clone::Downgrade for $name $(<$($generic),+>)? {
1150            type Weak = $crate::object::WeakRef<Self>;
1151
1152            #[inline]
1153            fn downgrade(&self) -> Self::Weak {
1154                <Self as $crate::object::ObjectExt>::downgrade(&self)
1155            }
1156        }
1157    };
1158
1159    (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => { };
1160
1161    (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1162        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$super_name> for $name $(<$($generic),+>)? { }
1163
1164        #[doc(hidden)]
1165        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $super_name {
1166            #[inline]
1167            fn from(v: $name $(<$($generic),+>)?) -> Self {
1168                <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1169            }
1170        }
1171
1172        #[doc(hidden)]
1173        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$super_name> for $name $(<$($generic),+>)? {
1174            #[inline]
1175            fn as_ref(&self) -> &$super_name {
1176                $crate::object::Cast::upcast_ref(self)
1177            }
1178        }
1179
1180        #[doc(hidden)]
1181        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$super_name> for $name $(<$($generic),+>)? {
1182            #[inline]
1183            fn borrow(&self) -> &$super_name {
1184                $crate::object::Cast::upcast_ref(self)
1185            }
1186        }
1187    };
1188
1189    (@munch_impls $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1190        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1191        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1192    };
1193
1194    // If there is no parent class, i.e. only glib::Object
1195    (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, ) => {
1196        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, );
1197        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1198            type Parent = $crate::object::Object;
1199        }
1200    };
1201
1202    // If there is only one parent class
1203    (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path) => {
1204        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1205        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1206            type Parent = $super_name;
1207        }
1208    };
1209
1210    // If there is more than one parent class
1211    (@munch_first_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $super_name:path, $($implements:tt)*) => {
1212        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $super_name);
1213        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ParentClassIs for $name $(<$($generic),+>)? {
1214            type Parent = $super_name;
1215        }
1216        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1217    };
1218
1219    // This case is only for glib::Object itself below. All other cases have glib::Object in its
1220    // parent class list
1221    (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty, @type_ $get_type_expr:expr) => {
1222        $crate::glib_object_wrapper!(
1223            @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1224            @type_ $get_type_expr);
1225
1226        #[doc(hidden)]
1227        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1228    };
1229
1230    (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty,
1231     @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1232        $crate::glib_object_wrapper!(
1233            @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, @ffi_class std::os::raw::c_void,
1234            @type_ $get_type_expr, @extends [$($extends)*], @implements [$($implements)*]
1235        );
1236    };
1237
1238    (@object [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $parent_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty,
1239     @type_ $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1240        $crate::glib_object_wrapper!(
1241            @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $parent_type, $ffi_name, $ffi_class_name,
1242            @type_ $get_type_expr
1243        );
1244
1245        $crate::glib_object_wrapper!(@munch_first_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($extends)*);
1246
1247        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($implements)*);
1248
1249        #[doc(hidden)]
1250        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1251            #[inline]
1252            fn as_ref(&self) -> &$crate::object::Object {
1253                $crate::object::Cast::upcast_ref(self)
1254            }
1255        }
1256
1257        #[doc(hidden)]
1258        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1259            #[inline]
1260            fn borrow(&self) -> &$crate::object::Object {
1261                $crate::object::Cast::upcast_ref(self)
1262            }
1263        }
1264
1265        #[doc(hidden)]
1266        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1267            #[inline]
1268            fn from(v: $name $(<$($generic),+>)?) -> Self {
1269                <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1270            }
1271        }
1272
1273        #[doc(hidden)]
1274        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1275
1276        #[doc(hidden)]
1277        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsClass for $name $(<$($generic),+>)? { }
1278    };
1279
1280    // FIXME: Workaround for `glib::Object` not being `Send+Sync` but subclasses of it being both
1281    // if the impl struct is.
1282    (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1283     @extends [], @implements [$($implements:tt)*]) => {
1284        $crate::glib_object_wrapper!(
1285            @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1286            $subclass, (),
1287            <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1288            @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1289            @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1290            @extends [], @implements [$($implements)*]
1291        );
1292
1293        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1294            type Subclass = $subclass;
1295        }
1296    };
1297
1298    (@object_subclass [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $subclass:ty,
1299     @extends [$($extends:tt)+], @implements [$($implements:tt)*]) => {
1300        $crate::glib_object_wrapper!(
1301            @object [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?,
1302            $subclass, <$subclass as $crate::subclass::types::ObjectSubclass>::ParentType,
1303            <$subclass as $crate::subclass::types::ObjectSubclass>::Instance,
1304            @ffi_class <$subclass as $crate::subclass::types::ObjectSubclass>::Class,
1305            @type_ $crate::translate::IntoGlib::into_glib(<$subclass as $crate::subclass::types::ObjectSubclassType>::type_()),
1306            @extends [$($extends)*], @implements [$($implements)*]
1307        );
1308
1309        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::ObjectSubclassIs for $name $(<$($generic),+>)? {
1310            type Subclass = $subclass;
1311        }
1312    };
1313
1314    (@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty,
1315     @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1316        $crate::glib_object_wrapper!(
1317            @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, $ffi_name, @ffi_class std::os::raw::c_void,
1318            @type_ $get_type_expr, @requires [$($requires)*]
1319        );
1320    };
1321
1322    (@object_interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $iface:ty,
1323    @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1324       $crate::glib_object_wrapper!(
1325           @interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $iface, <$iface as $crate::subclass::interface::ObjectInterface>::Instance,
1326           @ffi_class  <$iface as $crate::subclass::interface::ObjectInterface>::Interface,
1327           @type_ $get_type_expr, @requires [$($requires)*]
1328       );
1329   };
1330
1331    (@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty,
1332     @type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1333        $crate::glib_object_wrapper!(
1334            @generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $impl_type, (), $ffi_name, $ffi_class_name,
1335            @type_ $get_type_expr
1336        );
1337        $crate::glib_object_wrapper!(@munch_impls $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $($requires)*);
1338
1339        #[doc(hidden)]
1340        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? AsRef<$crate::object::Object> for $name $(<$($generic),+>)? {
1341            #[inline]
1342            fn as_ref(&self) -> &$crate::object::Object {
1343                $crate::object::Cast::upcast_ref(self)
1344            }
1345        }
1346
1347        #[doc(hidden)]
1348        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::borrow::Borrow<$crate::object::Object> for $name $(<$($generic),+>)? {
1349            #[inline]
1350            fn borrow(&self) -> &$crate::object::Object {
1351                $crate::object::Cast::upcast_ref(self)
1352            }
1353        }
1354
1355        #[doc(hidden)]
1356        impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? From<$name $(<$($generic),+>)?> for $crate::object::Object {
1357            #[inline]
1358            fn from(v: $name $(<$($generic),+>)?) -> Self {
1359                <$name $(::<$($generic),+>)? as $crate::prelude::Cast>::upcast(v)
1360            }
1361        }
1362
1363        #[doc(hidden)]
1364        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::IsA<$crate::object::Object> for $name $(<$($generic),+>)? { }
1365
1366        #[doc(hidden)]
1367        unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::object::IsInterface for $name $(<$($generic),+>)? { }
1368    };
1369}
1370
1371glib_object_wrapper!(@object
1372    [doc = "The base class in the object hierarchy."]
1373    pub Object, *mut std::os::raw::c_void, (), gobject_ffi::GObject, @ffi_class gobject_ffi::GObjectClass, @type_ gobject_ffi::g_object_get_type()
1374);
1375pub type ObjectClass = Class<Object>;
1376
1377impl Object {
1378    pub const NONE: Option<&'static Object> = None;
1379
1380    // rustdoc-stripper-ignore-next
1381    /// Create a new instance of an object with the default property values.
1382    ///
1383    /// # Panics
1384    ///
1385    /// This panics if the object is not instantiable.
1386    #[track_caller]
1387    #[allow(clippy::new_ret_no_self)]
1388    pub fn new<T: IsA<Object> + IsClass>() -> T {
1389        let object = Object::with_type(T::static_type());
1390        unsafe { object.unsafe_cast() }
1391    }
1392
1393    // rustdoc-stripper-ignore-next
1394    /// Create a new instance of an object with the default property values.
1395    ///
1396    /// # Panics
1397    ///
1398    /// This panics if the object is not instantiable.
1399    #[track_caller]
1400    pub fn with_type(type_: Type) -> Object {
1401        Object::with_mut_values(type_, &mut [])
1402    }
1403
1404    // rustdoc-stripper-ignore-next
1405    /// Create a new instance of an object of the given type with the given properties as mutable
1406    /// values.
1407    ///
1408    /// # Panics
1409    ///
1410    /// This panics if the object is not instantiable, doesn't have all the given properties or
1411    /// property values of the wrong type are provided.
1412    #[track_caller]
1413    pub fn with_mut_values(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1414        #[cfg(feature = "gio")]
1415        unsafe {
1416            let iface_type = from_glib(gio_sys::g_initable_get_type());
1417            if type_.is_a(iface_type) {
1418                panic!("Can't instantiate type '{type_}' implementing `gio::Initable`. Use `gio::Initable::new()`");
1419            }
1420            let iface_type = from_glib(gio_sys::g_async_initable_get_type());
1421            if type_.is_a(iface_type) {
1422                panic!("Can't instantiate type '{type_}' implementing `gio::AsyncInitable`. Use `gio::AsyncInitable::new()`");
1423            }
1424        }
1425
1426        unsafe { Object::new_internal(type_, properties) }
1427    }
1428
1429    // rustdoc-stripper-ignore-next
1430    /// Create a new instance of an object of the given type with the given properties.
1431    ///
1432    /// # Panics
1433    ///
1434    /// This panics if the object is not instantiable, doesn't have all the given properties or
1435    /// property values of the wrong type are provided.
1436    ///
1437    /// Unlike the other constructors this does not panic if the object is implementing
1438    /// `gio::Initable` or `gio::AsyncInitable` and it might be unsafe to use the returned object
1439    /// without using the API of those interfaces first.
1440    #[track_caller]
1441    pub unsafe fn new_internal(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1442        if !type_.is_a(Object::static_type()) {
1443            panic!("Can't instantiate non-GObject type '{type_}'");
1444        }
1445
1446        if gobject_ffi::g_type_test_flags(
1447            type_.into_glib(),
1448            gobject_ffi::G_TYPE_FLAG_INSTANTIATABLE,
1449        ) == ffi::GFALSE
1450        {
1451            panic!("Can't instantiate type '{type_}'");
1452        }
1453
1454        if gobject_ffi::g_type_test_flags(type_.into_glib(), gobject_ffi::G_TYPE_FLAG_ABSTRACT)
1455            != ffi::GFALSE
1456        {
1457            panic!("Can't instantiate abstract type '{type_}'");
1458        }
1459
1460        let mut property_names = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1461        let mut property_values = smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1462
1463        if !properties.is_empty() {
1464            let klass = ObjectClass::from_type(type_)
1465                .unwrap_or_else(|| panic!("Can't retrieve class for type '{type_}'"));
1466
1467            for (idx, (name, value)) in properties.iter_mut().enumerate() {
1468                let pspec = klass
1469                    .find_property(name)
1470                    .unwrap_or_else(|| panic!("Can't find property '{name}' for type '{type_}'"));
1471
1472                if (pspec.flags().contains(crate::ParamFlags::CONSTRUCT)
1473                    || pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
1474                    && property_names[0..idx]
1475                        .iter()
1476                        .any(|other_name| pspec.name().as_ptr() == *other_name)
1477                {
1478                    panic!("Can't set construct property '{name}' for type '{type_}' twice");
1479                }
1480
1481                // FIXME: With GLib 2.74 and GParamSpecClass::value_is_valid() it is possible to
1482                // not require mutable values here except for when LAX_VALIDATION is provided and a
1483                // change is needed, or a GObject value needs it's GType changed.
1484                validate_property_type(type_, true, &pspec, value);
1485
1486                property_names.push(pspec.name().as_ptr());
1487                property_values.push(*value.to_glib_none().0);
1488            }
1489        }
1490
1491        let ptr = gobject_ffi::g_object_new_with_properties(
1492            type_.into_glib(),
1493            properties.len() as u32,
1494            mut_override(property_names.as_ptr() as *const *const _),
1495            property_values.as_ptr(),
1496        );
1497
1498        if ptr.is_null() {
1499            panic!("Can't instantiate object for type '{type_}'");
1500        } else if type_.is_a(InitiallyUnowned::static_type()) {
1501            // Attention: This takes ownership of the floating reference
1502            from_glib_none(ptr)
1503        } else {
1504            from_glib_full(ptr)
1505        }
1506    }
1507
1508    // rustdoc-stripper-ignore-next
1509    /// Create a new object builder for a specific type.
1510    pub fn builder<'a, O: IsA<Object> + IsClass>() -> ObjectBuilder<'a, O> {
1511        ObjectBuilder::new(O::static_type())
1512    }
1513
1514    // rustdoc-stripper-ignore-next
1515    /// Create a new object builder for a specific type.
1516    pub fn builder_with_type<'a>(type_: Type) -> ObjectBuilder<'a, Object> {
1517        ObjectBuilder::new(type_)
1518    }
1519}
1520
1521#[must_use = "builder doesn't do anything unless built"]
1522pub struct ObjectBuilder<'a, O> {
1523    type_: Type,
1524    properties: smallvec::SmallVec<[(&'a str, Value); 16]>,
1525    phantom: PhantomData<O>,
1526}
1527
1528impl<'a, O: IsA<Object> + IsClass> ObjectBuilder<'a, O> {
1529    #[inline]
1530    fn new(type_: Type) -> Self {
1531        ObjectBuilder {
1532            type_,
1533            properties: smallvec::SmallVec::new(),
1534            phantom: PhantomData,
1535        }
1536    }
1537
1538    // rustdoc-stripper-ignore-next
1539    /// Gets the type of this builder.
1540    #[inline]
1541    pub fn type_(&self) -> Type {
1542        self.type_
1543    }
1544
1545    // rustdoc-stripper-ignore-next
1546    /// Sets property `name` to the given value `value`.
1547    ///
1548    /// Overrides any default or previously defined value for `name`.
1549    pub fn property(self, name: &'a str, value: impl Into<Value>) -> Self {
1550        let ObjectBuilder {
1551            type_,
1552            mut properties,
1553            ..
1554        } = self;
1555        properties.push((name, value.into()));
1556
1557        ObjectBuilder {
1558            type_,
1559            properties,
1560            phantom: PhantomData,
1561        }
1562    }
1563
1564    // rustdoc-stripper-ignore-next
1565    /// Sets property `name` to the given inner value if the `predicate` evaluates to `true`.
1566    ///
1567    /// This has no effect if the `predicate` evaluates to `false`,
1568    /// i.e. default or previous value for `name` is kept.
1569    #[inline]
1570    pub fn property_if(self, name: &'a str, value: impl Into<Value>, predicate: bool) -> Self {
1571        if predicate {
1572            self.property(name, value)
1573        } else {
1574            self
1575        }
1576    }
1577
1578    // rustdoc-stripper-ignore-next
1579    /// Sets property `name` to the given inner value if `value` is `Some`.
1580    ///
1581    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1582    #[inline]
1583    pub fn property_if_some(self, name: &'a str, value: Option<impl Into<Value>>) -> Self {
1584        if let Some(value) = value {
1585            self.property(name, value)
1586        } else {
1587            self
1588        }
1589    }
1590
1591    // rustdoc-stripper-ignore-next
1592    /// Sets property `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
1593    ///
1594    /// Overrides any default or previously defined value for `name`.
1595    #[inline]
1596    pub fn property_from_iter<V: ValueType + Into<Value> + FromIterator<Value>>(
1597        self,
1598        name: &'a str,
1599        iter: impl IntoIterator<Item = impl Into<Value>>,
1600    ) -> Self {
1601        let iter = iter.into_iter().map(|item| item.into());
1602        self.property(name, V::from_iter(iter))
1603    }
1604
1605    // rustdoc-stripper-ignore-next
1606    /// Sets property `name` using the given `ValueType` `V` built from `iter`'s Item`s,
1607    /// if `iter` is not empty.
1608    ///
1609    /// This has no effect if `iter` is empty, i.e. previous property value for `name` is unchanged.
1610    #[inline]
1611    pub fn property_if_not_empty<V: ValueType + Into<Value> + FromIterator<Value>>(
1612        self,
1613        name: &'a str,
1614        iter: impl IntoIterator<Item = impl Into<Value>>,
1615    ) -> Self {
1616        let mut iter = iter.into_iter().peekable();
1617        if iter.peek().is_some() {
1618            let iter = iter.map(|item| item.into());
1619            self.property(name, V::from_iter(iter))
1620        } else {
1621            self
1622        }
1623    }
1624
1625    // rustdoc-stripper-ignore-next
1626    /// Build the object with the provided properties.
1627    ///
1628    /// # Panics
1629    ///
1630    /// This panics if the object is not instantiable, doesn't have all the given properties or
1631    /// property values of the wrong type are provided.
1632    #[track_caller]
1633    #[inline]
1634    pub fn build(mut self) -> O {
1635        let object = Object::with_mut_values(self.type_, &mut self.properties);
1636        unsafe { object.unsafe_cast::<O>() }
1637    }
1638}
1639
1640#[must_use = "if unused the property notifications will immediately be thawed"]
1641pub struct PropertyNotificationFreezeGuard(ObjectRef);
1642
1643impl Drop for PropertyNotificationFreezeGuard {
1644    #[doc(alias = "g_object_thaw_notify")]
1645    #[inline]
1646    fn drop(&mut self) {
1647        unsafe { gobject_ffi::g_object_thaw_notify(self.0.to_glib_none().0) }
1648    }
1649}
1650
1651pub trait ObjectExt: ObjectType {
1652    // rustdoc-stripper-ignore-next
1653    /// Returns `true` if the object is an instance of (can be cast to) `T`.
1654    fn is<T: StaticType>(&self) -> bool;
1655
1656    // rustdoc-stripper-ignore-next
1657    /// Returns the type of the object.
1658    #[doc(alias = "get_type")]
1659    fn type_(&self) -> Type;
1660
1661    // rustdoc-stripper-ignore-next
1662    /// Returns the [`ObjectClass`] of the object.
1663    ///
1664    /// This is equivalent to calling `obj.class().upcast_ref::<ObjectClass>()`.
1665    #[doc(alias = "get_object_class")]
1666    fn object_class(&self) -> &ObjectClass;
1667
1668    /// Returns the class of the object.
1669    #[doc(alias = "get_class")]
1670    fn class(&self) -> &Class<Self>
1671    where
1672        Self: IsClass;
1673
1674    // rustdoc-stripper-ignore-next
1675    /// Returns the class of the object in the given type `T`.
1676    ///
1677    /// `None` is returned if the object is not a subclass of `T`.
1678    #[doc(alias = "get_class_of")]
1679    fn class_of<T: IsClass>(&self) -> Option<&Class<T>>;
1680
1681    // rustdoc-stripper-ignore-next
1682    /// Returns the interface `T` of the object.
1683    ///
1684    /// `None` is returned if the object does not implement the interface `T`.
1685    #[doc(alias = "get_interface")]
1686    fn interface<T: IsInterface>(&self) -> Option<InterfaceRef<T>>;
1687
1688    // rustdoc-stripper-ignore-next
1689    /// Sets the property `property_name` of the object to value `value`.
1690    ///
1691    /// # Panics
1692    ///
1693    /// If the property does not exist, if the type of the property is different than
1694    /// the provided value, or if the property is not writable.
1695    #[doc(alias = "g_object_set_property")]
1696    fn set_property(&self, property_name: &str, value: impl Into<Value>);
1697
1698    // rustdoc-stripper-ignore-next
1699    /// Sets the property `property_name` of the object to value `value`.
1700    ///
1701    /// # Panics
1702    ///
1703    /// If the property does not exist, the type of the property is different than the
1704    /// provided value, or if the property is not writable.
1705    #[doc(alias = "g_object_set_property")]
1706    fn set_property_from_value(&self, property_name: &str, value: &Value);
1707
1708    // rustdoc-stripper-ignore-next
1709    /// Sets multiple properties of the object at once.
1710    ///
1711    /// # Panics
1712    ///
1713    /// This does not set any properties if one or more properties don't exist, values of the wrong
1714    /// type are provided, or if any of the properties is not writable.
1715    #[doc(alias = "g_object_set")]
1716    fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]);
1717
1718    // rustdoc-stripper-ignore-next
1719    /// Sets multiple properties of the object at once.
1720    ///
1721    /// # Panics
1722    ///
1723    /// This does not set any properties if one or more properties don't exist, values of the wrong
1724    /// type are provided, or if any of the properties is not writable.
1725    #[doc(alias = "g_object_set")]
1726    fn set_properties_from_value(&self, property_values: &[(&str, Value)]);
1727
1728    // rustdoc-stripper-ignore-next
1729    /// Gets the property `property_name` of the object and cast it to the type V.
1730    ///
1731    /// # Panics
1732    ///
1733    /// If the property doesn't exist or is not readable or of a different type than V.
1734    #[doc(alias = "get_property")]
1735    #[doc(alias = "g_object_get_property")]
1736    fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V;
1737
1738    // rustdoc-stripper-ignore-next
1739    /// Gets the property `property_name` of the object.
1740    ///
1741    /// # Panics
1742    ///
1743    /// If the property does not exist or is not writable.
1744    #[doc(alias = "get_property")]
1745    #[doc(alias = "g_object_get_property")]
1746    fn property_value(&self, property_name: &str) -> Value;
1747
1748    // rustdoc-stripper-ignore-next
1749    /// Check if the object has a property `property_name` of the given `type_`.
1750    ///
1751    /// If no type is provided then only the existence of the property is checked.
1752    fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool;
1753
1754    // rustdoc-stripper-ignore-next
1755    /// Get the type of the property `property_name` of this object.
1756    ///
1757    /// This returns `None` if the property does not exist.
1758    #[doc(alias = "get_property_type")]
1759    fn property_type(&self, property_name: &str) -> Option<Type>;
1760
1761    // rustdoc-stripper-ignore-next
1762    /// Get the [`ParamSpec`](crate::ParamSpec) of the property `property_name` of this object.
1763    fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec>;
1764
1765    // rustdoc-stripper-ignore-next
1766    /// Return all [`ParamSpec`](crate::ParamSpec) of the properties of this object.
1767    fn list_properties(&self) -> PtrSlice<crate::ParamSpec>;
1768
1769    // rustdoc-stripper-ignore-next
1770    /// Freeze all property notifications until the return guard object is dropped.
1771    ///
1772    /// This prevents the `notify` signal for all properties of this object to be emitted.
1773    #[doc(alias = "g_object_freeze_notify")]
1774    fn freeze_notify(&self) -> PropertyNotificationFreezeGuard;
1775
1776    // rustdoc-stripper-ignore-next
1777    /// Set arbitrary data on this object with the given `key`.
1778    ///
1779    /// # Safety
1780    ///
1781    /// This function doesn't store type information
1782    unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD);
1783
1784    // rustdoc-stripper-ignore-next
1785    /// Return previously set arbitrary data of this object with the given `key`.
1786    ///
1787    /// # Safety
1788    ///
1789    /// The returned pointer can become invalid by a call to
1790    /// `set_qdata`, `steal_qdata`, `set_data` or `steal_data`.
1791    ///
1792    /// The caller is responsible for ensuring the returned value is of a suitable type
1793    #[doc(alias = "get_qdata")]
1794    unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>>;
1795
1796    // rustdoc-stripper-ignore-next
1797    /// Retrieve previously set arbitrary data of this object with the given `key`.
1798    ///
1799    /// The data is not set on the object anymore afterwards.
1800    ///
1801    /// # Safety
1802    ///
1803    /// The caller is responsible for ensuring the returned value is of a suitable type
1804    unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>;
1805
1806    // rustdoc-stripper-ignore-next
1807    /// Set arbitrary data on this object with the given `key`.
1808    ///
1809    /// # Safety
1810    ///
1811    /// This function doesn't store type information
1812    unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD);
1813
1814    // rustdoc-stripper-ignore-next
1815    /// Return previously set arbitrary data of this object with the given `key`.
1816    ///
1817    /// # Safety
1818    ///
1819    /// The returned pointer can become invalid by a call to
1820    /// `set_qdata`, `steal_qdata`, `set_data` or `steal_data`.
1821    ///
1822    /// The caller is responsible for ensuring the returned value is of a suitable type
1823    #[doc(alias = "get_data")]
1824    unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>>;
1825
1826    // rustdoc-stripper-ignore-next
1827    /// Retrieve previously set arbitrary data of this object with the given `key`.
1828    ///
1829    /// The data is not set on the object anymore afterwards.
1830    ///
1831    /// # Safety
1832    ///
1833    /// The caller is responsible for ensuring the returned value is of a suitable type
1834    unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD>;
1835
1836    // rustdoc-stripper-ignore-next
1837    /// Block a given signal handler.
1838    ///
1839    /// It will not be called again during signal emissions until it is unblocked.
1840    #[doc(alias = "g_signal_handler_block")]
1841    fn block_signal(&self, handler_id: &SignalHandlerId);
1842
1843    // rustdoc-stripper-ignore-next
1844    /// Unblock a given signal handler.
1845    #[doc(alias = "g_signal_handler_unblock")]
1846    fn unblock_signal(&self, handler_id: &SignalHandlerId);
1847
1848    // rustdoc-stripper-ignore-next
1849    /// Stop emission of the currently emitted signal.
1850    #[doc(alias = "g_signal_stop_emission")]
1851    fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>);
1852
1853    // rustdoc-stripper-ignore-next
1854    /// Stop emission of the currently emitted signal by the (possibly detailed) signal name.
1855    #[doc(alias = "g_signal_stop_emission_by_name")]
1856    fn stop_signal_emission_by_name(&self, signal_name: &str);
1857
1858    // rustdoc-stripper-ignore-next
1859    /// Connect to the signal `signal_name` on this object.
1860    ///
1861    /// If `after` is set to `true` then the callback will be called after the default class
1862    /// handler of the signal is emitted, otherwise before.
1863    ///
1864    /// # Panics
1865    ///
1866    /// If the signal does not exist.
1867    fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1868    where
1869        F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1870
1871    // rustdoc-stripper-ignore-next
1872    /// Connect to the signal `signal_id` on this object.
1873    ///
1874    /// If `after` is set to `true` then the callback will be called after the default class
1875    /// handler of the signal is emitted, otherwise before.
1876    ///
1877    /// Same as [`Self::connect`] but takes a `SignalId` instead of a signal name.
1878    ///
1879    /// # Panics
1880    ///
1881    /// If the signal does not exist.
1882    fn connect_id<F>(
1883        &self,
1884        signal_id: SignalId,
1885        details: Option<Quark>,
1886        after: bool,
1887        callback: F,
1888    ) -> SignalHandlerId
1889    where
1890        F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
1891
1892    // rustdoc-stripper-ignore-next
1893    /// Connect to the signal `signal_name` on this object.
1894    ///
1895    /// If `after` is set to `true` then the callback will be called after the default class
1896    /// handler of the signal is emitted, otherwise before.
1897    ///
1898    /// Same as [`Self::connect`] but takes a non-`Send+Sync` closure. If the signal is emitted from a
1899    /// different thread than it was connected to then the signal emission will panic.
1900    ///
1901    /// # Panics
1902    ///
1903    /// If the signal does not exist.
1904    fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
1905    where
1906        F: Fn(&[Value]) -> Option<Value> + 'static;
1907
1908    // rustdoc-stripper-ignore-next
1909    /// Connect to the signal `signal_id` on this object.
1910    ///
1911    /// If `after` is set to `true` then the callback will be called after the default class
1912    /// handler of the signal is emitted, otherwise before.
1913    ///
1914    /// Same as [`Self::connect_id`] but takes a non-`Send+Sync` closure. If the signal is emitted from a
1915    /// different thread than it was connected to then the signal emission will panic.
1916    ///
1917    /// # Panics
1918    ///
1919    /// This panics if the signal does not exist.
1920    fn connect_local_id<F>(
1921        &self,
1922        signal_id: SignalId,
1923        details: Option<Quark>,
1924        after: bool,
1925        callback: F,
1926    ) -> SignalHandlerId
1927    where
1928        F: Fn(&[Value]) -> Option<Value> + 'static;
1929
1930    // rustdoc-stripper-ignore-next
1931    /// Connect to the signal `signal_name` on this object.
1932    ///
1933    /// If `after` is set to `true` then the callback will be called after the default class
1934    /// handler of the signal is emitted, otherwise before.
1935    ///
1936    /// Same as [`Self::connect`] but takes a non-`Send+Sync` and non-`'static'` closure. No runtime checks
1937    /// are performed for ensuring that the closure is called correctly.
1938    ///
1939    /// # Safety
1940    ///
1941    /// The provided closure must be valid until the signal handler is disconnected, and it must
1942    /// be allowed to call the closure from the threads the signal is emitted from.
1943    ///
1944    /// # Panics
1945    ///
1946    /// If the signal does not exist.
1947    unsafe fn connect_unsafe<F>(
1948        &self,
1949        signal_name: &str,
1950        after: bool,
1951        callback: F,
1952    ) -> SignalHandlerId
1953    where
1954        F: Fn(&[Value]) -> Option<Value>;
1955
1956    // rustdoc-stripper-ignore-next
1957    /// Connect to the signal `signal_id` on this object.
1958    ///
1959    /// If `after` is set to `true` then the callback will be called after the default class
1960    /// handler of the signal is emitted, otherwise before.
1961    ///
1962    ///
1963    /// Same as [`Self::connect_id`] but takes a non-`Send+Sync` and non-`'static'` closure. No runtime checks
1964    /// are performed for ensuring that the closure is called correctly.
1965    ///
1966    /// # Safety
1967    ///
1968    /// The provided closure must be valid until the signal handler is disconnected, and it must
1969    /// be allowed to call the closure from the threads the signal is emitted from.
1970    ///
1971    /// # Panics
1972    ///
1973    /// If the signal does not exist.
1974    unsafe fn connect_unsafe_id<F>(
1975        &self,
1976        signal_id: SignalId,
1977        details: Option<Quark>,
1978        after: bool,
1979        callback: F,
1980    ) -> SignalHandlerId
1981    where
1982        F: Fn(&[Value]) -> Option<Value>;
1983
1984    // rustdoc-stripper-ignore-next
1985    /// Connect a closure to the signal `signal_name` on this object.
1986    ///
1987    /// If `after` is set to `true` then the callback will be called after the default class
1988    /// handler of the signal is emitted, otherwise before.
1989    ///
1990    /// This panics if the signal does not exist.
1991    ///
1992    /// A recurring case is connecting a handler which will be automatically disconnected
1993    /// when an object it refers to is destroyed, as it happens with `g_signal_connect_object`
1994    /// in C. This can be achieved with a closure that watches an object: see the documentation
1995    /// of the [`closure!`](crate::closure!) macro for more details.
1996    ///
1997    /// Same as [`Self::connect`] but takes a [`Closure`] instead of a `Fn`.
1998    #[doc(alias = "g_signal_connect_closure")]
1999    #[doc(alias = "g_signal_connect_object")]
2000    fn connect_closure(
2001        &self,
2002        signal_name: &str,
2003        after: bool,
2004        closure: RustClosure,
2005    ) -> SignalHandlerId;
2006
2007    // rustdoc-stripper-ignore-next
2008    /// Connect a closure to the signal `signal_id` on this object.
2009    ///
2010    /// If `after` is set to `true` then the callback will be called after the default class
2011    /// handler of the signal is emitted, otherwise before.
2012    ///
2013    /// This panics if the signal does not exist.
2014    ///
2015    /// Same as [`Self::connect_closure`] but takes a
2016    /// [`SignalId`] instead of a signal name.
2017    #[doc(alias = "g_signal_connect_closure_by_id")]
2018    fn connect_closure_id(
2019        &self,
2020        signal_id: SignalId,
2021        details: Option<Quark>,
2022        after: bool,
2023        closure: RustClosure,
2024    ) -> SignalHandlerId;
2025
2026    // rustdoc-stripper-ignore-next
2027    /// Limits the lifetime of `closure` to the lifetime of the object. When
2028    /// the object's reference count drops to zero, the closure will be
2029    /// invalidated. An invalidated closure will ignore any calls to
2030    /// [`invoke_with_values`](crate::closure::Closure::invoke_with_values), or
2031    /// [`invoke`](crate::closure::RustClosure::invoke) when using Rust closures.
2032    #[doc(alias = "g_object_watch_closure")]
2033    fn watch_closure(&self, closure: &impl AsRef<Closure>);
2034
2035    // rustdoc-stripper-ignore-next
2036    /// Emit signal by signal id.
2037    ///
2038    /// If the signal has a return value then this is returned here.
2039    ///
2040    /// # Panics
2041    ///
2042    /// If the wrong number of arguments is provided, or arguments of the wrong types
2043    /// were provided.
2044    #[doc(alias = "g_signal_emitv")]
2045    fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R;
2046
2047    // rustdoc-stripper-ignore-next
2048    /// Same as [`Self::emit`] but takes `Value` for the arguments.
2049    fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value>;
2050
2051    // rustdoc-stripper-ignore-next
2052    /// Emit signal by its name.
2053    ///
2054    /// If the signal has a return value then this is returned here.
2055    ///
2056    /// # Panics
2057    ///
2058    /// If the signal does not exist, the wrong number of arguments is provided, or
2059    /// arguments of the wrong types were provided.
2060    #[doc(alias = "g_signal_emit_by_name")]
2061    fn emit_by_name<R: TryFromClosureReturnValue>(
2062        &self,
2063        signal_name: &str,
2064        args: &[&dyn ToValue],
2065    ) -> R;
2066
2067    // rustdoc-stripper-ignore-next
2068    /// Emit signal by its name.
2069    ///
2070    /// If the signal has a return value then this is returned here.
2071    ///
2072    /// # Panics
2073    ///
2074    /// If the signal does not exist, the wrong number of arguments is provided, or
2075    /// arguments of the wrong types were provided.
2076    fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value>;
2077
2078    // rustdoc-stripper-ignore-next
2079    /// Emit signal by its name with details.
2080    ///
2081    /// If the signal has a return value then this is returned here.
2082    ///
2083    /// # Panics
2084    ///
2085    /// If the wrong number of arguments is provided, or arguments of the wrong types
2086    /// were provided.
2087    fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2088        &self,
2089        signal_name: &str,
2090        details: Quark,
2091        args: &[&dyn ToValue],
2092    ) -> R;
2093
2094    // rustdoc-stripper-ignore-next
2095    /// Emit signal by its name with details.
2096    ///
2097    /// If the signal has a return value then this is returned here.
2098    ///
2099    /// # Panics
2100    ///
2101    /// If the wrong number of arguments is provided, or arguments of the wrong types
2102    /// were provided.
2103    fn emit_by_name_with_details_and_values(
2104        &self,
2105        signal_name: &str,
2106        details: Quark,
2107        args: &[Value],
2108    ) -> Option<Value>;
2109
2110    // rustdoc-stripper-ignore-next
2111    /// Emit signal by signal id with details.
2112    ///
2113    /// If the signal has a return value then this is returned here.
2114    ///
2115    /// # Panics
2116    ///
2117    /// If the wrong number of arguments is provided, or arguments of the wrong types
2118    /// were provided.
2119    fn emit_with_details<R: TryFromClosureReturnValue>(
2120        &self,
2121        signal_id: SignalId,
2122        details: Quark,
2123        args: &[&dyn ToValue],
2124    ) -> R;
2125
2126    // rustdoc-stripper-ignore-next
2127    /// Emit signal by signal id with details.
2128    ///
2129    /// If the signal has a return value then this is returned here.
2130    ///
2131    /// # Panics
2132    ///
2133    /// If the wrong number of arguments is provided, or arguments of the wrong types
2134    /// were provided.
2135    fn emit_with_details_and_values(
2136        &self,
2137        signal_id: SignalId,
2138        details: Quark,
2139        args: &[Value],
2140    ) -> Option<Value>;
2141
2142    // rustdoc-stripper-ignore-next
2143    /// Disconnect a previously connected signal handler.
2144    #[doc(alias = "g_signal_handler_disconnect")]
2145    fn disconnect(&self, handler_id: SignalHandlerId);
2146
2147    // rustdoc-stripper-ignore-next
2148    /// Connect to the `notify` signal of the object.
2149    ///
2150    /// This is emitted whenever a property is changed. If `name` is provided then the signal
2151    /// handler is only called for this specific property.
2152    fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
2153        &self,
2154        name: Option<&str>,
2155        f: F,
2156    ) -> SignalHandlerId;
2157
2158    // rustdoc-stripper-ignore-next
2159    /// Connect to the `notify` signal of the object.
2160    ///
2161    /// This is emitted whenever a property is changed. If `name` is provided then the signal
2162    /// handler is only called for this specific property.
2163    ///
2164    /// This is like `connect_notify` but doesn't require a `Send+Sync` closure. Signal emission
2165    /// will panic if the signal is emitted from the wrong thread.
2166    fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
2167        &self,
2168        name: Option<&str>,
2169        f: F,
2170    ) -> SignalHandlerId;
2171
2172    // rustdoc-stripper-ignore-next
2173    /// Connect to the `notify` signal of the object.
2174    ///
2175    /// This is emitted whenever a property is changed. If `name` is provided then the signal
2176    /// handler is only called for this specific property.
2177    ///
2178    /// This is like `connect_notify` but doesn't require a `Send+Sync` or `'static` closure. No
2179    /// runtime checks for wrongly calling the closure are performed.
2180    ///
2181    /// # Safety
2182    ///
2183    /// The provided closure must be valid until the signal handler is disconnected, and it must
2184    /// be allowed to call the closure from the threads the signal is emitted from.
2185    unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
2186        &self,
2187        name: Option<&str>,
2188        f: F,
2189    ) -> SignalHandlerId;
2190
2191    // rustdoc-stripper-ignore-next
2192    /// Notify that the given property has changed its value.
2193    ///
2194    /// This emits the `notify` signal.
2195    #[doc(alias = "g_object_notify")]
2196    fn notify(&self, property_name: &str);
2197
2198    // rustdoc-stripper-ignore-next
2199    /// Notify that the given property has changed its value.
2200    ///
2201    /// This emits the `notify` signal.
2202    #[doc(alias = "g_object_notify_by_pspec")]
2203    fn notify_by_pspec(&self, pspec: &crate::ParamSpec);
2204
2205    // rustdoc-stripper-ignore-next
2206    /// Downgrade this object to a weak reference.
2207    fn downgrade(&self) -> WeakRef<Self>;
2208
2209    // rustdoc-stripper-ignore-next
2210    /// Add a callback to be notified when the Object is disposed.
2211    #[doc(alias = "g_object_weak_ref")]
2212    #[doc(alias = "connect_drop")]
2213    fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2214
2215    // rustdoc-stripper-ignore-next
2216    /// Add a callback to be notified when the Object is disposed.
2217    ///
2218    /// This is like [`add_weak_ref_notify`][`ObjectExt::add_weak_ref_notify`] but doesn't require the closure to be [`Send`].
2219    /// Object dispose will panic if the object is disposed from the wrong thread.
2220    #[doc(alias = "g_object_weak_ref")]
2221    #[doc(alias = "connect_drop")]
2222    fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<Self>;
2223
2224    // rustdoc-stripper-ignore-next
2225    /// Bind property `source_property` on this object to the `target_property` on the `target` object.
2226    ///
2227    /// This allows keeping the properties of both objects in sync.
2228    ///
2229    /// The binding can be unidirectional or bidirectional and optionally it is possible to
2230    /// transform the property values before they're passed to the other object.
2231    fn bind_property<'a, 'f, 't, O: ObjectType>(
2232        &'a self,
2233        source_property: &'a str,
2234        target: &'a O,
2235        target_property: &'a str,
2236    ) -> BindingBuilder<'a, 'f, 't>;
2237
2238    // rustdoc-stripper-ignore-next
2239    /// Returns the strong reference count of this object.
2240    fn ref_count(&self) -> u32;
2241
2242    // rustdoc-stripper-ignore-next
2243    /// Runs the dispose mechanism of the object.
2244    ///
2245    /// This will dispose of any references the object has to other objects, and among other things
2246    /// will disconnect all signal handlers.
2247    ///
2248    /// # Safety
2249    ///
2250    /// Theoretically this is safe to run and afterwards the object is simply in a non-functional
2251    /// state, however many object implementations in C end up with memory safety issues if the
2252    /// object is used after disposal.
2253    #[doc(alias = "g_object_run_dispose")]
2254    unsafe fn run_dispose(&self);
2255}
2256
2257impl<T: ObjectType> ObjectExt for T {
2258    #[inline]
2259    fn is<U: StaticType>(&self) -> bool {
2260        self.type_().is_a(U::static_type())
2261    }
2262
2263    #[inline]
2264    fn type_(&self) -> Type {
2265        self.object_class().type_()
2266    }
2267
2268    #[inline]
2269    fn object_class(&self) -> &ObjectClass {
2270        unsafe {
2271            let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2272            let klass = (*obj).g_type_instance.g_class as *const ObjectClass;
2273            &*klass
2274        }
2275    }
2276
2277    #[inline]
2278    fn class(&self) -> &Class<Self>
2279    where
2280        Self: IsClass,
2281    {
2282        unsafe {
2283            let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2284            let klass = (*obj).g_type_instance.g_class as *const Class<Self>;
2285            &*klass
2286        }
2287    }
2288
2289    #[inline]
2290    fn class_of<U: IsClass>(&self) -> Option<&Class<U>> {
2291        if !self.is::<U>() {
2292            return None;
2293        }
2294
2295        unsafe {
2296            let obj: *mut gobject_ffi::GObject = self.as_object_ref().to_glib_none().0;
2297            let klass = (*obj).g_type_instance.g_class as *const Class<U>;
2298            Some(&*klass)
2299        }
2300    }
2301
2302    #[inline]
2303    fn interface<U: IsInterface>(&self) -> Option<InterfaceRef<U>> {
2304        Interface::from_class(self.object_class())
2305    }
2306
2307    #[track_caller]
2308    fn set_property(&self, property_name: &str, value: impl Into<Value>) {
2309        let pspec = self.find_property(property_name).unwrap_or_else(|| {
2310            panic!(
2311                "property '{property_name}' of type '{}' not found",
2312                self.type_()
2313            )
2314        });
2315
2316        let mut property_value = value.into();
2317        validate_property_type(self.type_(), false, &pspec, &mut property_value);
2318        unsafe {
2319            gobject_ffi::g_object_set_property(
2320                self.as_object_ref().to_glib_none().0,
2321                pspec.name().as_ptr() as *const _,
2322                property_value.to_glib_none().0,
2323            );
2324        }
2325    }
2326
2327    #[track_caller]
2328    fn set_property_from_value(&self, property_name: &str, value: &Value) {
2329        let pspec = match self.find_property(property_name) {
2330            Some(pspec) => pspec,
2331            None => {
2332                panic!(
2333                    "property '{property_name}' of type '{}' not found",
2334                    self.type_()
2335                );
2336            }
2337        };
2338
2339        // FIXME: With GLib 2.74 and GParamSpecClass::value_is_valid() it is possible to
2340        // not require mutable values here except for when LAX_VALIDATION is provided and a
2341        // change is needed, or a GObject value needs it's GType changed.
2342        let mut property_value = value.clone();
2343        validate_property_type(self.type_(), false, &pspec, &mut property_value);
2344        unsafe {
2345            gobject_ffi::g_object_set_property(
2346                self.as_object_ref().to_glib_none().0,
2347                pspec.name().as_ptr() as *const _,
2348                property_value.to_glib_none().0,
2349            );
2350        }
2351    }
2352
2353    #[track_caller]
2354    fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]) {
2355        let params = property_values
2356            .iter()
2357            .map(|&(name, value)| {
2358                let pspec = self.find_property(name).unwrap_or_else(|| {
2359                    panic!("Can't find property '{name}' for type '{}'", self.type_());
2360                });
2361
2362                let mut value = value.to_value();
2363                validate_property_type(self.type_(), false, &pspec, &mut value);
2364                (pspec.name().as_ptr(), value)
2365            })
2366            .collect::<smallvec::SmallVec<[_; 10]>>();
2367
2368        let _guard = self.freeze_notify();
2369        for (name, value) in params {
2370            unsafe {
2371                gobject_ffi::g_object_set_property(
2372                    self.as_object_ref().to_glib_none().0,
2373                    name as *const _,
2374                    value.to_glib_none().0,
2375                );
2376            }
2377        }
2378    }
2379
2380    #[track_caller]
2381    fn set_properties_from_value(&self, property_values: &[(&str, Value)]) {
2382        let params = property_values
2383            .iter()
2384            .map(|(name, value)| {
2385                let pspec = self.find_property(name).unwrap_or_else(|| {
2386                    panic!("Can't find property '{name}' for type '{}'", self.type_());
2387                });
2388
2389                let mut value = value.clone();
2390                validate_property_type(self.type_(), false, &pspec, &mut value);
2391                (pspec.name().as_ptr(), value)
2392            })
2393            .collect::<smallvec::SmallVec<[_; 10]>>();
2394
2395        let _guard = self.freeze_notify();
2396        for (name, value) in params {
2397            unsafe {
2398                gobject_ffi::g_object_set_property(
2399                    self.as_object_ref().to_glib_none().0,
2400                    name as *const _,
2401                    value.to_glib_none().0,
2402                );
2403            }
2404        }
2405    }
2406
2407    #[track_caller]
2408    fn property<V: for<'b> FromValue<'b> + 'static>(&self, property_name: &str) -> V {
2409        let prop = self.property_value(property_name);
2410        let v = prop
2411            .get_owned::<V>()
2412            .unwrap_or_else(|e| panic!("Failed to get cast value to a different type {e}"));
2413
2414        v
2415    }
2416
2417    #[track_caller]
2418    fn property_value(&self, property_name: &str) -> Value {
2419        let pspec = self.find_property(property_name).unwrap_or_else(|| {
2420            panic!(
2421                "property '{property_name}' of type '{}' not found",
2422                self.type_()
2423            )
2424        });
2425
2426        if !pspec.flags().contains(crate::ParamFlags::READABLE) {
2427            panic!(
2428                "property '{property_name}' of type '{}' is not readable",
2429                self.type_()
2430            );
2431        }
2432
2433        unsafe {
2434            let mut value = Value::from_type_unchecked(pspec.value_type());
2435            gobject_ffi::g_object_get_property(
2436                self.as_object_ref().to_glib_none().0,
2437                pspec.name().as_ptr() as *const _,
2438                value.to_glib_none_mut().0,
2439            );
2440
2441            // This can't really happen unless something goes wrong inside GObject
2442            if !value.type_().is_valid() {
2443                panic!(
2444                    "Failed to get property value for property '{property_name}' of type '{}'",
2445                    self.type_()
2446                )
2447            }
2448
2449            value
2450        }
2451    }
2452
2453    fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool {
2454        self.object_class().has_property(property_name, type_)
2455    }
2456
2457    fn property_type(&self, property_name: &str) -> Option<Type> {
2458        self.object_class().property_type(property_name)
2459    }
2460
2461    fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
2462        self.object_class().find_property(property_name)
2463    }
2464
2465    fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
2466        self.object_class().list_properties()
2467    }
2468
2469    #[inline]
2470    fn freeze_notify(&self) -> PropertyNotificationFreezeGuard {
2471        unsafe { gobject_ffi::g_object_freeze_notify(self.as_object_ref().to_glib_none().0) };
2472        PropertyNotificationFreezeGuard(self.as_object_ref().clone())
2473    }
2474
2475    unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD) {
2476        unsafe extern "C" fn drop_value<QD>(ptr: ffi::gpointer) {
2477            debug_assert!(!ptr.is_null());
2478            let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2479            drop(value)
2480        }
2481
2482        let ptr = Box::into_raw(Box::new(value)) as ffi::gpointer;
2483        gobject_ffi::g_object_set_qdata_full(
2484            self.as_object_ref().to_glib_none().0,
2485            key.into_glib(),
2486            ptr,
2487            Some(drop_value::<QD>),
2488        );
2489    }
2490
2491    unsafe fn qdata<QD: 'static>(&self, key: Quark) -> Option<ptr::NonNull<QD>> {
2492        ptr::NonNull::new(gobject_ffi::g_object_get_qdata(
2493            self.as_object_ref().to_glib_none().0,
2494            key.into_glib(),
2495        ) as *mut QD)
2496    }
2497
2498    unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD> {
2499        let ptr = gobject_ffi::g_object_steal_qdata(
2500            self.as_object_ref().to_glib_none().0,
2501            key.into_glib(),
2502        );
2503        if ptr.is_null() {
2504            None
2505        } else {
2506            let value: Box<QD> = Box::from_raw(ptr as *mut QD);
2507            Some(*value)
2508        }
2509    }
2510
2511    unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD) {
2512        self.set_qdata::<QD>(Quark::from_str(key), value)
2513    }
2514
2515    unsafe fn data<QD: 'static>(&self, key: &str) -> Option<ptr::NonNull<QD>> {
2516        self.qdata::<QD>(Quark::from_str(key))
2517    }
2518
2519    unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD> {
2520        self.steal_qdata::<QD>(Quark::from_str(key))
2521    }
2522
2523    fn block_signal(&self, handler_id: &SignalHandlerId) {
2524        unsafe {
2525            gobject_ffi::g_signal_handler_block(
2526                self.as_object_ref().to_glib_none().0,
2527                handler_id.as_raw(),
2528            );
2529        }
2530    }
2531
2532    fn unblock_signal(&self, handler_id: &SignalHandlerId) {
2533        unsafe {
2534            gobject_ffi::g_signal_handler_unblock(
2535                self.as_object_ref().to_glib_none().0,
2536                handler_id.as_raw(),
2537            );
2538        }
2539    }
2540
2541    fn stop_signal_emission(&self, signal_id: SignalId, detail: Option<Quark>) {
2542        unsafe {
2543            gobject_ffi::g_signal_stop_emission(
2544                self.as_object_ref().to_glib_none().0,
2545                signal_id.into_glib(),
2546                detail.into_glib(),
2547            );
2548        }
2549    }
2550
2551    fn stop_signal_emission_by_name(&self, signal_name: &str) {
2552        unsafe {
2553            signal_name.run_with_gstr(|signal_name| {
2554                gobject_ffi::g_signal_stop_emission_by_name(
2555                    self.as_object_ref().to_glib_none().0,
2556                    signal_name.as_ptr(),
2557                )
2558            });
2559        }
2560    }
2561
2562    #[track_caller]
2563    fn connect<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2564    where
2565        F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2566    {
2567        unsafe { self.connect_unsafe(signal_name, after, callback) }
2568    }
2569
2570    #[track_caller]
2571    fn connect_id<F>(
2572        &self,
2573        signal_id: SignalId,
2574        details: Option<Quark>,
2575        after: bool,
2576        callback: F,
2577    ) -> SignalHandlerId
2578    where
2579        F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
2580    {
2581        unsafe { self.connect_unsafe_id(signal_id, details, after, callback) }
2582    }
2583
2584    #[track_caller]
2585    fn connect_local<F>(&self, signal_name: &str, after: bool, callback: F) -> SignalHandlerId
2586    where
2587        F: Fn(&[Value]) -> Option<Value> + 'static,
2588    {
2589        let callback = crate::thread_guard::ThreadGuard::new(callback);
2590
2591        unsafe {
2592            self.connect_unsafe(signal_name, after, move |values| {
2593                (callback.get_ref())(values)
2594            })
2595        }
2596    }
2597
2598    #[track_caller]
2599    fn connect_local_id<F>(
2600        &self,
2601        signal_id: SignalId,
2602        details: Option<Quark>,
2603        after: bool,
2604        callback: F,
2605    ) -> SignalHandlerId
2606    where
2607        F: Fn(&[Value]) -> Option<Value> + 'static,
2608    {
2609        let callback = crate::thread_guard::ThreadGuard::new(callback);
2610
2611        unsafe {
2612            self.connect_unsafe_id(signal_id, details, after, move |values| {
2613                (callback.get_ref())(values)
2614            })
2615        }
2616    }
2617
2618    #[track_caller]
2619    unsafe fn connect_unsafe<F>(
2620        &self,
2621        signal_name: &str,
2622        after: bool,
2623        callback: F,
2624    ) -> SignalHandlerId
2625    where
2626        F: Fn(&[Value]) -> Option<Value>,
2627    {
2628        let type_ = self.type_();
2629        let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2630            .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2631        self.connect_unsafe_id(signal_id, details, after, callback)
2632    }
2633
2634    #[track_caller]
2635    unsafe fn connect_unsafe_id<F>(
2636        &self,
2637        signal_id: SignalId,
2638        details: Option<Quark>,
2639        after: bool,
2640        callback: F,
2641    ) -> SignalHandlerId
2642    where
2643        F: Fn(&[Value]) -> Option<Value>,
2644    {
2645        let signal_query = signal_id.query();
2646        let type_ = self.type_();
2647        let return_type: Type = signal_query.return_type().into();
2648        let signal_name = signal_id.name();
2649        let signal_query_type = signal_query.type_();
2650
2651        let closure = if return_type == Type::UNIT {
2652            Closure::new_unsafe(move |values| {
2653                let ret = callback(values);
2654                if let Some(ret) = ret {
2655                    panic!(
2656                        "Signal '{signal_name}' of type '{type_}' required no return value but got value of type '{}'",
2657                        ret.type_()
2658                    );
2659                }
2660                None
2661            })
2662        } else {
2663            Closure::new_unsafe(move |values| {
2664                let mut ret = callback(values).unwrap_or_else(|| {
2665                    panic!(
2666                        "Signal '{signal_name}' of type '{type_}' required return value of type '{}' but got None",
2667                        return_type.name()
2668                    );
2669                });
2670                let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
2671                    mut_override(ret.to_glib_none().0),
2672                    return_type.into_glib(),
2673                ));
2674
2675                if valid_type {
2676                    return Some(ret);
2677                }
2678
2679                if let Err(got) = coerce_object_type(&mut ret, return_type) {
2680                    panic!(
2681                        "Signal '{signal_name}' of type '{type_}' required return value of type '{return_type}' but got '{got}'",
2682                    );
2683                };
2684                Some(ret)
2685            })
2686        };
2687
2688        assert!(
2689            type_.is_a(signal_query_type),
2690            "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2691        );
2692
2693        let handler = gobject_ffi::g_signal_connect_closure_by_id(
2694            self.as_object_ref().to_glib_none().0,
2695            signal_id.into_glib(),
2696            details.into_glib(),
2697            closure.as_ref().to_glib_none().0,
2698            after.into_glib(),
2699        );
2700
2701        if handler == 0 {
2702            panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2703        }
2704
2705        from_glib(handler)
2706    }
2707
2708    #[track_caller]
2709    fn connect_closure(
2710        &self,
2711        signal_name: &str,
2712        after: bool,
2713        closure: RustClosure,
2714    ) -> SignalHandlerId {
2715        let type_ = self.type_();
2716        let (signal_id, details) = SignalId::parse_name(signal_name, type_, true)
2717            .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2718        self.connect_closure_id(signal_id, details, after, closure)
2719    }
2720
2721    #[track_caller]
2722    fn connect_closure_id(
2723        &self,
2724        signal_id: SignalId,
2725        details: Option<Quark>,
2726        after: bool,
2727        closure: RustClosure,
2728    ) -> SignalHandlerId {
2729        let signal_query = signal_id.query();
2730        let type_ = self.type_();
2731        let signal_name = signal_id.name();
2732
2733        let signal_query_type = signal_query.type_();
2734        assert!(
2735            type_.is_a(signal_query_type),
2736            "Signal '{signal_name}' of type '{type_}' but got type '{signal_query_type}'",
2737        );
2738
2739        unsafe {
2740            let handler = gobject_ffi::g_signal_connect_closure_by_id(
2741                self.as_object_ref().to_glib_none().0,
2742                signal_id.into_glib(),
2743                details.into_glib(),
2744                closure.as_ref().to_glib_none().0,
2745                after.into_glib(),
2746            );
2747
2748            if handler == 0 {
2749                panic!("Failed to connect to signal '{signal_name}' of type '{type_}'",);
2750            }
2751
2752            from_glib(handler)
2753        }
2754    }
2755
2756    #[inline]
2757    fn watch_closure(&self, closure: &impl AsRef<Closure>) {
2758        let closure = closure.as_ref();
2759        unsafe {
2760            gobject_ffi::g_object_watch_closure(
2761                self.as_object_ref().to_glib_none().0,
2762                closure.to_glib_none().0,
2763            );
2764        }
2765    }
2766
2767    #[track_caller]
2768    fn emit<R: TryFromClosureReturnValue>(&self, signal_id: SignalId, args: &[&dyn ToValue]) -> R {
2769        let signal_query = signal_id.query();
2770        unsafe {
2771            let type_ = self.type_();
2772
2773            let self_v = {
2774                let mut v = Value::uninitialized();
2775                gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2776                gobject_ffi::g_value_set_object(
2777                    v.to_glib_none_mut().0,
2778                    self.as_object_ref().to_glib_none().0,
2779                );
2780                v
2781            };
2782
2783            let mut args = Iterator::chain(
2784                std::iter::once(self_v),
2785                args.iter().copied().map(ToValue::to_value),
2786            )
2787            .collect::<smallvec::SmallVec<[_; 10]>>();
2788
2789            validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2790
2791            let mut return_value = if signal_query.return_type() != Type::UNIT {
2792                Value::from_type_unchecked(signal_query.return_type().into())
2793            } else {
2794                Value::uninitialized()
2795            };
2796            let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2797                return_value.to_glib_none_mut().0
2798            } else {
2799                ptr::null_mut()
2800            };
2801
2802            gobject_ffi::g_signal_emitv(
2803                mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2804                signal_id.into_glib(),
2805                0,
2806                return_value_ptr,
2807            );
2808
2809            R::try_from_closure_return_value(
2810                Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2811            )
2812            .unwrap()
2813        }
2814    }
2815
2816    #[track_caller]
2817    fn emit_with_values(&self, signal_id: SignalId, args: &[Value]) -> Option<Value> {
2818        unsafe {
2819            let type_ = self.type_();
2820
2821            let signal_query = signal_id.query();
2822
2823            let self_v = {
2824                let mut v = Value::uninitialized();
2825                gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2826                gobject_ffi::g_value_set_object(
2827                    v.to_glib_none_mut().0,
2828                    self.as_object_ref().to_glib_none().0,
2829                );
2830                v
2831            };
2832
2833            let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
2834                .collect::<smallvec::SmallVec<[_; 10]>>();
2835
2836            validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2837
2838            let mut return_value = if signal_query.return_type() != Type::UNIT {
2839                Value::from_type_unchecked(signal_query.return_type().into())
2840            } else {
2841                Value::uninitialized()
2842            };
2843            let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2844                return_value.to_glib_none_mut().0
2845            } else {
2846                ptr::null_mut()
2847            };
2848
2849            gobject_ffi::g_signal_emitv(
2850                mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2851                signal_id.into_glib(),
2852                0,
2853                return_value_ptr,
2854            );
2855
2856            Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
2857        }
2858    }
2859
2860    #[track_caller]
2861    fn emit_by_name<R: TryFromClosureReturnValue>(
2862        &self,
2863        signal_name: &str,
2864        args: &[&dyn ToValue],
2865    ) -> R {
2866        let type_ = self.type_();
2867        let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2868            panic!("Signal '{signal_name}' of type '{type_}' not found");
2869        });
2870        self.emit(signal_id, args)
2871    }
2872
2873    #[track_caller]
2874    fn emit_by_name_with_values(&self, signal_name: &str, args: &[Value]) -> Option<Value> {
2875        let type_ = self.type_();
2876        let signal_id = SignalId::lookup(signal_name, type_).unwrap_or_else(|| {
2877            panic!("Signal '{signal_name}' of type '{type_}' not found");
2878        });
2879        self.emit_with_values(signal_id, args)
2880    }
2881
2882    #[track_caller]
2883    fn emit_by_name_with_details<R: TryFromClosureReturnValue>(
2884        &self,
2885        signal_name: &str,
2886        details: Quark,
2887        args: &[&dyn ToValue],
2888    ) -> R {
2889        let type_ = self.type_();
2890        let signal_id = SignalId::lookup(signal_name, type_)
2891            .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2892        self.emit_with_details(signal_id, details, args)
2893    }
2894
2895    #[track_caller]
2896    fn emit_by_name_with_details_and_values(
2897        &self,
2898        signal_name: &str,
2899        details: Quark,
2900        args: &[Value],
2901    ) -> Option<Value> {
2902        let type_ = self.type_();
2903        let signal_id = SignalId::lookup(signal_name, type_)
2904            .unwrap_or_else(|| panic!("Signal '{signal_name}' of type '{type_}' not found"));
2905        self.emit_with_details_and_values(signal_id, details, args)
2906    }
2907
2908    #[track_caller]
2909    fn emit_with_details<R: TryFromClosureReturnValue>(
2910        &self,
2911        signal_id: SignalId,
2912        details: Quark,
2913        args: &[&dyn ToValue],
2914    ) -> R {
2915        let signal_query = signal_id.query();
2916        assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2917
2918        unsafe {
2919            let type_ = self.type_();
2920
2921            let self_v = {
2922                let mut v = Value::uninitialized();
2923                gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2924                gobject_ffi::g_value_set_object(
2925                    v.to_glib_none_mut().0,
2926                    self.as_object_ref().to_glib_none().0,
2927                );
2928                v
2929            };
2930
2931            let mut args = Iterator::chain(
2932                std::iter::once(self_v),
2933                args.iter().copied().map(ToValue::to_value),
2934            )
2935            .collect::<smallvec::SmallVec<[_; 10]>>();
2936
2937            validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2938
2939            let mut return_value = if signal_query.return_type() != Type::UNIT {
2940                Value::from_type_unchecked(signal_query.return_type().into())
2941            } else {
2942                Value::uninitialized()
2943            };
2944            let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2945                return_value.to_glib_none_mut().0
2946            } else {
2947                ptr::null_mut()
2948            };
2949
2950            gobject_ffi::g_signal_emitv(
2951                mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
2952                signal_id.into_glib(),
2953                details.into_glib(),
2954                return_value_ptr,
2955            );
2956
2957            R::try_from_closure_return_value(
2958                Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT),
2959            )
2960            .unwrap()
2961        }
2962    }
2963
2964    #[track_caller]
2965    fn emit_with_details_and_values(
2966        &self,
2967        signal_id: SignalId,
2968        details: Quark,
2969        args: &[Value],
2970    ) -> Option<Value> {
2971        let signal_query = signal_id.query();
2972        assert!(signal_query.flags().contains(crate::SignalFlags::DETAILED));
2973
2974        unsafe {
2975            let type_ = self.type_();
2976
2977            let self_v = {
2978                let mut v = Value::uninitialized();
2979                gobject_ffi::g_value_init(v.to_glib_none_mut().0, self.type_().into_glib());
2980                gobject_ffi::g_value_set_object(
2981                    v.to_glib_none_mut().0,
2982                    self.as_object_ref().to_glib_none().0,
2983                );
2984                v
2985            };
2986
2987            let mut args = Iterator::chain(std::iter::once(self_v), args.iter().cloned())
2988                .collect::<smallvec::SmallVec<[_; 10]>>();
2989
2990            validate_signal_arguments(type_, &signal_query, &mut args[1..]);
2991
2992            let mut return_value = if signal_query.return_type() != Type::UNIT {
2993                Value::from_type_unchecked(signal_query.return_type().into())
2994            } else {
2995                Value::uninitialized()
2996            };
2997            let return_value_ptr = if signal_query.return_type() != Type::UNIT {
2998                return_value.to_glib_none_mut().0
2999            } else {
3000                ptr::null_mut()
3001            };
3002
3003            gobject_ffi::g_signal_emitv(
3004                mut_override(args.as_ptr()) as *mut gobject_ffi::GValue,
3005                signal_id.into_glib(),
3006                details.into_glib(),
3007                return_value_ptr,
3008            );
3009
3010            Some(return_value).filter(|r| r.type_().is_valid() && r.type_() != Type::UNIT)
3011        }
3012    }
3013
3014    #[inline]
3015    fn disconnect(&self, handler_id: SignalHandlerId) {
3016        unsafe {
3017            gobject_ffi::g_signal_handler_disconnect(
3018                self.as_object_ref().to_glib_none().0,
3019                handler_id.as_raw(),
3020            );
3021        }
3022    }
3023
3024    fn connect_notify<F: Fn(&Self, &crate::ParamSpec) + Send + Sync + 'static>(
3025        &self,
3026        name: Option<&str>,
3027        f: F,
3028    ) -> SignalHandlerId {
3029        unsafe { self.connect_notify_unsafe(name, f) }
3030    }
3031
3032    fn connect_notify_local<F: Fn(&Self, &crate::ParamSpec) + 'static>(
3033        &self,
3034        name: Option<&str>,
3035        f: F,
3036    ) -> SignalHandlerId {
3037        let f = crate::thread_guard::ThreadGuard::new(f);
3038
3039        unsafe {
3040            self.connect_notify_unsafe(name, move |s, pspec| {
3041                (f.get_ref())(s, pspec);
3042            })
3043        }
3044    }
3045
3046    unsafe fn connect_notify_unsafe<F: Fn(&Self, &crate::ParamSpec)>(
3047        &self,
3048        name: Option<&str>,
3049        f: F,
3050    ) -> SignalHandlerId {
3051        unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &crate::ParamSpec)>(
3052            this: *mut gobject_ffi::GObject,
3053            param_spec: *mut gobject_ffi::GParamSpec,
3054            f: ffi::gpointer,
3055        ) where
3056            P: ObjectType,
3057        {
3058            let f: &F = &*(f as *const F);
3059            f(
3060                Object::from_glib_borrow(this).unsafe_cast_ref(),
3061                &from_glib_borrow(param_spec),
3062            )
3063        }
3064
3065        let signal_name = if let Some(name) = name {
3066            format!("notify::{name}\0")
3067        } else {
3068            "notify\0".into()
3069        };
3070
3071        let f: Box<F> = Box::new(f);
3072        crate::signal::connect_raw(
3073            self.as_object_ref().to_glib_none().0,
3074            signal_name.as_ptr() as *const _,
3075            Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
3076                notify_trampoline::<Self, F> as *const (),
3077            )),
3078            Box::into_raw(f),
3079        )
3080    }
3081
3082    #[inline]
3083    fn notify(&self, property_name: &str) {
3084        unsafe {
3085            property_name.run_with_gstr(|property_name| {
3086                gobject_ffi::g_object_notify(
3087                    self.as_object_ref().to_glib_none().0,
3088                    property_name.as_ptr(),
3089                )
3090            });
3091        }
3092    }
3093
3094    #[inline]
3095    fn notify_by_pspec(&self, pspec: &crate::ParamSpec) {
3096        unsafe {
3097            gobject_ffi::g_object_notify_by_pspec(
3098                self.as_object_ref().to_glib_none().0,
3099                pspec.to_glib_none().0,
3100            );
3101        }
3102    }
3103
3104    #[inline]
3105    fn downgrade(&self) -> WeakRef<T> {
3106        unsafe {
3107            let w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3108            gobject_ffi::g_weak_ref_init(
3109                mut_override(&*w.0),
3110                self.as_object_ref().to_glib_none().0,
3111            );
3112            w
3113        }
3114    }
3115
3116    fn add_weak_ref_notify<F: FnOnce() + Send + 'static>(&self, f: F) -> WeakRefNotify<T> {
3117        WeakRefNotify::new(self, f)
3118    }
3119
3120    fn add_weak_ref_notify_local<F: FnOnce() + 'static>(&self, f: F) -> WeakRefNotify<T> {
3121        let callback = crate::thread_guard::ThreadGuard::new(f);
3122
3123        WeakRefNotify::new(self, move || callback.into_inner()())
3124    }
3125
3126    fn bind_property<'a, 'f, 't, O: ObjectType>(
3127        &'a self,
3128        source_property: &'a str,
3129        target: &'a O,
3130        target_property: &'a str,
3131    ) -> BindingBuilder<'a, 'f, 't> {
3132        BindingBuilder::new(self, source_property, target, target_property)
3133    }
3134
3135    #[inline]
3136    fn ref_count(&self) -> u32 {
3137        let stash = self.as_object_ref().to_glib_none();
3138        let ptr: *mut gobject_ffi::GObject = stash.0;
3139
3140        unsafe { ffi::g_atomic_int_get(&(*ptr).ref_count as *const u32 as *const i32) as u32 }
3141    }
3142
3143    #[inline]
3144    unsafe fn run_dispose(&self) {
3145        gobject_ffi::g_object_run_dispose(self.as_ptr() as *mut _);
3146    }
3147}
3148
3149// Helper struct to avoid creating an extra ref on objects inside closure watches. This is safe
3150// because `watch_closure` ensures the object has a ref when the closure is called.
3151#[doc(hidden)]
3152pub struct WatchedObject<T: ObjectType>(ptr::NonNull<T::GlibType>);
3153
3154#[doc(hidden)]
3155unsafe impl<T: ObjectType + Send + Sync> Send for WatchedObject<T> {}
3156
3157#[doc(hidden)]
3158unsafe impl<T: ObjectType + Send + Sync> Sync for WatchedObject<T> {}
3159
3160#[doc(hidden)]
3161impl<T: ObjectType> WatchedObject<T> {
3162    pub fn new(obj: &T) -> Self {
3163        Self(unsafe { ptr::NonNull::new_unchecked(obj.as_ptr()) })
3164    }
3165    // rustdoc-stripper-ignore-next
3166    /// # Safety
3167    ///
3168    /// This should only be called from within a closure that was previously attached to `T` using
3169    /// `Watchable::watch_closure`.
3170    #[inline]
3171    pub unsafe fn borrow(&self) -> Borrowed<T>
3172    where
3173        T: FromGlibPtrBorrow<*mut <T as ObjectType>::GlibType>,
3174    {
3175        from_glib_borrow(self.0.as_ptr())
3176    }
3177}
3178
3179#[doc(hidden)]
3180pub trait Watchable<T: ObjectType> {
3181    fn watched_object(&self) -> WatchedObject<T>;
3182    fn watch_closure(&self, closure: &impl AsRef<Closure>);
3183}
3184
3185#[doc(hidden)]
3186impl<T: ObjectType> Watchable<T> for T {
3187    fn watched_object(&self) -> WatchedObject<T> {
3188        WatchedObject::new(self)
3189    }
3190    fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3191        ObjectExt::watch_closure(self, closure)
3192    }
3193}
3194
3195#[doc(hidden)]
3196impl<T: ObjectType> Watchable<T> for BorrowedObject<'_, T> {
3197    fn watched_object(&self) -> WatchedObject<T> {
3198        WatchedObject::new(self)
3199    }
3200    fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3201        ObjectExt::watch_closure(&**self, closure)
3202    }
3203}
3204
3205#[doc(hidden)]
3206impl<T: ObjectType> Watchable<T> for &T {
3207    fn watched_object(&self) -> WatchedObject<T> {
3208        WatchedObject::new(*self)
3209    }
3210    fn watch_closure(&self, closure: &impl AsRef<Closure>) {
3211        ObjectExt::watch_closure(*self, closure)
3212    }
3213}
3214
3215// Validate that the given property value has an acceptable type for the given property pspec
3216// and if necessary update the value
3217#[track_caller]
3218fn validate_property_type(
3219    type_: Type,
3220    allow_construct_only: bool,
3221    pspec: &crate::ParamSpec,
3222    property_value: &mut Value,
3223) {
3224    if !pspec.flags().contains(crate::ParamFlags::WRITABLE)
3225        || (!allow_construct_only && pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
3226    {
3227        panic!(
3228            "property '{}' of type '{type_}' is not writable",
3229            pspec.name(),
3230        );
3231    }
3232
3233    unsafe {
3234        // While GLib actually allows all types that can somehow be transformed
3235        // into the property type, we're more restrictive here to be consistent
3236        // with Rust's type rules. We only allow the exact same type, or if the
3237        // value type is a subtype of the property type
3238        let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
3239            mut_override(property_value.to_glib_none().0),
3240            pspec.value_type().into_glib(),
3241        ));
3242
3243        if !valid_type {
3244            if let Err(got) = coerce_object_type(property_value, pspec.value_type()) {
3245                panic!(
3246                        "property '{}' of type '{type_}' can't be set from the given type (expected: '{}', got: '{got}')",
3247                        pspec.name(),
3248                        pspec.value_type(),
3249                    );
3250            }
3251        }
3252
3253        let changed: bool = from_glib(gobject_ffi::g_param_value_validate(
3254            pspec.to_glib_none().0,
3255            property_value.to_glib_none_mut().0,
3256        ));
3257        let change_allowed = pspec.flags().contains(crate::ParamFlags::LAX_VALIDATION);
3258        if changed && !change_allowed {
3259            panic!(
3260                "property '{}' of type '{type_}' can't be set from given value, it is invalid or out of range",
3261                pspec.name(),
3262            );
3263        }
3264    }
3265}
3266
3267// If it's not directly a valid type but an object type, we check if the
3268// actual type of the contained object is compatible and if so create
3269// a properly typed Value (by mutating the existing Value).
3270// This can happen if the type field in the Value is set to a more
3271// generic type than the contained value.
3272fn coerce_object_type(property_value: &mut Value, type_: Type) -> Result<(), Type> {
3273    // return early if type coercion is not possible
3274    match property_value.get::<Option<Object>>() {
3275        Ok(Some(obj)) if !(obj.type_().is_a(type_)) => Err(obj.type_()),
3276        Ok(_) => {
3277            property_value.inner.g_type = type_.into_glib();
3278            Ok(())
3279        }
3280        Err(_) => Err(property_value.type_()),
3281    }
3282}
3283
3284#[track_caller]
3285fn validate_signal_arguments(type_: Type, signal_query: &SignalQuery, args: &mut [Value]) {
3286    let signal_name = signal_query.signal_name();
3287
3288    if signal_query.n_params() != args.len() as u32 {
3289        panic!(
3290            "Incompatible number of arguments for signal '{signal_name}' of type '{type_}' (expected {}, got {})",
3291            signal_query.n_params(),
3292            args.len(),
3293        );
3294    }
3295
3296    let param_types = Iterator::zip(args.iter_mut(), signal_query.param_types());
3297
3298    for (i, (arg, param_type)) in param_types.enumerate() {
3299        let param_type: Type = (*param_type).into();
3300        if param_type != arg.type_() {
3301            coerce_object_type(arg, param_type).unwrap_or_else(|got|
3302                panic!(
3303                    "Incompatible argument type in argument {i} for signal '{signal_name}' of type '{type_}' (expected {param_type}, got {got})",
3304                )
3305            );
3306        }
3307    }
3308}
3309
3310/// Trait for class methods on `Object` and subclasses of it.
3311pub unsafe trait ObjectClassExt {
3312    // rustdoc-stripper-ignore-next
3313    /// Check if the object class has a property `property_name` of the given `type_`.
3314    ///
3315    /// If no type is provided then only the existence of the property is checked.
3316    fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool {
3317        let ptype = self.property_type(property_name);
3318
3319        match (ptype, type_) {
3320            (None, _) => false,
3321            (Some(_), None) => true,
3322            (Some(ptype), Some(type_)) => ptype == type_,
3323        }
3324    }
3325
3326    // rustdoc-stripper-ignore-next
3327    /// Get the type of the property `property_name` of this object class.
3328    ///
3329    /// This returns `None` if the property does not exist.
3330    #[doc(alias = "get_property_type")]
3331    fn property_type(&self, property_name: &str) -> Option<Type> {
3332        self.find_property(property_name)
3333            .map(|pspec| pspec.value_type())
3334    }
3335
3336    // rustdoc-stripper-ignore-next
3337    /// Get the [`ParamSpec`](crate::ParamSpec) of the property `property_name` of this object class.
3338    #[doc(alias = "g_object_class_find_property")]
3339    fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
3340        unsafe {
3341            let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3342
3343            property_name.run_with_gstr(|property_name| {
3344                from_glib_none(gobject_ffi::g_object_class_find_property(
3345                    klass as *mut _,
3346                    property_name.as_ptr(),
3347                ))
3348            })
3349        }
3350    }
3351
3352    // rustdoc-stripper-ignore-next
3353    /// Return all [`ParamSpec`](crate::ParamSpec) of the properties of this object class.
3354    #[doc(alias = "g_object_class_list_properties")]
3355    fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
3356        unsafe {
3357            let klass = self as *const _ as *const gobject_ffi::GObjectClass;
3358
3359            let mut n_properties = 0;
3360
3361            let props =
3362                gobject_ffi::g_object_class_list_properties(klass as *mut _, &mut n_properties);
3363            PtrSlice::from_glib_container_num(props, n_properties as usize, true)
3364        }
3365    }
3366}
3367
3368unsafe impl<T: ObjectType + IsClass> ObjectClassExt for Class<T> {}
3369
3370wrapper! {
3371    #[doc(alias = "GInitiallyUnowned")]
3372    pub struct InitiallyUnowned(Object<gobject_ffi::GInitiallyUnowned, gobject_ffi::GInitiallyUnownedClass>);
3373
3374    match fn {
3375        type_ => || gobject_ffi::g_initially_unowned_get_type(),
3376    }
3377}
3378
3379// ManuallyDrop -> The lifetime of the data isn't bound to a Rust value but a GObject. Drop could free data too early.
3380// Pin          -> Make sure the pointer Box(1) passed to FFI is always valid and never reallocates.
3381// Box(1)       -> Pointer to Box(2), 64 bits large and compatible with FFI.
3382// Box(2)       -> Pointer to dyn FnOnce(), 128 bits large and incompatible with FFI (so Box(1) is passed instead).
3383type WeakRefNotifyData = ManuallyDrop<Pin<Box<Box<dyn FnOnce() + 'static>>>>;
3384
3385// rustdoc-stripper-ignore-next
3386/// A handle to disconnect a weak ref notify closure.
3387pub struct WeakRefNotify<T: ObjectType> {
3388    object: WeakRef<T>,
3389    data: WeakRefNotifyData,
3390}
3391
3392unsafe extern "C" fn notify_func(data: ffi::gpointer, _obj: *mut gobject_ffi::GObject) {
3393    // SAFETY: Call to FFI with pointers that must be valid due to Pin and lifetimes.
3394    //         ManuallyDrop and Pin are elided because the pointer only points to Box<Box<dyn FnOnce()>>.
3395    let callback: Box<Box<dyn FnOnce()>> = Box::from_raw(data as *mut _);
3396
3397    // SAFETY: Function must have type FnOnce() due type checks in WeakRefNotify::new.
3398    //         This callback can only be called once when the object is disposed, to the data can be dropped.
3399    (*callback)()
3400}
3401
3402impl<T: ObjectType> WeakRefNotify<T> {
3403    fn new<F: FnOnce() + 'static>(obj: &T, f: F) -> WeakRefNotify<T> {
3404        let data: WeakRefNotifyData = ManuallyDrop::new(Box::pin(Box::new(f)));
3405        let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&data).get_ref();
3406
3407        unsafe {
3408            // SAFETY: Call to FFI with pointers that must be valid due to Pin and lifetimes.
3409            gobject_ffi::g_object_weak_ref(
3410                obj.as_ptr() as *mut gobject_ffi::GObject,
3411                Some(notify_func),
3412                data_ptr as *mut _,
3413            );
3414        }
3415
3416        let object = obj.downgrade();
3417
3418        WeakRefNotify { object, data }
3419    }
3420
3421    // rustdoc-stripper-ignore-next
3422    /// Try to upgrade this weak reference to a strong reference.
3423    ///
3424    /// If the stored object was already destroyed then `None` is returned.
3425    pub fn upgrade(&self) -> Option<T> {
3426        self.object.upgrade()
3427    }
3428
3429    #[doc(alias = "g_object_weak_unref")]
3430    pub fn disconnect(mut self) {
3431        // Upgrade the object to make sure it's alive and the callback can't be called while it's disconnected.
3432        if let Some(obj) = self.object.upgrade() {
3433            let data_ptr: *const Box<dyn FnOnce()> = Pin::as_ref(&self.data).get_ref();
3434
3435            unsafe {
3436                // SAFETY: Call to FFI with pointers that must be valid due to Pin and lifetimes.
3437                gobject_ffi::g_object_weak_unref(
3438                    obj.as_ptr() as *mut gobject_ffi::GObject,
3439                    Some(notify_func),
3440                    data_ptr as *mut _,
3441                );
3442
3443                // SAFETY: The data can be dropped because references to GObject have been dropped too.
3444                //         The callback can't be called before or after because it's disconnected and the object is still alive.
3445                //         This function can't be called anymore either because it consumes self.
3446                ManuallyDrop::drop(&mut self.data);
3447            }
3448        }
3449    }
3450}
3451
3452// rustdoc-stripper-ignore-next
3453/// A weak reference to an object.
3454#[derive(Debug)]
3455#[doc(alias = "GWeakRef")]
3456pub struct WeakRef<T: ObjectType>(Pin<Box<gobject_ffi::GWeakRef>>, PhantomData<*mut T>);
3457
3458impl<T: ObjectType> WeakRef<T> {
3459    // rustdoc-stripper-ignore-next
3460    /// Create a new empty weak reference.
3461    ///
3462    /// `upgrade` will always return `None` until an object is set on it.
3463    #[inline]
3464    pub fn new() -> WeakRef<T> {
3465        unsafe {
3466            let mut w = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3467            gobject_ffi::g_weak_ref_init(
3468                Pin::as_mut(&mut w.0).get_unchecked_mut(),
3469                ptr::null_mut(),
3470            );
3471            w
3472        }
3473    }
3474
3475    // rustdoc-stripper-ignore-next
3476    /// Set this weak reference to the given object.
3477    #[doc(alias = "g_weak_ref_set")]
3478    #[inline]
3479    pub fn set(&self, obj: Option<&T>) {
3480        unsafe {
3481            gobject_ffi::g_weak_ref_set(
3482                mut_override(Pin::as_ref(&self.0).get_ref()),
3483                obj.map_or(std::ptr::null_mut(), |obj| {
3484                    obj.as_object_ref().to_glib_none().0
3485                }),
3486            );
3487        }
3488    }
3489
3490    // rustdoc-stripper-ignore-next
3491    /// Try to upgrade this weak reference to a strong reference.
3492    ///
3493    /// If the stored object was already destroyed or no object was set in this weak reference then
3494    /// `None` is returned.
3495    #[inline]
3496    pub fn upgrade(&self) -> Option<T> {
3497        unsafe {
3498            let ptr = gobject_ffi::g_weak_ref_get(mut_override(Pin::as_ref(&self.0).get_ref()));
3499            if ptr.is_null() {
3500                None
3501            } else {
3502                let obj: Object = from_glib_full(ptr);
3503                Some(T::unsafe_from(obj.into()))
3504            }
3505        }
3506    }
3507}
3508
3509impl<T: ObjectType> Drop for WeakRef<T> {
3510    #[inline]
3511    fn drop(&mut self) {
3512        unsafe {
3513            gobject_ffi::g_weak_ref_clear(Pin::as_mut(&mut self.0).get_unchecked_mut());
3514        }
3515    }
3516}
3517
3518impl<T: ObjectType> Clone for WeakRef<T> {
3519    #[inline]
3520    fn clone(&self) -> Self {
3521        unsafe {
3522            let o = self.upgrade();
3523
3524            let mut c = WeakRef(Box::pin(mem::zeroed()), PhantomData);
3525            gobject_ffi::g_weak_ref_init(
3526                Pin::as_mut(&mut c.0).get_unchecked_mut(),
3527                o.to_glib_none().0 as *mut gobject_ffi::GObject,
3528            );
3529
3530            c
3531        }
3532    }
3533}
3534
3535impl<T: ObjectType> Default for WeakRef<T> {
3536    #[inline]
3537    fn default() -> Self {
3538        Self::new()
3539    }
3540}
3541
3542unsafe impl<T: ObjectType + Sync + Sync> Sync for WeakRef<T> {}
3543unsafe impl<T: ObjectType + Send + Sync> Send for WeakRef<T> {}
3544
3545impl<T: ObjectType> PartialEq for WeakRef<T> {
3546    #[inline]
3547    fn eq(&self, other: &Self) -> bool {
3548        unsafe { self.0.priv_.p == other.0.priv_.p }
3549    }
3550}
3551
3552impl<T: ObjectType> PartialEq<T> for WeakRef<T> {
3553    #[inline]
3554    fn eq(&self, other: &T) -> bool {
3555        unsafe { self.0.priv_.p == other.as_ptr() as *mut std::os::raw::c_void }
3556    }
3557}
3558
3559impl<T: ObjectType> PartialOrd for WeakRef<T> {
3560    #[inline]
3561    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
3562        unsafe { self.0.priv_.p.partial_cmp(&other.0.priv_.p) }
3563    }
3564}
3565
3566// rustdoc-stripper-ignore-next
3567/// A weak reference to the object it was created for that can be sent to
3568/// different threads even for object types that don't implement `Send`.
3569///
3570/// Trying to upgrade the weak reference from another thread than the one
3571/// where it was created on will panic but dropping or cloning can be done
3572/// safely from any thread.
3573#[derive(Debug)]
3574pub struct SendWeakRef<T: ObjectType>(WeakRef<T>, Option<usize>);
3575
3576impl<T: ObjectType> SendWeakRef<T> {
3577    #[inline]
3578    #[deprecated = "Use from() instead. See https://github.com/gtk-rs/gtk-rs-core/issues/1617"]
3579    pub fn new() -> SendWeakRef<T> {
3580        SendWeakRef(WeakRef::new(), None)
3581    }
3582
3583    #[inline]
3584    pub fn into_weak_ref(self) -> WeakRef<T> {
3585        assert!(
3586            self.1.is_none() || self.1 == Some(thread_id()),
3587            "SendWeakRef dereferenced on a different thread",
3588        );
3589
3590        self.0
3591    }
3592}
3593
3594impl<T: ObjectType> ops::Deref for SendWeakRef<T> {
3595    type Target = WeakRef<T>;
3596
3597    #[inline]
3598    fn deref(&self) -> &WeakRef<T> {
3599        assert!(
3600            self.1.is_none() || self.1 == Some(thread_id()),
3601            "SendWeakRef dereferenced on a different thread"
3602        );
3603
3604        &self.0
3605    }
3606}
3607
3608// Deriving this gives the wrong trait bounds
3609impl<T: ObjectType> Clone for SendWeakRef<T> {
3610    #[inline]
3611    fn clone(&self) -> Self {
3612        Self(self.0.clone(), self.1)
3613    }
3614}
3615
3616impl<T: ObjectType> Default for SendWeakRef<T> {
3617    #[inline]
3618    fn default() -> Self {
3619        #[allow(deprecated)]
3620        Self::new()
3621    }
3622}
3623
3624impl<T: ObjectType> From<WeakRef<T>> for SendWeakRef<T> {
3625    #[inline]
3626    fn from(v: WeakRef<T>) -> SendWeakRef<T> {
3627        SendWeakRef(v, Some(thread_id()))
3628    }
3629}
3630
3631unsafe impl<T: ObjectType> Sync for SendWeakRef<T> {}
3632unsafe impl<T: ObjectType> Send for SendWeakRef<T> {}
3633
3634type TransformFn<'b> =
3635    Option<Box<dyn Fn(&'b crate::Binding, &'b Value) -> Option<Value> + Send + Sync + 'static>>;
3636
3637// rustdoc-stripper-ignore-next
3638/// Builder for object property bindings.
3639#[must_use = "The builder must be built to be used"]
3640pub struct BindingBuilder<'a, 'f, 't> {
3641    source: &'a ObjectRef,
3642    source_property: &'a str,
3643    target: &'a ObjectRef,
3644    target_property: &'a str,
3645    flags: crate::BindingFlags,
3646    transform_from: TransformFn<'f>,
3647    transform_to: TransformFn<'t>,
3648}
3649
3650impl fmt::Debug for BindingBuilder<'_, '_, '_> {
3651    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3652        f.debug_struct("BindingBuilder")
3653            .field("source", &self.source)
3654            .field("source_property", &self.source_property)
3655            .field("target", &self.target)
3656            .field("target_property", &self.target_property)
3657            .field("flags", &self.flags)
3658            .finish()
3659    }
3660}
3661
3662impl<'a, 'f, 't> BindingBuilder<'a, 'f, 't> {
3663    fn new(
3664        source: &'a impl ObjectType,
3665        source_property: &'a str,
3666        target: &'a impl ObjectType,
3667        target_property: &'a str,
3668    ) -> Self {
3669        Self {
3670            source: source.as_object_ref(),
3671            source_property,
3672            target: target.as_object_ref(),
3673            target_property,
3674            flags: crate::BindingFlags::DEFAULT,
3675            transform_to: None,
3676            transform_from: None,
3677        }
3678    }
3679
3680    // rustdoc-stripper-ignore-next
3681    /// Transform changed property values from the target object to the source object with the given closure.
3682    ///
3683    /// This function operates on `glib::Value`s.
3684    /// See [`Self::transform_from`] for a version which operates on concrete argument and return types.
3685    pub fn transform_from_with_values<
3686        F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3687    >(
3688        self,
3689        func: F,
3690    ) -> Self {
3691        Self {
3692            transform_from: Some(Box::new(func)),
3693            ..self
3694        }
3695    }
3696
3697    // rustdoc-stripper-ignore-next
3698    /// Transform changed property values from the target object to the source object with the given closure.
3699    ///
3700    /// This function operates on concrete argument and return types.
3701    /// See [`Self::transform_from_with_values`] for a version which operates on `glib::Value`s.
3702    pub fn transform_from<
3703        S: FromValue<'f>,
3704        T: Into<Value>,
3705        F: Fn(&'f crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3706    >(
3707        self,
3708        func: F,
3709    ) -> Self {
3710        Self {
3711            transform_from: Some(Box::new(move |binding, from_value| {
3712                let from_value = from_value.get().expect("Wrong value type");
3713                func(binding, from_value).map(|r| r.into())
3714            })),
3715            ..self
3716        }
3717    }
3718
3719    // rustdoc-stripper-ignore-next
3720    /// Transform changed property values from the source object to the target object with the given closure.
3721    ///
3722    /// This function operates on `glib::Value`s.
3723    /// See [`Self::transform_to`] for a version which operates on concrete argument and return types.
3724    pub fn transform_to_with_values<
3725        F: Fn(&crate::Binding, &Value) -> Option<Value> + Send + Sync + 'static,
3726    >(
3727        self,
3728        func: F,
3729    ) -> Self {
3730        Self {
3731            transform_to: Some(Box::new(func)),
3732            ..self
3733        }
3734    }
3735
3736    // rustdoc-stripper-ignore-next
3737    /// Transform changed property values from the source object to the target object with the given closure.
3738    ///
3739    /// This function operates on concrete argument and return types.
3740    /// See [`Self::transform_to_with_values`] for a version which operates on `glib::Value`s.
3741    pub fn transform_to<
3742        S: FromValue<'t>,
3743        T: Into<Value>,
3744        F: Fn(&'t crate::Binding, S) -> Option<T> + Send + Sync + 'static,
3745    >(
3746        self,
3747        func: F,
3748    ) -> Self {
3749        Self {
3750            transform_to: Some(Box::new(move |binding, from_value| {
3751                let from_value = from_value.get().expect("Wrong value type");
3752                func(binding, from_value).map(|r| r.into())
3753            })),
3754            ..self
3755        }
3756    }
3757
3758    // rustdoc-stripper-ignore-next
3759    /// Bind the properties with the given flags.
3760    pub fn flags(self, flags: crate::BindingFlags) -> Self {
3761        Self { flags, ..self }
3762    }
3763
3764    // rustdoc-stripper-ignore-next
3765    /// Set the binding flags to [`BIDIRECTIONAL`][crate::BindingFlags::BIDIRECTIONAL].
3766    pub fn bidirectional(mut self) -> Self {
3767        self.flags |= crate::BindingFlags::BIDIRECTIONAL;
3768        self
3769    }
3770
3771    // rustdoc-stripper-ignore-next
3772    /// Set the binding flags to [`SYNC_CREATE`][crate::BindingFlags::SYNC_CREATE].
3773    pub fn sync_create(mut self) -> Self {
3774        self.flags |= crate::BindingFlags::SYNC_CREATE;
3775        self
3776    }
3777
3778    // rustdoc-stripper-ignore-next
3779    /// Set the binding flags to [`INVERT_BOOLEAN`][crate::BindingFlags::INVERT_BOOLEAN].
3780    pub fn invert_boolean(mut self) -> Self {
3781        self.flags |= crate::BindingFlags::INVERT_BOOLEAN;
3782        self
3783    }
3784
3785    // rustdoc-stripper-ignore-next
3786    /// Establish the property binding.
3787    ///
3788    /// # Panics
3789    /// This panics if the provided properties do not exist.
3790    #[track_caller]
3791    pub fn build(self) -> crate::Binding {
3792        unsafe extern "C" fn transform_to_trampoline(
3793            binding: *mut gobject_ffi::GBinding,
3794            from_value: *const gobject_ffi::GValue,
3795            to_value: *mut gobject_ffi::GValue,
3796            user_data: ffi::gpointer,
3797        ) -> ffi::gboolean {
3798            let transform_data = &*(user_data
3799                as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3800
3801            match (transform_data.0.as_ref().unwrap())(
3802                &from_glib_borrow(binding),
3803                &*(from_value as *const Value),
3804            ) {
3805                None => false,
3806                Some(res) => {
3807                    assert!(
3808                        res.type_().is_a(transform_data.3.value_type()),
3809                        "Target property {} expected type {} but transform_to function returned {}",
3810                        transform_data.3.name(),
3811                        transform_data.3.value_type(),
3812                        res.type_()
3813                    );
3814                    *to_value = res.into_raw();
3815                    true
3816                }
3817            }
3818            .into_glib()
3819        }
3820
3821        unsafe extern "C" fn transform_from_trampoline(
3822            binding: *mut gobject_ffi::GBinding,
3823            from_value: *const gobject_ffi::GValue,
3824            to_value: *mut gobject_ffi::GValue,
3825            user_data: ffi::gpointer,
3826        ) -> ffi::gboolean {
3827            let transform_data = &*(user_data
3828                as *const (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec));
3829
3830            match (transform_data.1.as_ref().unwrap())(
3831                &from_glib_borrow(binding),
3832                &*(from_value as *const Value),
3833            ) {
3834                None => false,
3835                Some(res) => {
3836                    assert!(
3837                        res.type_().is_a(transform_data.2.value_type()),
3838                        "Source property {} expected type {} but transform_from function returned {}",
3839                        transform_data.2.name(),
3840                        transform_data.2.value_type(),
3841                        res.type_()
3842                    );
3843                    *to_value = res.into_raw();
3844                    true
3845                }
3846            }
3847            .into_glib()
3848        }
3849
3850        unsafe extern "C" fn free_transform_data(data: ffi::gpointer) {
3851            let _ = Box::from_raw(
3852                data as *mut (TransformFn, TransformFn, crate::ParamSpec, crate::ParamSpec),
3853            );
3854        }
3855
3856        unsafe {
3857            let source = Object {
3858                inner: TypedObjectRef::new(self.source.clone()),
3859                phantom: std::marker::PhantomData,
3860            };
3861            let target = Object {
3862                inner: TypedObjectRef::new(self.target.clone()),
3863                phantom: std::marker::PhantomData,
3864            };
3865
3866            let source_property = source
3867                .find_property(self.source_property)
3868                .unwrap_or_else(|| {
3869                    panic!(
3870                        "Source property {} on type {} not found",
3871                        self.source_property,
3872                        source.type_()
3873                    );
3874                });
3875            let target_property = target
3876                .find_property(self.target_property)
3877                .unwrap_or_else(|| {
3878                    panic!(
3879                        "Target property {} on type {} not found",
3880                        self.target_property,
3881                        target.type_()
3882                    );
3883                });
3884
3885            let source_property_name = source_property.name().as_ptr();
3886            let target_property_name = target_property.name().as_ptr();
3887
3888            let have_transform_to = self.transform_to.is_some();
3889            let have_transform_from = self.transform_from.is_some();
3890            let transform_data = if have_transform_to || have_transform_from {
3891                Box::into_raw(Box::new((
3892                    self.transform_to,
3893                    self.transform_from,
3894                    source_property,
3895                    target_property,
3896                )))
3897            } else {
3898                ptr::null_mut()
3899            };
3900
3901            from_glib_none(gobject_ffi::g_object_bind_property_full(
3902                source.to_glib_none().0,
3903                source_property_name as *const _,
3904                target.to_glib_none().0,
3905                target_property_name as *const _,
3906                self.flags.into_glib(),
3907                if have_transform_to {
3908                    Some(transform_to_trampoline)
3909                } else {
3910                    None
3911                },
3912                if have_transform_from {
3913                    Some(transform_from_trampoline)
3914                } else {
3915                    None
3916                },
3917                transform_data as ffi::gpointer,
3918                if transform_data.is_null() {
3919                    None
3920                } else {
3921                    Some(free_transform_data)
3922                },
3923            ))
3924        }
3925    }
3926}
3927
3928// rustdoc-stripper-ignore-next
3929/// Class struct of type `T`.
3930#[repr(transparent)]
3931pub struct Class<T: IsClass>(T::GlibClassType);
3932
3933impl<T: IsClass> Class<T> {
3934    // rustdoc-stripper-ignore-next
3935    /// Get the type id for this class.
3936    ///
3937    /// This is not equivalent to `T::static_type()` but is the type of the subclass of `T` where
3938    /// this class belongs to.
3939    #[doc(alias = "get_type")]
3940    #[inline]
3941    pub fn type_(&self) -> Type {
3942        unsafe {
3943            // This also works for interfaces because they also have the type
3944            // as the first struct field.
3945            let klass = self as *const _ as *const gobject_ffi::GTypeClass;
3946            from_glib((*klass).g_type)
3947        }
3948    }
3949
3950    // rustdoc-stripper-ignore-next
3951    /// Casts this class to a reference to a parent type's class.
3952    #[inline]
3953    pub fn upcast_ref<U: IsClass>(&self) -> &Class<U>
3954    where
3955        T: IsA<U>,
3956    {
3957        unsafe {
3958            let klass = self as *const _ as *const Class<U>;
3959            &*klass
3960        }
3961    }
3962
3963    // rustdoc-stripper-ignore-next
3964    /// Casts this class to a mutable reference to a parent type's class.
3965    #[inline]
3966    pub fn upcast_ref_mut<U: IsClass>(&mut self) -> &mut Class<U>
3967    where
3968        T: IsA<U>,
3969    {
3970        unsafe {
3971            let klass = self as *mut _ as *mut Class<U>;
3972            &mut *klass
3973        }
3974    }
3975
3976    // rustdoc-stripper-ignore-next
3977    /// Casts this class to a reference to a child type's class or
3978    /// fails if this class is not implementing the child class.
3979    #[inline]
3980    pub fn downcast_ref<U: IsClass + IsA<T>>(&self) -> Option<&Class<U>> {
3981        if !self.type_().is_a(U::static_type()) {
3982            return None;
3983        }
3984
3985        unsafe {
3986            let klass = self as *const _ as *const Class<U>;
3987            Some(&*klass)
3988        }
3989    }
3990
3991    // rustdoc-stripper-ignore-next
3992    /// Casts this class to a mutable reference to a child type's class or
3993    /// fails if this class is not implementing the child class.
3994    #[inline]
3995    pub fn downcast_ref_mut<U: IsClass + IsA<T>>(&mut self) -> Option<&mut Class<U>> {
3996        if !self.type_().is_a(U::static_type()) {
3997            return None;
3998        }
3999
4000        unsafe {
4001            let klass = self as *mut _ as *mut Class<U>;
4002            Some(&mut *klass)
4003        }
4004    }
4005
4006    // rustdoc-stripper-ignore-next
4007    /// Gets the class struct for `Self` of `type_`.
4008    ///
4009    /// This will return `None` if `type_` is not a subclass of `Self`.
4010    #[doc(alias = "g_type_class_ref")]
4011    #[inline]
4012    pub fn from_type(type_: Type) -> Option<ClassRef<'static, T>> {
4013        if !type_.is_a(T::static_type()) {
4014            return None;
4015        }
4016
4017        unsafe {
4018            let ptr = gobject_ffi::g_type_class_ref(type_.into_glib());
4019            if ptr.is_null() {
4020                None
4021            } else {
4022                Some(ClassRef(
4023                    ptr::NonNull::new_unchecked(ptr as *mut Self),
4024                    true,
4025                    PhantomData,
4026                ))
4027            }
4028        }
4029    }
4030
4031    // rustdoc-stripper-ignore-next
4032    /// Gets the parent class struct, if any.
4033    #[doc(alias = "g_type_class_peek_parent")]
4034    #[inline]
4035    pub fn parent(&self) -> Option<ClassRef<T>> {
4036        unsafe {
4037            let ptr = gobject_ffi::g_type_class_peek_parent(&self.0 as *const _ as *mut _);
4038            if ptr.is_null() {
4039                None
4040            } else {
4041                Some(ClassRef(
4042                    ptr::NonNull::new_unchecked(ptr as *mut Self),
4043                    false,
4044                    PhantomData,
4045                ))
4046            }
4047        }
4048    }
4049}
4050
4051unsafe impl<T: IsClass> Send for Class<T> {}
4052unsafe impl<T: IsClass> Sync for Class<T> {}
4053
4054impl<T: IsClass> AsRef<T::GlibClassType> for Class<T> {
4055    #[inline]
4056    fn as_ref(&self) -> &T::GlibClassType {
4057        &self.0
4058    }
4059}
4060
4061impl<T: IsClass> AsMut<T::GlibClassType> for Class<T> {
4062    #[inline]
4063    fn as_mut(&mut self) -> &mut T::GlibClassType {
4064        &mut self.0
4065    }
4066}
4067
4068// rustdoc-stripper-ignore-next
4069/// Reference to the class struct of type `T`.
4070#[derive(Debug)]
4071pub struct ClassRef<'a, T: IsClass>(ptr::NonNull<Class<T>>, bool, PhantomData<&'a ()>);
4072
4073impl<T: IsClass> ops::Deref for ClassRef<'_, T> {
4074    type Target = Class<T>;
4075
4076    #[inline]
4077    fn deref(&self) -> &Class<T> {
4078        unsafe { self.0.as_ref() }
4079    }
4080}
4081
4082impl<T: IsClass> Drop for ClassRef<'_, T> {
4083    #[inline]
4084    fn drop(&mut self) {
4085        if self.1 {
4086            unsafe {
4087                gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
4088            }
4089        }
4090    }
4091}
4092
4093unsafe impl<T: IsClass> Send for ClassRef<'_, T> {}
4094unsafe impl<T: IsClass> Sync for ClassRef<'_, T> {}
4095
4096// This should require Self: IsA<Self::Super>, but that seems to cause a cycle error
4097pub unsafe trait ParentClassIs: IsClass {
4098    type Parent: IsClass;
4099}
4100
4101// rustdoc-stripper-ignore-next
4102/// Automatically implemented by `ObjectSubclass` variants of
4103/// [`wrapper!`][crate::wrapper!]
4104pub unsafe trait ObjectSubclassIs: IsClass {
4105    type Subclass: ObjectSubclass;
4106}
4107
4108impl<T: ParentClassIs> ops::Deref for Class<T> {
4109    type Target = Class<T::Parent>;
4110
4111    #[inline]
4112    fn deref(&self) -> &Self::Target {
4113        unsafe {
4114            let klass = self as *const _ as *const Self::Target;
4115            &*klass
4116        }
4117    }
4118}
4119
4120impl<T: ParentClassIs> ops::DerefMut for Class<T> {
4121    #[inline]
4122    fn deref_mut(&mut self) -> &mut Self::Target {
4123        unsafe {
4124            let klass = self as *mut _ as *mut Self::Target;
4125            &mut *klass
4126        }
4127    }
4128}
4129
4130// rustdoc-stripper-ignore-next
4131/// Trait implemented by class types.
4132pub unsafe trait IsClass: ObjectType {}
4133
4134// rustdoc-stripper-ignore-next
4135/// Interface struct of type `T` for some type.
4136#[repr(transparent)]
4137pub struct Interface<T: IsInterface>(T::GlibClassType);
4138
4139impl<T: IsInterface> Interface<T> {
4140    // rustdoc-stripper-ignore-next
4141    /// Get the type id for this interface.
4142    ///
4143    /// This is equivalent to `T::static_type()`.
4144    #[doc(alias = "get_type")]
4145    #[inline]
4146    pub fn type_(&self) -> Type {
4147        unsafe {
4148            let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4149            from_glib((*klass).g_type)
4150        }
4151    }
4152
4153    // rustdoc-stripper-ignore-next
4154    /// Get the type id for the instance type of this interface.
4155    ///
4156    /// This is not equivalent to `T::static_type()` but is the type id of the type this specific
4157    /// interface belongs to.
4158    #[doc(alias = "get_instance_type")]
4159    #[inline]
4160    pub fn instance_type(&self) -> Type {
4161        unsafe {
4162            // This also works for interfaces because they also have the type
4163            // as the first struct field.
4164            let klass = self as *const _ as *const gobject_ffi::GTypeInterface;
4165            from_glib((*klass).g_instance_type)
4166        }
4167    }
4168
4169    // rustdoc-stripper-ignore-next
4170    /// Gets the interface struct for `Self` of `klass`.
4171    ///
4172    /// This will return `None` if `klass` is not implementing `Self`.
4173    #[inline]
4174    pub fn from_class<U: IsClass>(klass: &Class<U>) -> Option<InterfaceRef<T>> {
4175        if !klass.type_().is_a(T::static_type()) {
4176            return None;
4177        }
4178
4179        unsafe {
4180            let ptr = gobject_ffi::g_type_interface_peek(
4181                &klass.0 as *const _ as *mut _,
4182                T::static_type().into_glib(),
4183            );
4184            if ptr.is_null() {
4185                None
4186            } else {
4187                Some(InterfaceRef(
4188                    ptr::NonNull::new_unchecked(ptr as *mut Self),
4189                    false,
4190                    PhantomData,
4191                ))
4192            }
4193        }
4194    }
4195
4196    // rustdoc-stripper-ignore-next
4197    /// Gets the default interface struct for `Self`.
4198    ///
4199    /// This will return `None` if `type_` is not an interface.
4200    #[inline]
4201    pub fn from_type(type_: Type) -> Option<InterfaceRef<'static, T>> {
4202        if !type_.is_a(Type::INTERFACE) {
4203            return None;
4204        }
4205
4206        unsafe {
4207            let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4208            if ptr.is_null() {
4209                None
4210            } else {
4211                Some(InterfaceRef(
4212                    ptr::NonNull::new_unchecked(ptr as *mut Self),
4213                    true,
4214                    PhantomData,
4215                ))
4216            }
4217        }
4218    }
4219
4220    // rustdoc-stripper-ignore-next
4221    /// Gets the default interface struct for `Self`.
4222    #[doc(alias = "g_type_default_interface_ref")]
4223    #[allow(clippy::should_implement_trait)]
4224    #[inline]
4225    pub fn default() -> InterfaceRef<'static, T> {
4226        unsafe {
4227            let ptr = gobject_ffi::g_type_default_interface_ref(T::static_type().into_glib());
4228            debug_assert!(!ptr.is_null());
4229            InterfaceRef(
4230                ptr::NonNull::new_unchecked(ptr as *mut Self),
4231                true,
4232                PhantomData,
4233            )
4234        }
4235    }
4236
4237    // rustdoc-stripper-ignore-next
4238    /// Gets the parent interface struct, if any.
4239    ///
4240    /// This returns the parent interface if a parent type of the instance type also implements the
4241    /// interface.
4242    #[doc(alias = "g_type_interface_peek_parent")]
4243    #[inline]
4244    pub fn parent(&self) -> Option<InterfaceRef<T>> {
4245        unsafe {
4246            let ptr = gobject_ffi::g_type_interface_peek_parent(&self.0 as *const _ as *mut _);
4247            if ptr.is_null() {
4248                None
4249            } else {
4250                Some(InterfaceRef(
4251                    ptr::NonNull::new_unchecked(ptr as *mut Self),
4252                    false,
4253                    PhantomData,
4254                ))
4255            }
4256        }
4257    }
4258}
4259
4260impl<T: IsA<Object> + IsInterface> Interface<T> {
4261    // rustdoc-stripper-ignore-next
4262    /// Check if this interface has a property `property_name` of the given `type_`.
4263    ///
4264    /// If no type is provided then only the existence of the property is checked.
4265    pub fn has_property(&self, property_name: &str, type_: Option<Type>) -> bool {
4266        let ptype = self.property_type(property_name);
4267
4268        match (ptype, type_) {
4269            (None, _) => false,
4270            (Some(_), None) => true,
4271            (Some(ptype), Some(type_)) => ptype == type_,
4272        }
4273    }
4274
4275    // rustdoc-stripper-ignore-next
4276    /// Get the type of the property `property_name` of this interface.
4277    ///
4278    /// This returns `None` if the property does not exist.
4279    #[doc(alias = "get_property_type")]
4280    pub fn property_type(&self, property_name: &str) -> Option<Type> {
4281        self.find_property(property_name)
4282            .map(|pspec| pspec.value_type())
4283    }
4284
4285    // rustdoc-stripper-ignore-next
4286    /// Get the [`ParamSpec`](crate::ParamSpec) of the property `property_name` of this interface.
4287    #[doc(alias = "g_object_interface_find_property")]
4288    pub fn find_property(&self, property_name: &str) -> Option<crate::ParamSpec> {
4289        unsafe {
4290            let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4291
4292            from_glib_none(gobject_ffi::g_object_interface_find_property(
4293                interface as *mut _,
4294                property_name.to_glib_none().0,
4295            ))
4296        }
4297    }
4298
4299    // rustdoc-stripper-ignore-next
4300    /// Return all [`ParamSpec`](crate::ParamSpec) of the properties of this interface.
4301    #[doc(alias = "g_object_interface_list_properties")]
4302    pub fn list_properties(&self) -> PtrSlice<crate::ParamSpec> {
4303        unsafe {
4304            let interface = self as *const _ as *const gobject_ffi::GTypeInterface;
4305
4306            let mut n_properties = 0;
4307
4308            let props = gobject_ffi::g_object_interface_list_properties(
4309                interface as *mut _,
4310                &mut n_properties,
4311            );
4312            PtrSlice::from_glib_container_num(props, n_properties as usize, true)
4313        }
4314    }
4315}
4316
4317unsafe impl<T: IsInterface> Send for Interface<T> {}
4318unsafe impl<T: IsInterface> Sync for Interface<T> {}
4319
4320impl<T: IsInterface> AsRef<T::GlibClassType> for Interface<T> {
4321    #[inline]
4322    fn as_ref(&self) -> &T::GlibClassType {
4323        &self.0
4324    }
4325}
4326
4327impl<T: IsInterface> AsMut<T::GlibClassType> for Interface<T> {
4328    #[inline]
4329    fn as_mut(&mut self) -> &mut T::GlibClassType {
4330        &mut self.0
4331    }
4332}
4333
4334// rustdoc-stripper-ignore-next
4335/// Reference to a class struct of type `T`.
4336#[derive(Debug)]
4337pub struct InterfaceRef<'a, T: IsInterface>(ptr::NonNull<Interface<T>>, bool, PhantomData<&'a ()>);
4338
4339impl<T: IsInterface> Drop for InterfaceRef<'_, T> {
4340    #[inline]
4341    fn drop(&mut self) {
4342        if self.1 {
4343            unsafe {
4344                gobject_ffi::g_type_default_interface_unref(self.0.as_ptr() as *mut _);
4345            }
4346        }
4347    }
4348}
4349
4350impl<T: IsInterface> ops::Deref for InterfaceRef<'_, T> {
4351    type Target = Interface<T>;
4352
4353    #[inline]
4354    fn deref(&self) -> &Interface<T> {
4355        unsafe { self.0.as_ref() }
4356    }
4357}
4358
4359unsafe impl<T: IsInterface> Send for InterfaceRef<'_, T> {}
4360unsafe impl<T: IsInterface> Sync for InterfaceRef<'_, T> {}
4361
4362// rustdoc-stripper-ignore-next
4363/// Trait implemented by interface types.
4364pub unsafe trait IsInterface: ObjectType {}
4365
4366// rustdoc-stripper-ignore-next
4367/// `Value` type checker for object types.
4368pub struct ObjectValueTypeChecker<T>(std::marker::PhantomData<T>);
4369
4370unsafe impl<T: StaticType> crate::value::ValueTypeChecker for ObjectValueTypeChecker<T> {
4371    type Error = crate::value::ValueTypeMismatchOrNoneError<crate::value::ValueTypeMismatchError>;
4372
4373    fn check(value: &Value) -> Result<(), Self::Error> {
4374        // g_type_check_value_holds() only checks for the GType of the GValue. This might be
4375        // initialized to a parent type of the expected type and would then fail while it's
4376        // still valid to retrieve the value.
4377
4378        unsafe {
4379            let requested_type = T::static_type().into_glib();
4380            let type_ = value.inner.g_type;
4381
4382            // Direct match or value type is a subtype of the requested type.
4383            if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4384                let obj = gobject_ffi::g_value_get_object(&value.inner);
4385                if obj.is_null() {
4386                    return Err(Self::Error::UnexpectedNone);
4387                } else {
4388                    return Ok(());
4389                }
4390            }
4391
4392            // If the value type is not a GObject or subtype of GObject then there's a mismatch.
4393            if gobject_ffi::g_type_is_a(type_, gobject_ffi::G_TYPE_OBJECT) == ffi::GFALSE {
4394                return Err(crate::value::ValueTypeMismatchError::new(
4395                    Type::from_glib(type_),
4396                    T::static_type(),
4397                )
4398                .into());
4399            }
4400
4401            // Otherwise peek at the actual object and its concrete type.
4402            let obj = gobject_ffi::g_value_get_object(&value.inner);
4403
4404            // Allow any types if the object is NULL.
4405            if obj.is_null() {
4406                return Err(Self::Error::UnexpectedNone);
4407            }
4408
4409            let type_ = (*(*obj).g_type_instance.g_class).g_type;
4410            // Direct match or concrete type is a subtype of the requested type.
4411            if gobject_ffi::g_type_is_a(type_, requested_type) != ffi::GFALSE {
4412                Ok(())
4413            } else {
4414                Err(crate::value::ValueTypeMismatchError::new(
4415                    Type::from_glib(type_),
4416                    T::static_type(),
4417                )
4418                .into())
4419            }
4420        }
4421    }
4422}
4423
4424// rustdoc-stripper-ignore-next
4425/// Borrowed reference to an object of type `T`.
4426///
4427/// This dereferences into `&T`.
4428#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4429#[repr(transparent)]
4430pub struct BorrowedObject<'a, T> {
4431    ptr: ptr::NonNull<gobject_ffi::GObject>,
4432    phantom: PhantomData<&'a T>,
4433}
4434
4435unsafe impl<T: Send + Sync> Send for BorrowedObject<'_, T> {}
4436unsafe impl<T: Send + Sync> Sync for BorrowedObject<'_, T> {}
4437
4438impl<'a, T: ObjectType> BorrowedObject<'a, T> {
4439    // rustdoc-stripper-ignore-next
4440    /// Creates a new borrowed object reference.
4441    ///
4442    /// # SAFETY:
4443    ///
4444    /// The pointer needs to be valid for at least the lifetime `'a`.
4445    #[inline]
4446    pub unsafe fn new(ptr: *mut T::GlibType) -> BorrowedObject<'a, T> {
4447        BorrowedObject {
4448            ptr: ptr::NonNull::new_unchecked(ptr as *mut _),
4449            phantom: PhantomData,
4450        }
4451    }
4452
4453    // rustdoc-stripper-ignore-next
4454    /// Downgrade to a weak reference.
4455    #[inline]
4456    pub fn downgrade(&self) -> <Self as crate::clone::Downgrade>::Weak
4457    where
4458        T: crate::clone::Downgrade,
4459    {
4460        <T as crate::clone::Downgrade>::downgrade(self)
4461    }
4462}
4463
4464impl<T> ops::Deref for BorrowedObject<'_, T> {
4465    type Target = T;
4466
4467    #[inline]
4468    fn deref(&self) -> &T {
4469        unsafe { &*(&self.ptr as *const _ as *const T) }
4470    }
4471}
4472
4473impl<T> AsRef<T> for BorrowedObject<'_, T> {
4474    #[inline]
4475    fn as_ref(&self) -> &T {
4476        unsafe { &*(&self.ptr as *const _ as *const T) }
4477    }
4478}
4479
4480impl<T: PartialEq> PartialEq<T> for BorrowedObject<'_, T> {
4481    #[inline]
4482    fn eq(&self, other: &T) -> bool {
4483        <T as PartialEq>::eq(self, other)
4484    }
4485}
4486
4487impl<T: PartialOrd> PartialOrd<T> for BorrowedObject<'_, T> {
4488    #[inline]
4489    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
4490        <T as PartialOrd>::partial_cmp(self, other)
4491    }
4492}
4493
4494impl<T: crate::clone::Downgrade + ObjectType> crate::clone::Downgrade for BorrowedObject<'_, T> {
4495    type Weak = <T as crate::clone::Downgrade>::Weak;
4496
4497    #[inline]
4498    fn downgrade(&self) -> Self::Weak {
4499        <T as crate::clone::Downgrade>::downgrade(self)
4500    }
4501}
4502
4503#[cfg(test)]
4504mod tests {
4505    use std::{
4506        cell::Cell,
4507        rc::Rc,
4508        sync::{
4509            atomic::{AtomicBool, Ordering},
4510            Arc,
4511        },
4512    };
4513
4514    use super::*;
4515
4516    #[test]
4517    fn new() {
4518        let obj: Object = Object::new();
4519        drop(obj);
4520    }
4521
4522    #[test]
4523    fn data() {
4524        let obj: Object = Object::new();
4525        unsafe {
4526            obj.set_data::<String>("foo", "hello".into());
4527            let data = obj.data::<String>("foo").unwrap();
4528            assert_eq!(data.as_ref(), "hello");
4529            let data2 = obj.steal_data::<String>("foo").unwrap();
4530            assert_eq!(data2, "hello");
4531        }
4532    }
4533
4534    #[test]
4535    fn weak_ref() {
4536        let obj: Object = Object::new();
4537
4538        let weakref: WeakRef<Object> = WeakRef::new();
4539        weakref.set(Some(&obj));
4540        assert!(weakref.upgrade().is_some());
4541        weakref.set(None);
4542        assert!(weakref.upgrade().is_none());
4543
4544        let weakref = WeakRef::new();
4545        weakref.set(Some(&obj));
4546        assert!(weakref.upgrade().is_some());
4547
4548        drop(obj);
4549        assert!(weakref.upgrade().is_none());
4550    }
4551
4552    #[test]
4553    fn weak_ref_notify() {
4554        let obj: Object = Object::new();
4555
4556        let handle = obj.add_weak_ref_notify(|| {
4557            unreachable!();
4558        });
4559
4560        handle.disconnect();
4561
4562        let called = Arc::new(AtomicBool::new(false));
4563        let called_weak = Arc::downgrade(&called);
4564        let handle = obj.add_weak_ref_notify(move || {
4565            called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4566        });
4567
4568        drop(obj);
4569        assert!(called.load(Ordering::SeqCst));
4570        handle.disconnect();
4571
4572        let obj: Object = Object::new();
4573
4574        let called = Arc::new(AtomicBool::new(false));
4575        let called_weak = Arc::downgrade(&called);
4576        obj.add_weak_ref_notify(move || {
4577            called_weak.upgrade().unwrap().store(true, Ordering::SeqCst);
4578        });
4579
4580        drop(obj);
4581        assert!(called.load(Ordering::SeqCst));
4582
4583        let obj: Object = Object::new();
4584
4585        let called = Rc::new(Cell::new(false));
4586        let called_weak = Rc::downgrade(&called);
4587        obj.add_weak_ref_notify_local(move || {
4588            called_weak.upgrade().unwrap().set(true);
4589        });
4590
4591        drop(obj);
4592        assert!(called.get());
4593    }
4594
4595    #[test]
4596    fn test_value() {
4597        let obj1: Object = Object::new();
4598        let v = obj1.to_value();
4599        let obj2 = v.get::<&Object>().unwrap();
4600
4601        assert_eq!(obj1.as_ptr(), obj2.as_ptr());
4602    }
4603
4604    #[test]
4605    fn test_borrow_hashing() {
4606        let mut m = std::collections::HashSet::new();
4607        let boxed_object = crate::BoxedAnyObject::new("");
4608
4609        m.insert(boxed_object.clone());
4610
4611        let object: &Object = std::borrow::Borrow::borrow(&boxed_object);
4612        assert_eq!(m.get(object), Some(&boxed_object));
4613    }
4614}