1use 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
33pub 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 GlibType: 'static;
50 type GlibClassType: 'static;
52 type RustClassType: 'static;
54
55 fn as_object_ref(&self) -> &ObjectRef;
56 fn as_ptr(&self) -> *mut Self::GlibType;
57}
58
59pub trait UnsafeFrom<T> {
61 unsafe fn unsafe_from(t: T) -> Self;
62}
63
64pub unsafe trait IsA<T: ObjectType>: ObjectType + AsRef<T> + 'static {}
76
77pub unsafe trait IsClassFor: Sized + 'static {
79 type Instance: ObjectType;
81
82 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 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 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 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 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 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
186pub trait Cast: ObjectType {
190 #[inline]
204 fn upcast<T: ObjectType>(self) -> T
205 where
206 Self: IsA<T>,
207 {
208 unsafe { self.unsafe_cast() }
209 }
210
211 #[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 #[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 #[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 #[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 #[inline]
338 fn dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
339 if !self.is::<T>() {
340 None
341 } else {
342 Some(unsafe { self.unsafe_cast_ref() })
347 }
348 }
349
350 unsafe fn unsafe_cast<T: ObjectType>(self) -> T {
354 debug_assert!(self.is::<T>());
355 T::unsafe_from(self.into())
356 }
357
358 unsafe fn unsafe_cast_ref<T: ObjectType>(&self) -> &T {
362 debug_assert!(self.is::<T>());
363 &*(self as *const Self as *const T)
368 }
369}
370
371impl<T: ObjectType> Cast for T {}
372
373pub 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#[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 #[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 unimplemented!()
539 }
540
541 fn to_glib_full_from_slice(_: &[$name]) -> *const *mut $ffi_name {
542 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 unimplemented!()
655 }
656
657 unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
658 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 unimplemented!()
672 }
673
674 unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
675 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 !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 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 (@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 (@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 (@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 (@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 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 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 !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 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 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 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 !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 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
1593pub 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
1627impl<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}