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