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