glib/
object.rs

1// Copyright 2015-2016, The Gtk-rs Project Developers.
2// See the COPYRIGHT file at the top-level directory of this distribution.
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5//! `IMPL` Object wrapper implementation and `Object` binding.
6
7use glib_sys;
8use gobject_sys;
9use std::fmt;
10use std::hash;
11use std::marker::PhantomData;
12use std::mem;
13use std::ops;
14use std::ptr;
15use translate::*;
16use types::StaticType;
17
18use value::ToValue;
19use BoolError;
20use Closure;
21use SignalHandlerId;
22use Type;
23use Value;
24
25use get_thread_id;
26
27#[doc(hidden)]
28pub use gobject_sys::GObject;
29
30#[doc(hidden)]
31pub use gobject_sys::GObjectClass;
32
33/// Implemented by types representing `glib::Object` and subclasses of it.
34pub unsafe trait ObjectType:
35    UnsafeFrom<ObjectRef>
36    + Into<ObjectRef>
37    + StaticType
38    + fmt::Debug
39    + Clone
40    + PartialEq
41    + Eq
42    + PartialOrd
43    + Ord
44    + hash::Hash
45    + for<'a> ToGlibPtr<'a, *mut <Self as ObjectType>::GlibType>
46    + 'static
47{
48    /// type of the FFI Instance structure.
49    type GlibType: 'static;
50    /// type of the FFI Class structure.
51    type GlibClassType: 'static;
52    /// type of the Rust Class structure.
53    type RustClassType: 'static;
54
55    fn as_object_ref(&self) -> &ObjectRef;
56    fn as_ptr(&self) -> *mut Self::GlibType;
57}
58
59/// Unsafe variant of the `From` trait.
60pub trait UnsafeFrom<T> {
61    unsafe fn unsafe_from(t: T) -> Self;
62}
63
64/// Declares the "is a" relationship.
65///
66/// `Self` is said to implement `T`.
67///
68/// For instance, since originally `GtkWidget` is a subclass of `GObject` and
69/// implements the `GtkBuildable` interface, `gtk::Widget` implements
70/// `IsA<glib::Object>` and `IsA<gtk::Buildable>`.
71///
72///
73/// The trait can only be implemented if the appropriate `ToGlibPtr`
74/// implementations exist.
75pub unsafe trait IsA<T: ObjectType>: ObjectType + AsRef<T> + 'static {}
76
77/// Trait for mapping a class struct type to its corresponding instance type.
78pub unsafe trait IsClassFor: Sized + 'static {
79    /// Corresponding Rust instance type for this class.
80    type Instance: ObjectType;
81
82    /// Get the type id for this class.
83    fn get_type(&self) -> Type {
84        unsafe {
85            let klass = self as *const _ as *const gobject_sys::GTypeClass;
86            from_glib((*klass).g_type)
87        }
88    }
89
90    /// Casts this class to a reference to a parent type's class.
91    fn upcast_ref<U: IsClassFor>(&self) -> &U
92    where
93        Self::Instance: IsA<U::Instance>,
94        U::Instance: ObjectType,
95    {
96        unsafe {
97            let klass = self as *const _ as *const U;
98            &*klass
99        }
100    }
101
102    /// Casts this class to a mutable reference to a parent type's class.
103    fn upcast_ref_mut<U: IsClassFor>(&mut self) -> &mut U
104    where
105        Self::Instance: IsA<U::Instance>,
106        U::Instance: ObjectType,
107    {
108        unsafe {
109            let klass = self as *mut _ as *mut U;
110            &mut *klass
111        }
112    }
113
114    /// Casts this class to a reference to a child type's class or
115    /// fails if this class is not implementing the child class.
116    fn downcast_ref<U: IsClassFor>(&self) -> Option<&U>
117    where
118        U::Instance: IsA<Self::Instance>,
119        Self::Instance: ObjectType,
120    {
121        if !self.get_type().is_a(&U::Instance::static_type()) {
122            return None;
123        }
124
125        unsafe {
126            let klass = self as *const _ as *const U;
127            Some(&*klass)
128        }
129    }
130
131    /// Casts this class to a mutable reference to a child type's class or
132    /// fails if this class is not implementing the child class.
133    fn downcast_ref_mut<U: IsClassFor>(&mut self) -> Option<&mut U>
134    where
135        U::Instance: IsA<Self::Instance>,
136        Self::Instance: ObjectType,
137    {
138        if !self.get_type().is_a(&U::Instance::static_type()) {
139            return None;
140        }
141
142        unsafe {
143            let klass = self as *mut _ as *mut U;
144            Some(&mut *klass)
145        }
146    }
147
148    /// Gets the class struct corresponding to `type_`.
149    ///
150    /// This will return `None` if `type_` is not a subclass of `Self`.
151    fn from_type(type_: Type) -> Option<ClassRef<Self>> {
152        if !type_.is_a(&Self::Instance::static_type()) {
153            return None;
154        }
155
156        unsafe {
157            let ptr = gobject_sys::g_type_class_ref(type_.to_glib());
158            if ptr.is_null() {
159                None
160            } else {
161                Some(ClassRef(ptr::NonNull::new_unchecked(ptr as *mut Self)))
162            }
163        }
164    }
165}
166
167#[derive(Debug)]
168pub struct ClassRef<T: IsClassFor>(ptr::NonNull<T>);
169
170impl<T: IsClassFor> ops::Deref for ClassRef<T> {
171    type Target = T;
172
173    fn deref(&self) -> &T {
174        unsafe { self.0.as_ref() }
175    }
176}
177
178impl<T: IsClassFor> Drop for ClassRef<T> {
179    fn drop(&mut self) {
180        unsafe {
181            gobject_sys::g_type_class_unref(self.0.as_ptr() as *mut _);
182        }
183    }
184}
185
186/// Upcasting and downcasting support.
187///
188/// Provides conversions up and down the class hierarchy tree.
189pub trait Cast: ObjectType {
190    /// Upcasts an object to a superclass or interface `T`.
191    ///
192    /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
193    /// known at compile-time, whether a specific object implements an interface or not, in which case
194    /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
195    /// is checking the types at runtime.
196    ///
197    /// # Example
198    ///
199    /// ```ignore
200    /// let button = gtk::Button::new();
201    /// let widget = button.upcast::<gtk::Widget>();
202    /// ```
203    #[inline]
204    fn upcast<T: ObjectType>(self) -> T
205    where
206        Self: IsA<T>,
207    {
208        unsafe { self.unsafe_cast() }
209    }
210
211    /// Upcasts an object to a reference of its superclass or interface `T`.
212    ///
213    /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
214    /// known at compile-time, whether a specific object implements an interface or not, in which case
215    /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
216    /// is checking the types at runtime.
217    ///
218    /// # Example
219    ///
220    /// ```ignore
221    /// let button = gtk::Button::new();
222    /// let widget = button.upcast_ref::<gtk::Widget>();
223    /// ```
224    #[inline]
225    fn upcast_ref<T: ObjectType>(&self) -> &T
226    where
227        Self: IsA<T>,
228    {
229        unsafe { self.unsafe_cast_ref() }
230    }
231
232    /// Tries to downcast to a subclass or interface implementor `T`.
233    ///
234    /// Returns `Ok(T)` if the object is an instance of `T` and `Err(self)`
235    /// otherwise.
236    ///
237    /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
238    /// known at compile-time, whether a specific object implements an interface or not, in which case
239    /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
240    /// is checking the types at runtime.
241    ///
242    /// # Example
243    ///
244    /// ```ignore
245    /// let button = gtk::Button::new();
246    /// let widget = button.upcast::<gtk::Widget>();
247    /// assert!(widget.downcast::<gtk::Button>().is_ok());
248    /// ```
249    #[inline]
250    fn downcast<T: ObjectType>(self) -> Result<T, Self>
251    where
252        Self: CanDowncast<T>,
253    {
254        if self.is::<T>() {
255            Ok(unsafe { self.unsafe_cast() })
256        } else {
257            Err(self)
258        }
259    }
260
261    /// Tries to downcast to a reference of its subclass or interface implementor `T`.
262    ///
263    /// Returns `Some(T)` if the object is an instance of `T` and `None`
264    /// otherwise.
265    ///
266    /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
267    /// known at compile-time, whether a specific object implements an interface or not, in which case
268    /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
269    /// is checking the types at runtime.
270    ///
271    /// # Example
272    ///
273    /// ```ignore
274    /// let button = gtk::Button::new();
275    /// let widget = button.upcast::<gtk::Widget>();
276    /// assert!(widget.downcast_ref::<gtk::Button>().is_some());
277    /// ```
278    #[inline]
279    fn downcast_ref<T: ObjectType>(&self) -> Option<&T>
280    where
281        Self: CanDowncast<T>,
282    {
283        if self.is::<T>() {
284            Some(unsafe { self.unsafe_cast_ref() })
285        } else {
286            None
287        }
288    }
289
290    /// Tries to cast to an object of type `T`. This handles upcasting, downcasting
291    /// and casting between interface and interface implementors. All checks are performed at
292    /// runtime, while `downcast` and `upcast` will do many checks at compile-time already.
293    ///
294    /// It is not always known at compile-time, whether a specific object implements an interface or
295    /// not, and checking as to be performed at runtime.
296    ///
297    /// Returns `Ok(T)` if the object is an instance of `T` and `Err(self)`
298    /// otherwise.
299    ///
300    /// # Example
301    ///
302    /// ```ignore
303    /// let button = gtk::Button::new();
304    /// let widget = button.dynamic_cast::<gtk::Widget>();
305    /// assert!(widget.is_ok());
306    /// let widget = widget.unwrap();
307    /// assert!(widget.dynamic_cast::<gtk::Button>().is_ok());
308    /// ```
309    #[inline]
310    fn dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
311        if !self.is::<T>() {
312            Err(self)
313        } else {
314            Ok(unsafe { self.unsafe_cast() })
315        }
316    }
317
318    /// Tries to cast to reference to an object of type `T`. This handles upcasting, downcasting
319    /// and casting between interface and interface implementors. All checks are performed at
320    /// runtime, while `downcast` and `upcast` will do many checks at compile-time already.
321    ///
322    /// It is not always known at compile-time, whether a specific object implements an interface or
323    /// not, and checking as to be performed at runtime.
324    ///
325    /// Returns `Some(T)` if the object is an instance of `T` and `None`
326    /// otherwise.
327    ///
328    /// # Example
329    ///
330    /// ```ignore
331    /// let button = gtk::Button::new();
332    /// let widget = button.dynamic_cast_ref::<gtk::Widget>();
333    /// assert!(widget.is_some());
334    /// let widget = widget.unwrap();
335    /// assert!(widget.dynamic_cast_ref::<gtk::Button>().is_some());
336    /// ```
337    #[inline]
338    fn dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
339        if !self.is::<T>() {
340            None
341        } else {
342            // This transmute is safe because all our wrapper types have the
343            // same representation except for the name and the phantom data
344            // type. IsA<> is an unsafe trait that must only be implemented
345            // if this is a valid wrapper type
346            Some(unsafe { self.unsafe_cast_ref() })
347        }
348    }
349
350    /// Casts to `T` unconditionally.
351    ///
352    /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
353    unsafe fn unsafe_cast<T: ObjectType>(self) -> T {
354        debug_assert!(self.is::<T>());
355        T::unsafe_from(self.into())
356    }
357
358    /// Casts to `&T` unconditionally.
359    ///
360    /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
361    unsafe fn unsafe_cast_ref<T: ObjectType>(&self) -> &T {
362        debug_assert!(self.is::<T>());
363        // This transmute is safe because all our wrapper types have the
364        // same representation except for the name and the phantom data
365        // type. IsA<> is an unsafe trait that must only be implemented
366        // if this is a valid wrapper type
367        &*(self as *const Self as *const T)
368    }
369}
370
371impl<T: ObjectType> Cast for T {}
372
373/// Marker trait for the statically known possibility of downcasting from `Self` to `T`.
374pub trait CanDowncast<T> {}
375
376impl<Super: IsA<Super>, Sub: IsA<Super>> CanDowncast<Sub> for Super {}
377
378glib_wrapper! {
379    #[doc(hidden)]
380    #[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Hash)]
381    pub struct ObjectRef(Shared<GObject>);
382
383    match fn {
384        ref => |ptr| gobject_sys::g_object_ref_sink(ptr),
385        unref => |ptr| gobject_sys::g_object_unref(ptr),
386    }
387}
388
389/// ObjectType implementations for Object types. See `glib_wrapper!`.
390#[macro_export]
391macro_rules! glib_object_wrapper {
392    (@generic_impl [$($attr:meta)*] $name:ident, $ffi_name:path, $ffi_class_name:path, $rust_class_name:path, @get_type $get_type_expr:expr) => {
393        $(#[$attr])*
394        // Always derive Hash/Ord (and below impl Debug, PartialEq, Eq, PartialOrd) for object
395        // types. Due to inheritance and up/downcasting we must implement these by pointer or
396        // otherwise they would potentially give differeny results for the same object depending on
397        // the type we currently know for it
398        #[derive(Clone, Hash, Ord)]
399        pub struct $name($crate::object::ObjectRef, ::std::marker::PhantomData<$ffi_name>);
400
401        #[doc(hidden)]
402        impl Into<$crate::object::ObjectRef> for $name {
403            fn into(self) -> $crate::object::ObjectRef {
404                self.0
405            }
406        }
407
408        #[doc(hidden)]
409        impl $crate::object::UnsafeFrom<$crate::object::ObjectRef> for $name {
410            unsafe fn unsafe_from(t: $crate::object::ObjectRef) -> Self {
411                $name(t, ::std::marker::PhantomData)
412            }
413        }
414
415        #[doc(hidden)]
416        impl $crate::translate::GlibPtrDefault for $name {
417            type GlibType = *mut $ffi_name;
418        }
419
420        #[doc(hidden)]
421        unsafe impl $crate::object::ObjectType for $name {
422            type GlibType = $ffi_name;
423            type GlibClassType = $ffi_class_name;
424            type RustClassType = $rust_class_name;
425
426            fn as_object_ref(&self) -> &$crate::object::ObjectRef {
427                &self.0
428            }
429
430            fn as_ptr(&self) -> *mut Self::GlibType {
431                self.0.to_glib_none().0 as *mut _
432            }
433        }
434
435        #[doc(hidden)]
436        impl AsRef<$crate::object::ObjectRef> for $name {
437            fn as_ref(&self) -> &$crate::object::ObjectRef {
438                &self.0
439            }
440        }
441
442        #[doc(hidden)]
443        impl AsRef<$name> for $name {
444            fn as_ref(&self) -> &$name {
445                self
446            }
447        }
448
449        #[doc(hidden)]
450        unsafe impl $crate::object::IsA<$name> for $name { }
451
452        #[doc(hidden)]
453        impl<'a> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name {
454            type Storage = <$crate::object::ObjectRef as
455                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;
456
457            #[inline]
458            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
459                let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.0);
460                $crate::translate::Stash(stash.0 as *const _, stash.1)
461            }
462
463            #[inline]
464            fn to_glib_full(&self) -> *const $ffi_name {
465                $crate::translate::ToGlibPtr::to_glib_full(&self.0) as *const _
466            }
467        }
468
469        #[doc(hidden)]
470        impl<'a> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name {
471            type Storage = <$crate::object::ObjectRef as
472                $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;
473
474            #[inline]
475            fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
476                let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.0);
477                $crate::translate::Stash(stash.0 as *mut _, stash.1)
478            }
479
480            #[inline]
481            fn to_glib_full(&self) -> *mut $ffi_name {
482                $crate::translate::ToGlibPtr::to_glib_full(&self.0) as *mut _
483            }
484        }
485
486        #[doc(hidden)]
487        impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *mut *mut $ffi_name> for $name {
488            type Storage = (Vec<$crate::translate::Stash<'a, *mut $ffi_name, $name>>, Option<Vec<*mut $ffi_name>>);
489
490            fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut *mut $ffi_name, Self::Storage) {
491                let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
492                let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
493                v_ptr.push(::std::ptr::null_mut() as *mut $ffi_name);
494
495                (v_ptr.as_ptr() as *mut *mut $ffi_name, (v, Some(v_ptr)))
496            }
497
498            fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut *mut $ffi_name, Self::Storage) {
499                let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
500
501                let v_ptr = unsafe {
502                    let v_ptr = $crate::glib_sys::g_malloc0(::std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
503
504                    for (i, s) in v.iter().enumerate() {
505                        ::std::ptr::write(v_ptr.add(i), s.0);
506                    }
507
508                    v_ptr
509                };
510
511                (v_ptr, (v, None))
512            }
513
514            fn to_glib_full_from_slice(t: &[$name]) -> *mut *mut $ffi_name {
515                unsafe {
516                    let v_ptr = $crate::glib_sys::g_malloc0(::std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
517
518                    for (i, s) in t.iter().enumerate() {
519                        ::std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
520                    }
521
522                    v_ptr
523                }
524            }
525        }
526
527        #[doc(hidden)]
528        impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *const *mut $ffi_name> for $name {
529            type Storage = (Vec<$crate::translate::Stash<'a, *mut $ffi_name, $name>>, Option<Vec<*mut $ffi_name>>);
530
531            fn to_glib_none_from_slice(t: &'a [$name]) -> (*const *mut $ffi_name, Self::Storage) {
532                let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *mut $ffi_name>::to_glib_none_from_slice(t);
533                (ptr as *const *mut $ffi_name, stash)
534            }
535
536            fn to_glib_container_from_slice(_: &'a [$name]) -> (*const *mut $ffi_name, Self::Storage) {
537                // Can't have consumer free a *const pointer
538                unimplemented!()
539            }
540
541            fn to_glib_full_from_slice(_: &[$name]) -> *const *mut $ffi_name {
542                // Can't have consumer free a *const pointer
543                unimplemented!()
544            }
545        }
546
547        #[doc(hidden)]
548        impl $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name {
549            #[inline]
550            #[allow(clippy::cast_ptr_alignment)]
551            unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
552                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
553                $name($crate::translate::from_glib_none(ptr as *mut _), ::std::marker::PhantomData)
554            }
555        }
556
557        #[doc(hidden)]
558        impl $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name {
559            #[inline]
560            #[allow(clippy::cast_ptr_alignment)]
561            unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
562                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
563                $name($crate::translate::from_glib_none(ptr as *mut _), ::std::marker::PhantomData)
564            }
565        }
566
567        #[doc(hidden)]
568        impl $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name {
569            #[inline]
570            #[allow(clippy::cast_ptr_alignment)]
571            unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
572                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
573                $name($crate::translate::from_glib_full(ptr as *mut _), ::std::marker::PhantomData)
574            }
575        }
576
577        #[doc(hidden)]
578        impl $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name {
579            #[inline]
580            #[allow(clippy::cast_ptr_alignment)]
581            unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> Self {
582                debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
583                $name($crate::translate::from_glib_borrow(ptr as *mut _),
584                      ::std::marker::PhantomData)
585            }
586        }
587
588        #[doc(hidden)]
589        impl $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name {
590            #[inline]
591            #[allow(clippy::cast_ptr_alignment)]
592            unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> Self {
593                $crate::translate::from_glib_borrow(ptr as *mut $ffi_name)
594            }
595        }
596
597        #[doc(hidden)]
598        impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
599            unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
600                if num == 0 || ptr.is_null() {
601                    return Vec::new();
602                }
603
604                let mut res = Vec::with_capacity(num);
605                for i in 0..num {
606                    res.push($crate::translate::from_glib_none(::std::ptr::read(ptr.add(i))));
607                }
608                res
609            }
610
611            unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
612                let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
613                $crate::glib_sys::g_free(ptr as *mut _);
614                res
615            }
616
617            unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
618                if num == 0 || ptr.is_null() {
619                    return Vec::new();
620                }
621
622                let mut res = Vec::with_capacity(num);
623                for i in 0..num {
624                    res.push($crate::translate::from_glib_full(::std::ptr::read(ptr.add(i))));
625                }
626                $crate::glib_sys::g_free(ptr as *mut _);
627                res
628            }
629        }
630
631        #[doc(hidden)]
632        impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
633            unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
634                $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
635            }
636
637            unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
638                $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
639            }
640
641            unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
642                $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
643            }
644        }
645
646        #[doc(hidden)]
647        impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name {
648            unsafe fn from_glib_none_num_as_vec(ptr: *const *mut $ffi_name, num: usize) -> Vec<Self> {
649                $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
650            }
651
652            unsafe fn from_glib_container_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
653                // Can't free a *const
654                unimplemented!()
655            }
656
657            unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
658                // Can't free a *const
659                unimplemented!()
660            }
661        }
662
663        #[doc(hidden)]
664        impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name {
665            unsafe fn from_glib_none_as_vec(ptr: *const *mut $ffi_name) -> Vec<Self> {
666                $crate::translate::FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
667            }
668
669            unsafe fn from_glib_container_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
670                // Can't free a *const
671                unimplemented!()
672            }
673
674            unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
675                // Can't free a *const
676                unimplemented!()
677            }
678        }
679
680        impl $crate::types::StaticType for $name {
681            fn static_type() -> $crate::types::Type {
682                #[allow(unused_unsafe)]
683                unsafe { $crate::translate::from_glib($get_type_expr) }
684            }
685        }
686
687        impl<T: $crate::object::ObjectType> ::std::cmp::PartialEq<T> for $name {
688            #[inline]
689            fn eq(&self, other: &T) -> bool {
690                $crate::translate::ToGlibPtr::to_glib_none(&self.0).0 == $crate::translate::ToGlibPtr::to_glib_none($crate::object::ObjectType::as_object_ref(other)).0
691            }
692        }
693
694        impl ::std::cmp::Eq for $name { }
695
696        impl<T: $crate::object::ObjectType> ::std::cmp::PartialOrd<T> for $name {
697            #[inline]
698            fn partial_cmp(&self, other: &T) -> Option<::std::cmp::Ordering> {
699                $crate::translate::ToGlibPtr::to_glib_none(&self.0).0.partial_cmp(&$crate::translate::ToGlibPtr::to_glib_none($crate::object::ObjectType::as_object_ref(other)).0)
700            }
701        }
702
703        impl ::std::fmt::Debug for $name {
704            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
705                f.debug_struct(stringify!($name))
706                    .field("inner", &self.0)
707                    .field("type", &<$name as $crate::ObjectExt>::get_type(self))
708                    .finish()
709            }
710        }
711
712        #[doc(hidden)]
713        impl<'a> $crate::value::FromValueOptional<'a> for $name {
714            unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
715                let obj = $crate::gobject_sys::g_value_get_object($crate::translate::ToGlibPtr::to_glib_none(value).0);
716
717                // If the object was floating, clear the floating flag. The one and only
718                // reference is still owned by the GValue at this point
719                if !obj.is_null() && $crate::gobject_sys::g_object_is_floating(obj) != $crate::glib_sys::GFALSE {
720                    $crate::gobject_sys::g_object_ref_sink(obj);
721                }
722
723                // And get a new reference to the object to pass to the caller
724                Option::<$name>::from_glib_none(obj as *mut $ffi_name).map(|o| $crate::object::Cast::unsafe_cast(o))
725            }
726        }
727
728        #[doc(hidden)]
729        impl $crate::value::SetValue for $name {
730            #[allow(clippy::cast_ptr_alignment)]
731            unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
732                $crate::gobject_sys::g_value_set_object($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_none(this).0 as *mut $crate::gobject_sys::GObject)
733            }
734        }
735
736        #[doc(hidden)]
737        impl $crate::value::SetValueOptional for $name {
738            #[allow(clippy::cast_ptr_alignment)]
739            unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
740                $crate::gobject_sys::g_value_set_object($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_none(&this).0 as *mut $crate::gobject_sys::GObject)
741            }
742        }
743    };
744
745    (@munch_impls $name:ident, ) => { };
746
747    (@munch_impls $name:ident, $super_name:path) => {
748        unsafe impl $crate::object::IsA<$super_name> for $name { }
749
750        #[doc(hidden)]
751        impl AsRef<$super_name> for $name {
752            fn as_ref(&self) -> &$super_name {
753                $crate::object::Cast::upcast_ref(self)
754            }
755        }
756    };
757
758    (@munch_impls $name:ident, $super_name:path, $($implements:tt)*) => {
759        glib_object_wrapper!(@munch_impls $name, $super_name);
760        glib_object_wrapper!(@munch_impls $name, $($implements)*);
761    };
762
763    // If there is no parent class, i.e. only glib::Object
764    (@munch_first_impl $name:ident, $rust_class_name:ident, ) => {
765        glib_object_wrapper!(@munch_impls $name, );
766
767        impl ::std::ops::Deref for $rust_class_name {
768            type Target = <$crate::object::Object as $crate::object::ObjectType>::RustClassType;
769
770            fn deref(&self) -> &Self::Target {
771                $crate::object::IsClassFor::upcast_ref(self)
772            }
773        }
774
775        impl ::std::ops::DerefMut for $rust_class_name {
776            fn deref_mut(&mut self) -> &mut Self::Target {
777                $crate::object::IsClassFor::upcast_ref_mut(self)
778            }
779        }
780    };
781
782    // If there is only one parent class
783    (@munch_first_impl $name:ident, $rust_class_name:ident, $super_name:path) => {
784        glib_object_wrapper!(@munch_impls $name, $super_name);
785
786        impl ::std::ops::Deref for $rust_class_name {
787            type Target = <$super_name as $crate::object::ObjectType>::RustClassType;
788
789            fn deref(&self) -> &Self::Target {
790                $crate::object::IsClassFor::upcast_ref(self)
791            }
792        }
793
794        impl ::std::ops::DerefMut for $rust_class_name {
795            fn deref_mut(&mut self) -> &mut Self::Target {
796                $crate::object::IsClassFor::upcast_ref_mut(self)
797            }
798        }
799    };
800
801    // If there is more than one parent class
802    (@munch_first_impl $name:ident, $rust_class_name:ident, $super_name:path, $($implements:tt)*) => {
803        glib_object_wrapper!(@munch_impls $name, $super_name);
804
805        impl ::std::ops::Deref for $rust_class_name {
806            type Target = <$super_name as $crate::object::ObjectType>::RustClassType;
807
808            fn deref(&self) -> &Self::Target {
809                $crate::object::IsClassFor::upcast_ref(self)
810            }
811        }
812
813        impl ::std::ops::DerefMut for $rust_class_name {
814            fn deref_mut(&mut self) -> &mut Self::Target {
815                $crate::object::IsClassFor::upcast_ref_mut(self)
816            }
817        }
818
819        glib_object_wrapper!(@munch_impls $name, $($implements)*);
820    };
821
822    (@class_impl $name:ident, $ffi_class_name:path, $rust_class_name:ident) => {
823        #[repr(C)]
824        pub struct $rust_class_name($ffi_class_name);
825
826        unsafe impl $crate::object::IsClassFor for $rust_class_name {
827            type Instance = $name;
828        }
829
830        unsafe impl Send for $rust_class_name { }
831        unsafe impl Sync for $rust_class_name { }
832    };
833
834    // This case is only for glib::Object itself below. All other cases have glib::Object in its
835    // parent class list
836    (@object [$($attr:meta)*] $name:ident, $ffi_name:path, $ffi_class_name:path, $rust_class_name:ident, @get_type $get_type_expr:expr) => {
837        glib_object_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name, $ffi_class_name, $rust_class_name,
838            @get_type $get_type_expr);
839        glib_object_wrapper!(@class_impl $name, $ffi_class_name, $rust_class_name);
840    };
841
842    (@object [$($attr:meta)*] $name:ident, $ffi_name:path, $ffi_class_name:path, $rust_class_name:ident,
843        @get_type $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
844        glib_object_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name, $ffi_class_name, $rust_class_name,
845            @get_type $get_type_expr);
846        glib_object_wrapper!(@munch_first_impl $name, $rust_class_name, $($extends)*);
847        glib_object_wrapper!(@munch_impls $name, $($implements)*);
848        glib_object_wrapper!(@class_impl $name, $ffi_class_name, $rust_class_name);
849
850        #[doc(hidden)]
851        impl AsRef<$crate::object::Object> for $name {
852            fn as_ref(&self) -> &$crate::object::Object {
853                $crate::object::Cast::upcast_ref(self)
854            }
855        }
856
857        #[doc(hidden)]
858        unsafe impl $crate::object::IsA<$crate::object::Object> for $name { }
859    };
860
861    (@interface [$($attr:meta)*] $name:ident, $ffi_name:path, @get_type $get_type_expr:expr, @requires [$($requires:tt)*]) => {
862        glib_object_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name, $crate::wrapper::Void, $crate::wrapper::Void,
863            @get_type $get_type_expr);
864        glib_object_wrapper!(@munch_impls $name, $($requires)*);
865
866        #[doc(hidden)]
867        impl AsRef<$crate::object::Object> for $name {
868            fn as_ref(&self) -> &$crate::object::Object {
869                $crate::object::Cast::upcast_ref(self)
870            }
871        }
872
873        #[doc(hidden)]
874        unsafe impl $crate::object::IsA<$crate::object::Object> for $name { }
875    };
876}
877
878glib_object_wrapper!(@object
879    [doc = "The base class in the object hierarchy."]
880    Object, GObject, GObjectClass, ObjectClass, @get_type gobject_sys::g_object_get_type()
881);
882
883impl Object {
884    pub fn new(type_: Type, properties: &[(&str, &dyn ToValue)]) -> Result<Object, BoolError> {
885        use std::ffi::CString;
886
887        if !type_.is_a(&Object::static_type()) {
888            return Err(glib_bool_error!("Can't instantiate non-GObject objects"));
889        }
890
891        let params = properties
892            .iter()
893            .map(|&(name, value)| (CString::new(name).unwrap(), value.to_value()))
894            .collect::<Vec<_>>();
895
896        let params_c = params
897            .iter()
898            .map(|&(ref name, ref value)| gobject_sys::GParameter {
899                name: name.as_ptr(),
900                value: unsafe { *value.to_glib_none().0 },
901            })
902            .collect::<Vec<_>>();
903
904        unsafe {
905            let ptr = gobject_sys::g_object_newv(
906                type_.to_glib(),
907                params_c.len() as u32,
908                mut_override(params_c.as_ptr()),
909            );
910            if ptr.is_null() {
911                Err(glib_bool_error!("Can't instantiate object"))
912            } else if type_.is_a(&InitiallyUnowned::static_type()) {
913                Ok(from_glib_none(ptr))
914            } else {
915                Ok(from_glib_full(ptr))
916            }
917        }
918    }
919}
920
921pub trait ObjectExt: ObjectType {
922    /// Returns `true` if the object is an instance of (can be cast to) `T`.
923    fn is<T: StaticType>(&self) -> bool;
924
925    fn get_type(&self) -> Type;
926    fn get_object_class(&self) -> &ObjectClass;
927
928    fn set_property<'a, N: Into<&'a str>>(
929        &self,
930        property_name: N,
931        value: &dyn ToValue,
932    ) -> Result<(), BoolError>;
933    fn get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError>;
934    fn has_property<'a, N: Into<&'a str>>(
935        &self,
936        property_name: N,
937        type_: Option<Type>,
938    ) -> Result<(), BoolError>;
939    fn get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type>;
940    fn find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec>;
941    fn list_properties(&self) -> Vec<::ParamSpec>;
942
943    fn block_signal(&self, handler_id: &SignalHandlerId);
944    fn unblock_signal(&self, handler_id: &SignalHandlerId);
945    fn stop_signal_emission(&self, signal_name: &str);
946
947    fn connect<'a, N, F>(
948        &self,
949        signal_name: N,
950        after: bool,
951        callback: F,
952    ) -> Result<SignalHandlerId, BoolError>
953    where
954        N: Into<&'a str>,
955        F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
956    unsafe fn connect_unsafe<'a, N, F>(
957        &self,
958        signal_name: N,
959        after: bool,
960        callback: F,
961    ) -> Result<SignalHandlerId, BoolError>
962    where
963        N: Into<&'a str>,
964        F: Fn(&[Value]) -> Option<Value>;
965    fn emit<'a, N: Into<&'a str>>(
966        &self,
967        signal_name: N,
968        args: &[&dyn ToValue],
969    ) -> Result<Option<Value>, BoolError>;
970    fn disconnect(&self, handler_id: SignalHandlerId);
971
972    fn connect_notify<F: Fn(&Self, &::ParamSpec) + Send + Sync + 'static>(
973        &self,
974        name: Option<&str>,
975        f: F,
976    ) -> SignalHandlerId;
977    unsafe fn connect_notify_unsafe<F: Fn(&Self, &::ParamSpec)>(
978        &self,
979        name: Option<&str>,
980        f: F,
981    ) -> SignalHandlerId;
982    fn notify<'a, N: Into<&'a str>>(&self, property_name: N);
983    fn notify_by_pspec(&self, pspec: &::ParamSpec);
984
985    fn downgrade(&self) -> WeakRef<Self>;
986
987    fn bind_property<'a, O: ObjectType, N: Into<&'a str>, M: Into<&'a str>>(
988        &'a self,
989        source_property: N,
990        target: &'a O,
991        target_property: M,
992    ) -> BindingBuilder<'a>;
993
994    fn ref_count(&self) -> u32;
995}
996
997impl<T: ObjectType> ObjectExt for T {
998    fn is<U: StaticType>(&self) -> bool {
999        self.get_type().is_a(&U::static_type())
1000    }
1001
1002    fn get_type(&self) -> Type {
1003        self.get_object_class().get_type()
1004    }
1005
1006    fn get_object_class(&self) -> &ObjectClass {
1007        unsafe {
1008            let obj: *mut gobject_sys::GObject = self.as_object_ref().to_glib_none().0;
1009            let klass = (*obj).g_type_instance.g_class as *const ObjectClass;
1010            &*klass
1011        }
1012    }
1013
1014    fn set_property<'a, N: Into<&'a str>>(
1015        &self,
1016        property_name: N,
1017        value: &dyn ToValue,
1018    ) -> Result<(), BoolError> {
1019        let property_name = property_name.into();
1020        let mut property_value = value.to_value();
1021
1022        let pspec = match self.find_property(property_name) {
1023            Some(pspec) => pspec,
1024            None => {
1025                return Err(glib_bool_error!("property not found"));
1026            }
1027        };
1028
1029        if !pspec.get_flags().contains(::ParamFlags::WRITABLE)
1030            || pspec.get_flags().contains(::ParamFlags::CONSTRUCT_ONLY)
1031        {
1032            return Err(glib_bool_error!("property is not writable"));
1033        }
1034
1035        unsafe {
1036            // While GLib actually allows all types that can somehow be transformed
1037            // into the property type, we're more restrictive here to be consistent
1038            // with Rust's type rules. We only allow the exact same type, or if the
1039            // value type is a subtype of the property type
1040            let valid_type: bool = from_glib(gobject_sys::g_type_check_value_holds(
1041                mut_override(property_value.to_glib_none().0),
1042                pspec.get_value_type().to_glib(),
1043            ));
1044
1045            // If it's not directly a valid type but an object type, we check if the
1046            // actual type of the contained object is compatible and if so create
1047            // a properly type Value. This can happen if the type field in the
1048            // Value is set to a more generic type than the contained value
1049            if !valid_type && property_value.type_().is_a(&Object::static_type()) {
1050                if let Some(obj) = property_value.get::<Object>() {
1051                    if obj.get_type().is_a(&pspec.get_value_type()) {
1052                        property_value.0.g_type = pspec.get_value_type().to_glib();
1053                    } else {
1054                        return Err(glib_bool_error!(
1055                            "property can't be set from the given object type"
1056                        ));
1057                    }
1058                } else {
1059                    // Otherwise if the value is None then the type is compatible too
1060                    property_value.0.g_type = pspec.get_value_type().to_glib();
1061                }
1062            } else if !valid_type {
1063                return Err(glib_bool_error!(
1064                    "property can't be set from the given type"
1065                ));
1066            }
1067
1068            let changed: bool = from_glib(gobject_sys::g_param_value_validate(
1069                pspec.to_glib_none().0,
1070                property_value.to_glib_none_mut().0,
1071            ));
1072            let change_allowed = pspec.get_flags().contains(::ParamFlags::LAX_VALIDATION);
1073            if changed && !change_allowed {
1074                return Err(glib_bool_error!(
1075                    "property can't be set from given value, it is invalid or out of range"
1076                ));
1077            }
1078
1079            gobject_sys::g_object_set_property(
1080                self.as_object_ref().to_glib_none().0,
1081                property_name.to_glib_none().0,
1082                property_value.to_glib_none().0,
1083            );
1084        }
1085
1086        Ok(())
1087    }
1088
1089    fn get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError> {
1090        let property_name = property_name.into();
1091
1092        let pspec = match self.find_property(property_name) {
1093            Some(pspec) => pspec,
1094            None => {
1095                return Err(glib_bool_error!("property not found"));
1096            }
1097        };
1098
1099        if !pspec.get_flags().contains(::ParamFlags::READABLE) {
1100            return Err(glib_bool_error!("property is not readable"));
1101        }
1102
1103        unsafe {
1104            let mut value = Value::from_type(pspec.get_value_type());
1105            gobject_sys::g_object_get_property(
1106                self.as_object_ref().to_glib_none().0,
1107                property_name.to_glib_none().0,
1108                value.to_glib_none_mut().0,
1109            );
1110
1111            // This can't really happen unless something goes wrong inside GObject
1112            if value.type_() == ::Type::Invalid {
1113                Err(glib_bool_error!("Failed to get property value"))
1114            } else {
1115                Ok(value)
1116            }
1117        }
1118    }
1119
1120    fn block_signal(&self, handler_id: &SignalHandlerId) {
1121        unsafe {
1122            gobject_sys::g_signal_handler_block(
1123                self.as_object_ref().to_glib_none().0,
1124                handler_id.to_glib(),
1125            );
1126        }
1127    }
1128
1129    fn unblock_signal(&self, handler_id: &SignalHandlerId) {
1130        unsafe {
1131            gobject_sys::g_signal_handler_unblock(
1132                self.as_object_ref().to_glib_none().0,
1133                handler_id.to_glib(),
1134            );
1135        }
1136    }
1137
1138    fn stop_signal_emission(&self, signal_name: &str) {
1139        unsafe {
1140            gobject_sys::g_signal_stop_emission_by_name(
1141                self.as_object_ref().to_glib_none().0,
1142                signal_name.to_glib_none().0,
1143            );
1144        }
1145    }
1146
1147    fn disconnect(&self, handler_id: SignalHandlerId) {
1148        unsafe {
1149            gobject_sys::g_signal_handler_disconnect(
1150                self.as_object_ref().to_glib_none().0,
1151                handler_id.to_glib(),
1152            );
1153        }
1154    }
1155
1156    fn connect_notify<F: Fn(&Self, &::ParamSpec) + Send + Sync + 'static>(
1157        &self,
1158        name: Option<&str>,
1159        f: F,
1160    ) -> SignalHandlerId {
1161        unsafe { self.connect_notify_unsafe(name, f) }
1162    }
1163
1164    unsafe fn connect_notify_unsafe<F: Fn(&Self, &::ParamSpec)>(
1165        &self,
1166        name: Option<&str>,
1167        f: F,
1168    ) -> SignalHandlerId {
1169        unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &::ParamSpec)>(
1170            this: *mut gobject_sys::GObject,
1171            param_spec: *mut gobject_sys::GParamSpec,
1172            f: glib_sys::gpointer,
1173        ) where
1174            P: ObjectType,
1175        {
1176            let f: &F = &*(f as *const F);
1177            f(
1178                &Object::from_glib_borrow(this).unsafe_cast(),
1179                &from_glib_borrow(param_spec),
1180            )
1181        }
1182
1183        let signal_name = if let Some(name) = name {
1184            format!("notify::{}\0", name)
1185        } else {
1186            "notify\0".into()
1187        };
1188
1189        let f: Box<F> = Box::new(f);
1190        ::signal::connect_raw(
1191            self.as_object_ref().to_glib_none().0,
1192            signal_name.as_ptr() as *const _,
1193            Some(mem::transmute(notify_trampoline::<Self, F> as usize)),
1194            Box::into_raw(f),
1195        )
1196    }
1197
1198    fn notify<'a, N: Into<&'a str>>(&self, property_name: N) {
1199        let property_name = property_name.into();
1200
1201        unsafe {
1202            gobject_sys::g_object_notify(
1203                self.as_object_ref().to_glib_none().0,
1204                property_name.to_glib_none().0,
1205            );
1206        }
1207    }
1208
1209    fn notify_by_pspec(&self, pspec: &::ParamSpec) {
1210        unsafe {
1211            gobject_sys::g_object_notify_by_pspec(
1212                self.as_object_ref().to_glib_none().0,
1213                pspec.to_glib_none().0,
1214            );
1215        }
1216    }
1217
1218    fn has_property<'a, N: Into<&'a str>>(
1219        &self,
1220        property_name: N,
1221        type_: Option<Type>,
1222    ) -> Result<(), BoolError> {
1223        self.get_object_class().has_property(property_name, type_)
1224    }
1225
1226    fn get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type> {
1227        self.get_object_class().get_property_type(property_name)
1228    }
1229
1230    fn find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec> {
1231        self.get_object_class().find_property(property_name)
1232    }
1233
1234    fn list_properties(&self) -> Vec<::ParamSpec> {
1235        self.get_object_class().list_properties()
1236    }
1237
1238    fn connect<'a, N, F>(
1239        &self,
1240        signal_name: N,
1241        after: bool,
1242        callback: F,
1243    ) -> Result<SignalHandlerId, BoolError>
1244    where
1245        N: Into<&'a str>,
1246        F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
1247    {
1248        unsafe { self.connect_unsafe(signal_name, after, callback) }
1249    }
1250
1251    unsafe fn connect_unsafe<'a, N, F>(
1252        &self,
1253        signal_name: N,
1254        after: bool,
1255        callback: F,
1256    ) -> Result<SignalHandlerId, BoolError>
1257    where
1258        N: Into<&'a str>,
1259        F: Fn(&[Value]) -> Option<Value>,
1260    {
1261        let signal_name: &str = signal_name.into();
1262
1263        let type_ = self.get_type();
1264
1265        let mut signal_id = 0;
1266        let mut signal_detail = 0;
1267
1268        let found: bool = from_glib(gobject_sys::g_signal_parse_name(
1269            signal_name.to_glib_none().0,
1270            type_.to_glib(),
1271            &mut signal_id,
1272            &mut signal_detail,
1273            true.to_glib(),
1274        ));
1275
1276        if !found {
1277            return Err(glib_bool_error!("Signal not found"));
1278        }
1279
1280        let mut details = mem::zeroed();
1281        gobject_sys::g_signal_query(signal_id, &mut details);
1282        if details.signal_id != signal_id {
1283            return Err(glib_bool_error!("Signal not found"));
1284        }
1285
1286        // This is actually G_SIGNAL_TYPE_STATIC_SCOPE
1287        let return_type: Type =
1288            from_glib(details.return_type & (!gobject_sys::G_TYPE_FLAG_RESERVED_ID_BIT));
1289        let closure = Closure::new_unsafe(move |values| {
1290            let ret = callback(values);
1291
1292            if return_type == Type::Unit {
1293                if let Some(ret) = ret {
1294                    panic!(
1295                        "Signal required no return value but got value of type {}",
1296                        ret.type_().name()
1297                    );
1298                }
1299                None
1300            } else {
1301                match ret {
1302                    Some(mut ret) => {
1303                        let valid_type: bool = from_glib(gobject_sys::g_type_check_value_holds(
1304                            mut_override(ret.to_glib_none().0),
1305                            return_type.to_glib(),
1306                        ));
1307
1308                        // If it's not directly a valid type but an object type, we check if the
1309                        // actual typed of the contained object is compatible and if so create
1310                        // a properly typed Value. This can happen if the type field in the
1311                        // Value is set to a more generic type than the contained value
1312                        if !valid_type && ret.type_().is_a(&Object::static_type()) {
1313                            if let Some(obj) = ret.get::<Object>() {
1314                                if obj.get_type().is_a(&return_type) {
1315                                    ret.0.g_type = return_type.to_glib();
1316                                } else {
1317                                    panic!("Signal required return value of type {} but got {} (actual {})",
1318                                       return_type.name(), ret.type_().name(), obj.get_type().name());
1319                                }
1320                            } else {
1321                                // Otherwise if the value is None then the type is compatible too
1322                                ret.0.g_type = return_type.to_glib();
1323                            }
1324                        } else if !valid_type {
1325                            panic!(
1326                                "Signal required return value of type {} but got {}",
1327                                return_type.name(),
1328                                ret.type_().name()
1329                            );
1330                        }
1331                        Some(ret)
1332                    }
1333                    None => {
1334                        panic!(
1335                            "Signal required return value of type {} but got None",
1336                            return_type.name()
1337                        );
1338                    }
1339                }
1340            }
1341        });
1342        let handler = gobject_sys::g_signal_connect_closure_by_id(
1343            self.as_object_ref().to_glib_none().0,
1344            signal_id,
1345            signal_detail,
1346            closure.to_glib_none().0,
1347            after.to_glib(),
1348        );
1349
1350        if handler == 0 {
1351            Err(glib_bool_error!("Failed to connect to signal"))
1352        } else {
1353            Ok(from_glib(handler))
1354        }
1355    }
1356
1357    fn emit<'a, N: Into<&'a str>>(
1358        &self,
1359        signal_name: N,
1360        args: &[&dyn ToValue],
1361    ) -> Result<Option<Value>, BoolError> {
1362        let signal_name: &str = signal_name.into();
1363        unsafe {
1364            let type_ = self.get_type();
1365
1366            let mut signal_id = 0;
1367            let mut signal_detail = 0;
1368
1369            let found: bool = from_glib(gobject_sys::g_signal_parse_name(
1370                signal_name.to_glib_none().0,
1371                type_.to_glib(),
1372                &mut signal_id,
1373                &mut signal_detail,
1374                true.to_glib(),
1375            ));
1376
1377            if !found {
1378                return Err(glib_bool_error!("Signal not found"));
1379            }
1380
1381            let mut details = mem::zeroed();
1382            gobject_sys::g_signal_query(signal_id, &mut details);
1383            if details.signal_id != signal_id {
1384                return Err(glib_bool_error!("Signal not found"));
1385            }
1386
1387            if details.n_params != args.len() as u32 {
1388                return Err(glib_bool_error!("Incompatible number of arguments"));
1389            }
1390
1391            for (i, item) in args.iter().enumerate() {
1392                let arg_type =
1393                    *(details.param_types.add(i)) & (!gobject_sys::G_TYPE_FLAG_RESERVED_ID_BIT);
1394                if arg_type != item.to_value_type().to_glib() {
1395                    return Err(glib_bool_error!("Incompatible argument types"));
1396                }
1397            }
1398
1399            let mut v_args: Vec<Value>;
1400            let mut s_args: [Value; 10] = mem::zeroed();
1401            let self_v = {
1402                let mut v = Value::uninitialized();
1403                gobject_sys::g_value_init(v.to_glib_none_mut().0, self.get_type().to_glib());
1404                gobject_sys::g_value_set_object(
1405                    v.to_glib_none_mut().0,
1406                    self.as_object_ref().to_glib_none().0,
1407                );
1408                v
1409            };
1410            let args = if args.len() < 10 {
1411                s_args[0] = self_v;
1412                for (i, arg) in args.iter().enumerate() {
1413                    s_args[i + 1] = arg.to_value();
1414                }
1415                &s_args[0..=args.len()]
1416            } else {
1417                v_args = Vec::with_capacity(args.len() + 1);
1418                v_args.push(self_v);
1419                for arg in args {
1420                    v_args.push(arg.to_value());
1421                }
1422                v_args.as_slice()
1423            };
1424
1425            let mut return_value = Value::uninitialized();
1426            if details.return_type != gobject_sys::G_TYPE_NONE {
1427                gobject_sys::g_value_init(return_value.to_glib_none_mut().0, details.return_type);
1428            }
1429
1430            gobject_sys::g_signal_emitv(
1431                mut_override(args.as_ptr()) as *mut gobject_sys::GValue,
1432                signal_id,
1433                signal_detail,
1434                return_value.to_glib_none_mut().0,
1435            );
1436
1437            if return_value.type_() != Type::Unit && return_value.type_() != Type::Invalid {
1438                Ok(Some(return_value))
1439            } else {
1440                Ok(None)
1441            }
1442        }
1443    }
1444
1445    fn downgrade(&self) -> WeakRef<T> {
1446        unsafe {
1447            let w = WeakRef(Box::new(mem::uninitialized()), PhantomData);
1448            gobject_sys::g_weak_ref_init(
1449                mut_override(&*w.0),
1450                self.as_object_ref().to_glib_none().0,
1451            );
1452            w
1453        }
1454    }
1455
1456    fn bind_property<'a, O: ObjectType, N: Into<&'a str>, M: Into<&'a str>>(
1457        &'a self,
1458        source_property: N,
1459        target: &'a O,
1460        target_property: M,
1461    ) -> BindingBuilder<'a> {
1462        let source_property = source_property.into();
1463        let target_property = target_property.into();
1464
1465        BindingBuilder::new(self, source_property, target, target_property)
1466    }
1467
1468    fn ref_count(&self) -> u32 {
1469        let stash = self.as_object_ref().to_glib_none();
1470        let ptr: *mut gobject_sys::GObject = stash.0;
1471
1472        unsafe { glib_sys::g_atomic_int_get(&(*ptr).ref_count as *const u32 as *const i32) as u32 }
1473    }
1474}
1475
1476impl ObjectClass {
1477    pub fn has_property<'a, N: Into<&'a str>>(
1478        &self,
1479        property_name: N,
1480        type_: Option<Type>,
1481    ) -> Result<(), BoolError> {
1482        let property_name = property_name.into();
1483        let ptype = self.get_property_type(property_name);
1484
1485        match (ptype, type_) {
1486            (None, _) => Err(glib_bool_error!("Invalid property name")),
1487            (Some(_), None) => Ok(()),
1488            (Some(ptype), Some(type_)) => {
1489                if ptype == type_ {
1490                    Ok(())
1491                } else {
1492                    Err(glib_bool_error!("Invalid property type"))
1493                }
1494            }
1495        }
1496    }
1497
1498    pub fn get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type> {
1499        self.find_property(property_name)
1500            .map(|pspec| pspec.get_value_type())
1501    }
1502
1503    pub fn find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec> {
1504        let property_name = property_name.into();
1505        unsafe {
1506            let klass = self as *const _ as *const gobject_sys::GObjectClass;
1507
1508            from_glib_none(gobject_sys::g_object_class_find_property(
1509                klass as *mut _,
1510                property_name.to_glib_none().0,
1511            ))
1512        }
1513    }
1514
1515    pub fn list_properties(&self) -> Vec<::ParamSpec> {
1516        unsafe {
1517            let klass = self as *const _ as *const gobject_sys::GObjectClass;
1518
1519            let mut n_properties = 0;
1520
1521            let props =
1522                gobject_sys::g_object_class_list_properties(klass as *mut _, &mut n_properties);
1523            FromGlibContainer::from_glib_none_num(props, n_properties as usize)
1524        }
1525    }
1526}
1527
1528glib_wrapper! {
1529    pub struct InitiallyUnowned(Object<gobject_sys::GInitiallyUnowned, gobject_sys::GInitiallyUnownedClass, InitiallyUnownedClass>);
1530
1531    match fn {
1532        get_type => || gobject_sys::g_initially_unowned_get_type(),
1533    }
1534}
1535
1536pub struct WeakRef<T: ObjectType>(Box<gobject_sys::GWeakRef>, PhantomData<*const T>);
1537
1538impl<T: ObjectType> WeakRef<T> {
1539    pub fn new() -> WeakRef<T> {
1540        unsafe {
1541            let w = WeakRef(Box::new(mem::uninitialized()), PhantomData);
1542            gobject_sys::g_weak_ref_init(mut_override(&*w.0), ptr::null_mut());
1543            w
1544        }
1545    }
1546
1547    pub fn upgrade(&self) -> Option<T> {
1548        unsafe {
1549            let ptr = gobject_sys::g_weak_ref_get(mut_override(&*self.0));
1550            if ptr.is_null() {
1551                None
1552            } else {
1553                let obj: Object = from_glib_full(ptr);
1554                Some(T::unsafe_from(obj.into()))
1555            }
1556        }
1557    }
1558}
1559
1560impl<T: ObjectType> Drop for WeakRef<T> {
1561    fn drop(&mut self) {
1562        unsafe {
1563            gobject_sys::g_weak_ref_clear(mut_override(&*self.0));
1564        }
1565    }
1566}
1567
1568impl<T: ObjectType> Clone for WeakRef<T> {
1569    fn clone(&self) -> Self {
1570        unsafe {
1571            let c = WeakRef(Box::new(mem::uninitialized()), PhantomData);
1572
1573            let o = gobject_sys::g_weak_ref_get(mut_override(&*self.0));
1574            gobject_sys::g_weak_ref_init(mut_override(&*c.0), o);
1575            if !o.is_null() {
1576                gobject_sys::g_object_unref(o);
1577            }
1578
1579            c
1580        }
1581    }
1582}
1583
1584impl<T: ObjectType> Default for WeakRef<T> {
1585    fn default() -> Self {
1586        Self::new()
1587    }
1588}
1589
1590unsafe impl<T: ObjectType + Sync + Sync> Sync for WeakRef<T> {}
1591unsafe impl<T: ObjectType + Send + Sync> Send for WeakRef<T> {}
1592
1593/// A weak reference to the object it was created for that can be sent to
1594/// different threads even for object types that don't implement `Send`.
1595///
1596/// Trying to upgrade the weak reference from another thread than the one
1597/// where it was created on will panic but dropping or cloning can be done
1598/// safely from any thread.
1599pub struct SendWeakRef<T: ObjectType>(WeakRef<T>, Option<usize>);
1600
1601impl<T: ObjectType> SendWeakRef<T> {
1602    pub fn new() -> SendWeakRef<T> {
1603        SendWeakRef(WeakRef::new(), None)
1604    }
1605
1606    pub fn into_weak_ref(self) -> WeakRef<T> {
1607        if self.1.is_some() && self.1 != Some(get_thread_id()) {
1608            panic!("SendWeakRef dereferenced on a different thread");
1609        }
1610
1611        self.0
1612    }
1613}
1614
1615impl<T: ObjectType> ops::Deref for SendWeakRef<T> {
1616    type Target = WeakRef<T>;
1617
1618    fn deref(&self) -> &WeakRef<T> {
1619        if self.1.is_some() && self.1 != Some(get_thread_id()) {
1620            panic!("SendWeakRef dereferenced on a different thread");
1621        }
1622
1623        &self.0
1624    }
1625}
1626
1627// Deriving this gives the wrong trait bounds
1628impl<T: ObjectType> Clone for SendWeakRef<T> {
1629    fn clone(&self) -> Self {
1630        SendWeakRef(self.0.clone(), self.1)
1631    }
1632}
1633
1634impl<T: ObjectType> Default for SendWeakRef<T> {
1635    fn default() -> Self {
1636        Self::new()
1637    }
1638}
1639
1640impl<T: ObjectType> From<WeakRef<T>> for SendWeakRef<T> {
1641    fn from(v: WeakRef<T>) -> SendWeakRef<T> {
1642        SendWeakRef(v, Some(get_thread_id()))
1643    }
1644}
1645
1646unsafe impl<T: ObjectType> Sync for SendWeakRef<T> {}
1647unsafe impl<T: ObjectType> Send for SendWeakRef<T> {}
1648
1649pub struct BindingBuilder<'a> {
1650    source: &'a ObjectRef,
1651    source_property: &'a str,
1652    target: &'a ObjectRef,
1653    target_property: &'a str,
1654    flags: ::BindingFlags,
1655    transform_to: Option<::Closure>,
1656    transform_from: Option<::Closure>,
1657}
1658
1659impl<'a> BindingBuilder<'a> {
1660    fn new<S: ObjectType, T: ObjectType>(
1661        source: &'a S,
1662        source_property: &'a str,
1663        target: &'a T,
1664        target_property: &'a str,
1665    ) -> Self {
1666        Self {
1667            source: source.as_object_ref(),
1668            source_property,
1669            target: target.as_object_ref(),
1670            target_property,
1671            flags: ::BindingFlags::DEFAULT,
1672            transform_to: None,
1673            transform_from: None,
1674        }
1675    }
1676
1677    fn transform_closure<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>(
1678        func: F,
1679    ) -> ::Closure {
1680        ::Closure::new(move |values| {
1681            assert_eq!(values.len(), 3);
1682            let binding = values[0].get::<::Binding>().unwrap();
1683            let from = unsafe {
1684                let ptr = gobject_sys::g_value_get_boxed(mut_override(
1685                    &values[1] as *const Value as *const gobject_sys::GValue,
1686                ));
1687                assert!(!ptr.is_null());
1688                &*(ptr as *const gobject_sys::GValue as *const Value)
1689            };
1690
1691            match func(&binding, &from) {
1692                None => Some(false.to_value()),
1693                Some(value) => {
1694                    unsafe {
1695                        gobject_sys::g_value_set_boxed(
1696                            mut_override(&values[2] as *const Value as *const gobject_sys::GValue),
1697                            &value as *const Value as *const _,
1698                        );
1699                    }
1700
1701                    Some(true.to_value())
1702                }
1703            }
1704        })
1705    }
1706
1707    pub fn transform_from<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>(
1708        self,
1709        func: F,
1710    ) -> Self {
1711        Self {
1712            transform_from: Some(Self::transform_closure(func)),
1713            ..self
1714        }
1715    }
1716
1717    pub fn transform_to<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>(
1718        self,
1719        func: F,
1720    ) -> Self {
1721        Self {
1722            transform_to: Some(Self::transform_closure(func)),
1723            ..self
1724        }
1725    }
1726
1727    pub fn flags(self, flags: ::BindingFlags) -> Self {
1728        Self { flags, ..self }
1729    }
1730
1731    pub fn build(self) -> Option<::Binding> {
1732        unsafe {
1733            from_glib_none(gobject_sys::g_object_bind_property_with_closures(
1734                self.source.to_glib_none().0,
1735                self.source_property.to_glib_none().0,
1736                self.target.to_glib_none().0,
1737                self.target_property.to_glib_none().0,
1738                self.flags.to_glib(),
1739                self.transform_to.to_glib_none().0,
1740                self.transform_from.to_glib_none().0,
1741            ))
1742        }
1743    }
1744}