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