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
7 use glib_sys;
8 use gobject_sys;
9 use quark::Quark;
10 use std::cmp;
11 use std::fmt;
12 use std::hash;
13 use std::marker::PhantomData;
14 use std::mem;
15 use std::ops;
16 use std::ptr;
17 use translate::*;
18 use types::StaticType;
19
20 use value::ToValue;
21 use BoolError;
22 use Closure;
23 use SignalHandlerId;
24 use Type;
25 use Value;
26
27 use get_thread_id;
28
29 #[doc(hidden)]
30 pub use gobject_sys::GObject;
31
32 #[doc(hidden)]
33 pub use gobject_sys::GObjectClass;
34
35 /// Implemented by types representing `glib::Object` and subclasses of it.
36 pub unsafe trait ObjectType:
37 UnsafeFrom<ObjectRef>
38 + Into<ObjectRef>
39 + StaticType
40 + fmt::Debug
41 + Clone
42 + PartialEq
43 + Eq
44 + PartialOrd
45 + Ord
46 + hash::Hash
47 + for<'a> ToGlibPtr<'a, *mut <Self as ObjectType>::GlibType>
48 + 'static
49 {
50 /// type of the FFI Instance structure.
51 type GlibType: 'static;
52 /// type of the FFI Class structure.
53 type GlibClassType: 'static;
54 /// type of the Rust Class structure.
55 type RustClassType: 'static;
56
as_object_ref(&self) -> &ObjectRef57 fn as_object_ref(&self) -> &ObjectRef;
as_ptr(&self) -> *mut Self::GlibType58 fn as_ptr(&self) -> *mut Self::GlibType;
59 }
60
61 /// Unsafe variant of the `From` trait.
62 pub trait UnsafeFrom<T> {
63 /// # Safety
64 ///
65 /// It is the responsibility of the caller to ensure *all* invariants of
66 /// the `T` hold before this is called, and that subsequent to conversion
67 /// to assume nothing other than the invariants of the output. Implementors
68 /// of this must ensure that the invariants of the output type hold.
unsafe_from(t: T) -> Self69 unsafe fn unsafe_from(t: T) -> Self;
70 }
71
72 /// Declares the "is a" relationship.
73 ///
74 /// `Self` is said to implement `T`.
75 ///
76 /// For instance, since originally `GtkWidget` is a subclass of `GObject` and
77 /// implements the `GtkBuildable` interface, `gtk::Widget` implements
78 /// `IsA<glib::Object>` and `IsA<gtk::Buildable>`.
79 ///
80 ///
81 /// The trait can only be implemented if the appropriate `ToGlibPtr`
82 /// implementations exist.
83 pub unsafe trait IsA<T: ObjectType>: ObjectType + AsRef<T> + 'static {}
84
85 /// Trait for mapping a class struct type to its corresponding instance type.
86 pub unsafe trait IsClassFor: Sized + 'static {
87 /// Corresponding Rust instance type for this class.
88 type Instance: ObjectType;
89
90 /// Get the type id for this class.
get_type(&self) -> Type91 fn get_type(&self) -> Type {
92 unsafe {
93 let klass = self as *const _ as *const gobject_sys::GTypeClass;
94 from_glib((*klass).g_type)
95 }
96 }
97
98 /// Casts this class to a reference to a parent type's class.
upcast_ref<U: IsClassFor>(&self) -> &U where Self::Instance: IsA<U::Instance>, U::Instance: ObjectType,99 fn upcast_ref<U: IsClassFor>(&self) -> &U
100 where
101 Self::Instance: IsA<U::Instance>,
102 U::Instance: ObjectType,
103 {
104 unsafe {
105 let klass = self as *const _ as *const U;
106 &*klass
107 }
108 }
109
110 /// Casts this class to a mutable reference to a parent type's class.
upcast_ref_mut<U: IsClassFor>(&mut self) -> &mut U where Self::Instance: IsA<U::Instance>, U::Instance: ObjectType,111 fn upcast_ref_mut<U: IsClassFor>(&mut self) -> &mut U
112 where
113 Self::Instance: IsA<U::Instance>,
114 U::Instance: ObjectType,
115 {
116 unsafe {
117 let klass = self as *mut _ as *mut U;
118 &mut *klass
119 }
120 }
121
122 /// Casts this class to a reference to a child type's class or
123 /// fails if this class is not implementing the child class.
downcast_ref<U: IsClassFor>(&self) -> Option<&U> where U::Instance: IsA<Self::Instance>, Self::Instance: ObjectType,124 fn downcast_ref<U: IsClassFor>(&self) -> Option<&U>
125 where
126 U::Instance: IsA<Self::Instance>,
127 Self::Instance: ObjectType,
128 {
129 if !self.get_type().is_a(&U::Instance::static_type()) {
130 return None;
131 }
132
133 unsafe {
134 let klass = self as *const _ as *const U;
135 Some(&*klass)
136 }
137 }
138
139 /// Casts this class to a mutable reference to a child type's class or
140 /// fails if this class is not implementing the child class.
downcast_ref_mut<U: IsClassFor>(&mut self) -> Option<&mut U> where U::Instance: IsA<Self::Instance>, Self::Instance: ObjectType,141 fn downcast_ref_mut<U: IsClassFor>(&mut self) -> Option<&mut U>
142 where
143 U::Instance: IsA<Self::Instance>,
144 Self::Instance: ObjectType,
145 {
146 if !self.get_type().is_a(&U::Instance::static_type()) {
147 return None;
148 }
149
150 unsafe {
151 let klass = self as *mut _ as *mut U;
152 Some(&mut *klass)
153 }
154 }
155
156 /// Gets the class struct corresponding to `type_`.
157 ///
158 /// This will return `None` if `type_` is not a subclass of `Self`.
from_type(type_: Type) -> Option<ClassRef<Self>>159 fn from_type(type_: Type) -> Option<ClassRef<Self>> {
160 if !type_.is_a(&Self::Instance::static_type()) {
161 return None;
162 }
163
164 unsafe {
165 let ptr = gobject_sys::g_type_class_ref(type_.to_glib());
166 if ptr.is_null() {
167 None
168 } else {
169 Some(ClassRef(ptr::NonNull::new_unchecked(ptr as *mut Self)))
170 }
171 }
172 }
173 }
174
175 #[derive(Debug)]
176 pub struct ClassRef<T: IsClassFor>(ptr::NonNull<T>);
177
178 impl<T: IsClassFor> ops::Deref for ClassRef<T> {
179 type Target = T;
180
deref(&self) -> &T181 fn deref(&self) -> &T {
182 unsafe { self.0.as_ref() }
183 }
184 }
185
186 impl<T: IsClassFor> Drop for ClassRef<T> {
drop(&mut self)187 fn drop(&mut self) {
188 unsafe {
189 gobject_sys::g_type_class_unref(self.0.as_ptr() as *mut _);
190 }
191 }
192 }
193
194 unsafe impl<T: IsClassFor> Send for ClassRef<T> {}
195 unsafe impl<T: IsClassFor> Sync for ClassRef<T> {}
196
197 /// Upcasting and downcasting support.
198 ///
199 /// Provides conversions up and down the class hierarchy tree.
200 pub trait Cast: ObjectType {
201 /// Upcasts an object to a superclass or interface `T`.
202 ///
203 /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
204 /// known at compile-time, whether a specific object implements an interface or not, in which case
205 /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
206 /// is checking the types at runtime.
207 ///
208 /// # Example
209 ///
210 /// ```ignore
211 /// let button = gtk::Button::new();
212 /// let widget = button.upcast::<gtk::Widget>();
213 /// ```
214 #[inline]
upcast<T: ObjectType>(self) -> T where Self: IsA<T>,215 fn upcast<T: ObjectType>(self) -> T
216 where
217 Self: IsA<T>,
218 {
219 unsafe { self.unsafe_cast() }
220 }
221
222 /// Upcasts an object to a reference of its superclass or interface `T`.
223 ///
224 /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
225 /// known at compile-time, whether a specific object implements an interface or not, in which case
226 /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
227 /// is checking the types at runtime.
228 ///
229 /// # Example
230 ///
231 /// ```ignore
232 /// let button = gtk::Button::new();
233 /// let widget = button.upcast_ref::<gtk::Widget>();
234 /// ```
235 #[inline]
upcast_ref<T: ObjectType>(&self) -> &T where Self: IsA<T>,236 fn upcast_ref<T: ObjectType>(&self) -> &T
237 where
238 Self: IsA<T>,
239 {
240 unsafe { self.unsafe_cast_ref() }
241 }
242
243 /// Tries to downcast to a subclass or interface implementor `T`.
244 ///
245 /// Returns `Ok(T)` if the object is an instance of `T` and `Err(self)`
246 /// otherwise.
247 ///
248 /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
249 /// known at compile-time, whether a specific object implements an interface or not, in which case
250 /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
251 /// is checking the types at runtime.
252 ///
253 /// # Example
254 ///
255 /// ```ignore
256 /// let button = gtk::Button::new();
257 /// let widget = button.upcast::<gtk::Widget>();
258 /// assert!(widget.downcast::<gtk::Button>().is_ok());
259 /// ```
260 #[inline]
downcast<T: ObjectType>(self) -> Result<T, Self> where Self: CanDowncast<T>,261 fn downcast<T: ObjectType>(self) -> Result<T, Self>
262 where
263 Self: CanDowncast<T>,
264 {
265 if self.is::<T>() {
266 Ok(unsafe { self.unsafe_cast() })
267 } else {
268 Err(self)
269 }
270 }
271
272 /// Tries to downcast to a reference of its subclass or interface implementor `T`.
273 ///
274 /// Returns `Some(T)` if the object is an instance of `T` and `None`
275 /// otherwise.
276 ///
277 /// *NOTE*: This statically checks at compile-time if casting is possible. It is not always
278 /// known at compile-time, whether a specific object implements an interface or not, in which case
279 /// `upcast` would fail to compile. `dynamic_cast` can be used in these circumstances, which
280 /// is checking the types at runtime.
281 ///
282 /// # Example
283 ///
284 /// ```ignore
285 /// let button = gtk::Button::new();
286 /// let widget = button.upcast::<gtk::Widget>();
287 /// assert!(widget.downcast_ref::<gtk::Button>().is_some());
288 /// ```
289 #[inline]
downcast_ref<T: ObjectType>(&self) -> Option<&T> where Self: CanDowncast<T>,290 fn downcast_ref<T: ObjectType>(&self) -> Option<&T>
291 where
292 Self: CanDowncast<T>,
293 {
294 if self.is::<T>() {
295 Some(unsafe { self.unsafe_cast_ref() })
296 } else {
297 None
298 }
299 }
300
301 /// Tries to cast to an object of type `T`. This handles upcasting, downcasting
302 /// and casting between interface and interface implementors. All checks are performed at
303 /// runtime, while `downcast` and `upcast` will do many checks at compile-time already.
304 ///
305 /// It is not always known at compile-time, whether a specific object implements an interface or
306 /// not, and checking as to be performed at runtime.
307 ///
308 /// Returns `Ok(T)` if the object is an instance of `T` and `Err(self)`
309 /// otherwise.
310 ///
311 /// # Example
312 ///
313 /// ```ignore
314 /// let button = gtk::Button::new();
315 /// let widget = button.dynamic_cast::<gtk::Widget>();
316 /// assert!(widget.is_ok());
317 /// let widget = widget.unwrap();
318 /// assert!(widget.dynamic_cast::<gtk::Button>().is_ok());
319 /// ```
320 #[inline]
dynamic_cast<T: ObjectType>(self) -> Result<T, Self>321 fn dynamic_cast<T: ObjectType>(self) -> Result<T, Self> {
322 if !self.is::<T>() {
323 Err(self)
324 } else {
325 Ok(unsafe { self.unsafe_cast() })
326 }
327 }
328
329 /// Tries to cast to reference to an object of type `T`. This handles upcasting, downcasting
330 /// and casting between interface and interface implementors. All checks are performed at
331 /// runtime, while `downcast` and `upcast` will do many checks at compile-time already.
332 ///
333 /// It is not always known at compile-time, whether a specific object implements an interface or
334 /// not, and checking as to be performed at runtime.
335 ///
336 /// Returns `Some(T)` if the object is an instance of `T` and `None`
337 /// otherwise.
338 ///
339 /// # Example
340 ///
341 /// ```ignore
342 /// let button = gtk::Button::new();
343 /// let widget = button.dynamic_cast_ref::<gtk::Widget>();
344 /// assert!(widget.is_some());
345 /// let widget = widget.unwrap();
346 /// assert!(widget.dynamic_cast_ref::<gtk::Button>().is_some());
347 /// ```
348 #[inline]
dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T>349 fn dynamic_cast_ref<T: ObjectType>(&self) -> Option<&T> {
350 if !self.is::<T>() {
351 None
352 } else {
353 // This cast is safe because all our wrapper types have the
354 // same representation except for the name and the phantom data
355 // type. IsA<> is an unsafe trait that must only be implemented
356 // if this is a valid wrapper type
357 Some(unsafe { self.unsafe_cast_ref() })
358 }
359 }
360
361 /// Casts to `T` unconditionally.
362 ///
363 /// # Panics
364 ///
365 /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
366 ///
367 /// # Safety
368 ///
369 /// If not running with `debug_assertions` enabled, the caller is responsible
370 /// for ensuring that the instance implements `T`
unsafe_cast<T: ObjectType>(self) -> T371 unsafe fn unsafe_cast<T: ObjectType>(self) -> T {
372 debug_assert!(self.is::<T>());
373 T::unsafe_from(self.into())
374 }
375
376 /// Casts to `&T` unconditionally.
377 ///
378 /// # Panics
379 ///
380 /// Panics if compiled with `debug_assertions` and the instance doesn't implement `T`.
381 ///
382 /// # Safety
383 ///
384 /// If not running with `debug_assertions` enabled, the caller is responsible
385 /// for ensuring that the instance implements `T`
unsafe_cast_ref<T: ObjectType>(&self) -> &T386 unsafe fn unsafe_cast_ref<T: ObjectType>(&self) -> &T {
387 debug_assert!(self.is::<T>());
388 // This cast is safe because all our wrapper types have the
389 // same representation except for the name and the phantom data
390 // type. IsA<> is an unsafe trait that must only be implemented
391 // if this is a valid wrapper type
392 &*(self as *const Self as *const T)
393 }
394 }
395
396 impl<T: ObjectType> Cast for T {}
397
398 /// Marker trait for the statically known possibility of downcasting from `Self` to `T`.
399 pub trait CanDowncast<T> {}
400
401 impl<Super: IsA<Super>, Sub: IsA<Super>> CanDowncast<Sub> for Super {}
402
403 // Manual implementation of glib_shared_wrapper! because of special cases
404 pub struct ObjectRef {
405 inner: ptr::NonNull<GObject>,
406 }
407
408 impl Clone for ObjectRef {
clone(&self) -> Self409 fn clone(&self) -> Self {
410 unsafe {
411 ObjectRef {
412 inner: ptr::NonNull::new_unchecked(gobject_sys::g_object_ref(self.inner.as_ptr())),
413 }
414 }
415 }
416 }
417
418 impl Drop for ObjectRef {
drop(&mut self)419 fn drop(&mut self) {
420 unsafe {
421 gobject_sys::g_object_unref(self.inner.as_ptr());
422 }
423 }
424 }
425
426 impl fmt::Debug for ObjectRef {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result427 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
428 let type_ = unsafe {
429 let klass = (*self.inner.as_ptr()).g_type_instance.g_class as *const ObjectClass;
430 (&*klass).get_type()
431 };
432
433 f.debug_struct("ObjectRef")
434 .field("inner", &self.inner)
435 .field("type", &type_)
436 .finish()
437 }
438 }
439
440 impl PartialOrd for ObjectRef {
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>441 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
442 self.inner.partial_cmp(&other.inner)
443 }
444 }
445
446 impl Ord for ObjectRef {
cmp(&self, other: &Self) -> cmp::Ordering447 fn cmp(&self, other: &Self) -> cmp::Ordering {
448 self.inner.cmp(&other.inner)
449 }
450 }
451
452 impl PartialEq for ObjectRef {
eq(&self, other: &Self) -> bool453 fn eq(&self, other: &Self) -> bool {
454 self.inner == other.inner
455 }
456 }
457
458 impl Eq for ObjectRef {}
459
460 impl hash::Hash for ObjectRef {
hash<H>(&self, state: &mut H) where H: hash::Hasher,461 fn hash<H>(&self, state: &mut H)
462 where
463 H: hash::Hasher,
464 {
465 self.inner.hash(state)
466 }
467 }
468
469 #[doc(hidden)]
470 impl GlibPtrDefault for ObjectRef {
471 type GlibType = *mut GObject;
472 }
473
474 #[doc(hidden)]
475 impl<'a> ToGlibPtr<'a, *mut GObject> for ObjectRef {
476 type Storage = &'a ObjectRef;
477
478 #[inline]
to_glib_none(&'a self) -> Stash<'a, *mut GObject, Self>479 fn to_glib_none(&'a self) -> Stash<'a, *mut GObject, Self> {
480 Stash(self.inner.as_ptr(), self)
481 }
482
483 #[inline]
to_glib_full(&self) -> *mut GObject484 fn to_glib_full(&self) -> *mut GObject {
485 unsafe { gobject_sys::g_object_ref(self.inner.as_ptr()) }
486 }
487 }
488
489 #[doc(hidden)]
490 impl<'a> ToGlibContainerFromSlice<'a, *mut *mut GObject> for ObjectRef {
491 type Storage = (
492 Vec<Stash<'a, *mut GObject, ObjectRef>>,
493 Option<Vec<*mut GObject>>,
494 );
495
to_glib_none_from_slice(t: &'a [ObjectRef]) -> (*mut *mut GObject, Self::Storage)496 fn to_glib_none_from_slice(t: &'a [ObjectRef]) -> (*mut *mut GObject, Self::Storage) {
497 let v: Vec<_> = t.iter().map(|s| s.to_glib_none()).collect();
498 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
499 v_ptr.push(ptr::null_mut() as *mut GObject);
500
501 (v_ptr.as_ptr() as *mut *mut GObject, (v, Some(v_ptr)))
502 }
503
to_glib_container_from_slice(t: &'a [ObjectRef]) -> (*mut *mut GObject, Self::Storage)504 fn to_glib_container_from_slice(t: &'a [ObjectRef]) -> (*mut *mut GObject, Self::Storage) {
505 let v: Vec<_> = t.iter().map(|s| s.to_glib_none()).collect();
506
507 let v_ptr = unsafe {
508 let v_ptr = glib_sys::g_malloc0(mem::size_of::<*mut GObject>() * (t.len() + 1))
509 as *mut *mut GObject;
510
511 for (i, s) in v.iter().enumerate() {
512 ptr::write(v_ptr.add(i), s.0);
513 }
514
515 v_ptr
516 };
517
518 (v_ptr, (v, None))
519 }
520
to_glib_full_from_slice(t: &[ObjectRef]) -> *mut *mut GObject521 fn to_glib_full_from_slice(t: &[ObjectRef]) -> *mut *mut GObject {
522 unsafe {
523 let v_ptr = glib_sys::g_malloc0(std::mem::size_of::<*mut GObject>() * (t.len() + 1))
524 as *mut *mut GObject;
525
526 for (i, s) in t.iter().enumerate() {
527 ptr::write(v_ptr.add(i), s.to_glib_full());
528 }
529
530 v_ptr
531 }
532 }
533 }
534
535 #[doc(hidden)]
536 impl<'a> ToGlibContainerFromSlice<'a, *const *mut GObject> for ObjectRef {
537 type Storage = (
538 Vec<Stash<'a, *mut GObject, ObjectRef>>,
539 Option<Vec<*mut GObject>>,
540 );
541
to_glib_none_from_slice(t: &'a [ObjectRef]) -> (*const *mut GObject, Self::Storage)542 fn to_glib_none_from_slice(t: &'a [ObjectRef]) -> (*const *mut GObject, Self::Storage) {
543 let (ptr, stash) =
544 ToGlibContainerFromSlice::<'a, *mut *mut GObject>::to_glib_none_from_slice(t);
545 (ptr as *const *mut GObject, stash)
546 }
547
to_glib_container_from_slice(_: &'a [ObjectRef]) -> (*const *mut GObject, Self::Storage)548 fn to_glib_container_from_slice(_: &'a [ObjectRef]) -> (*const *mut GObject, Self::Storage) {
549 // Can't have consumer free a *const pointer
550 unimplemented!()
551 }
552
to_glib_full_from_slice(_: &[ObjectRef]) -> *const *mut GObject553 fn to_glib_full_from_slice(_: &[ObjectRef]) -> *const *mut GObject {
554 // Can't have consumer free a *const pointer
555 unimplemented!()
556 }
557 }
558
559 #[doc(hidden)]
560 impl FromGlibPtrNone<*mut GObject> for ObjectRef {
561 #[inline]
from_glib_none(ptr: *mut GObject) -> Self562 unsafe fn from_glib_none(ptr: *mut GObject) -> Self {
563 assert!(!ptr.is_null());
564
565 // Attention: This takes ownership of floating references!
566 ObjectRef {
567 inner: ptr::NonNull::new_unchecked(gobject_sys::g_object_ref_sink(ptr)),
568 }
569 }
570 }
571
572 #[doc(hidden)]
573 impl FromGlibPtrNone<*const GObject> for ObjectRef {
574 #[inline]
from_glib_none(ptr: *const GObject) -> Self575 unsafe fn from_glib_none(ptr: *const GObject) -> Self {
576 // Attention: This takes ownership of floating references!
577 from_glib_none(ptr as *mut GObject)
578 }
579 }
580
581 #[doc(hidden)]
582 impl FromGlibPtrFull<*mut GObject> for ObjectRef {
583 #[inline]
from_glib_full(ptr: *mut GObject) -> Self584 unsafe fn from_glib_full(ptr: *mut GObject) -> Self {
585 assert!(!ptr.is_null());
586
587 ObjectRef {
588 inner: ptr::NonNull::new_unchecked(ptr),
589 }
590 }
591 }
592
593 #[doc(hidden)]
594 impl FromGlibPtrBorrow<*mut GObject> for ObjectRef {
595 #[inline]
from_glib_borrow(ptr: *mut GObject) -> Borrowed<Self>596 unsafe fn from_glib_borrow(ptr: *mut GObject) -> Borrowed<Self> {
597 assert!(!ptr.is_null());
598
599 Borrowed::new(ObjectRef {
600 inner: ptr::NonNull::new_unchecked(ptr),
601 })
602 }
603 }
604
605 #[doc(hidden)]
606 impl FromGlibPtrBorrow<*const GObject> for ObjectRef {
607 #[inline]
from_glib_borrow(ptr: *const GObject) -> Borrowed<Self>608 unsafe fn from_glib_borrow(ptr: *const GObject) -> Borrowed<Self> {
609 from_glib_borrow(ptr as *mut GObject)
610 }
611 }
612
613 #[doc(hidden)]
614 impl FromGlibContainerAsVec<*mut GObject, *mut *mut GObject> for ObjectRef {
from_glib_none_num_as_vec(ptr: *mut *mut GObject, num: usize) -> Vec<Self>615 unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut GObject, num: usize) -> Vec<Self> {
616 if num == 0 || ptr.is_null() {
617 return Vec::new();
618 }
619
620 // Attention: This takes ownership of floating references!
621 let mut res = Vec::with_capacity(num);
622 for i in 0..num {
623 res.push(from_glib_none(ptr::read(ptr.add(i))));
624 }
625 res
626 }
627
from_glib_container_num_as_vec(ptr: *mut *mut GObject, num: usize) -> Vec<Self>628 unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut GObject, num: usize) -> Vec<Self> {
629 // Attention: This takes ownership of floating references!
630 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
631 glib_sys::g_free(ptr as *mut _);
632 res
633 }
634
from_glib_full_num_as_vec(ptr: *mut *mut GObject, num: usize) -> Vec<Self>635 unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut GObject, num: usize) -> Vec<Self> {
636 if num == 0 || ptr.is_null() {
637 return Vec::new();
638 }
639
640 let mut res = Vec::with_capacity(num);
641 for i in 0..num {
642 res.push(from_glib_full(ptr::read(ptr.add(i))));
643 }
644 glib_sys::g_free(ptr as *mut _);
645 res
646 }
647 }
648
649 #[doc(hidden)]
650 impl FromGlibPtrArrayContainerAsVec<*mut GObject, *mut *mut GObject> for ObjectRef {
from_glib_none_as_vec(ptr: *mut *mut GObject) -> Vec<Self>651 unsafe fn from_glib_none_as_vec(ptr: *mut *mut GObject) -> Vec<Self> {
652 // Attention: This takes ownership of floating references!
653 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
654 }
655
from_glib_container_as_vec(ptr: *mut *mut GObject) -> Vec<Self>656 unsafe fn from_glib_container_as_vec(ptr: *mut *mut GObject) -> Vec<Self> {
657 // Attention: This takes ownership of floating references!
658 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
659 }
660
from_glib_full_as_vec(ptr: *mut *mut GObject) -> Vec<Self>661 unsafe fn from_glib_full_as_vec(ptr: *mut *mut GObject) -> Vec<Self> {
662 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
663 }
664 }
665
666 #[doc(hidden)]
667 impl FromGlibContainerAsVec<*mut GObject, *const *mut GObject> for ObjectRef {
from_glib_none_num_as_vec(ptr: *const *mut GObject, num: usize) -> Vec<Self>668 unsafe fn from_glib_none_num_as_vec(ptr: *const *mut GObject, num: usize) -> Vec<Self> {
669 // Attention: This takes ownership of floating references!
670 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
671 }
672
from_glib_container_num_as_vec(_: *const *mut GObject, _: usize) -> Vec<Self>673 unsafe fn from_glib_container_num_as_vec(_: *const *mut GObject, _: usize) -> Vec<Self> {
674 // Can't free a *const
675 unimplemented!()
676 }
677
from_glib_full_num_as_vec(_: *const *mut GObject, _: usize) -> Vec<Self>678 unsafe fn from_glib_full_num_as_vec(_: *const *mut GObject, _: usize) -> Vec<Self> {
679 // Can't free a *const
680 unimplemented!()
681 }
682 }
683
684 #[doc(hidden)]
685 impl FromGlibPtrArrayContainerAsVec<*mut GObject, *const *mut GObject> for ObjectRef {
from_glib_none_as_vec(ptr: *const *mut GObject) -> Vec<Self>686 unsafe fn from_glib_none_as_vec(ptr: *const *mut GObject) -> Vec<Self> {
687 // Attention: This takes ownership of floating references!
688 FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
689 }
690
from_glib_container_as_vec(_: *const *mut GObject) -> Vec<Self>691 unsafe fn from_glib_container_as_vec(_: *const *mut GObject) -> Vec<Self> {
692 // Can't free a *const
693 unimplemented!()
694 }
695
from_glib_full_as_vec(_: *const *mut GObject) -> Vec<Self>696 unsafe fn from_glib_full_as_vec(_: *const *mut GObject) -> Vec<Self> {
697 // Can't free a *const
698 unimplemented!()
699 }
700 }
701
702 #[doc(hidden)]
703 #[macro_export]
704 macro_rules! glib_weak_impl {
705 ($name:ident) => {
706 #[doc(hidden)]
707 impl $crate::clone::Downgrade for $name {
708 type Weak = $crate::object::WeakRef<Self>;
709
710 fn downgrade(&self) -> Self::Weak {
711 <Self as $crate::object::ObjectExt>::downgrade(&self)
712 }
713 }
714 };
715 }
716
717 /// ObjectType implementations for Object types. See `glib_wrapper!`.
718 #[macro_export]
719 macro_rules! glib_object_wrapper {
720 (@generic_impl [$($attr:meta)*] $name:ident, $ffi_name:path, $ffi_class_name:path, $rust_class_name:path, @get_type $get_type_expr:expr) => {
721 $(#[$attr])*
722 // Always derive Hash/Ord (and below impl Debug, PartialEq, Eq, PartialOrd) for object
723 // types. Due to inheritance and up/downcasting we must implement these by pointer or
724 // otherwise they would potentially give differeny results for the same object depending on
725 // the type we currently know for it
726 #[derive(Clone, Hash, Ord)]
727 pub struct $name($crate::object::ObjectRef, ::std::marker::PhantomData<$ffi_name>);
728
729 #[doc(hidden)]
730 impl Into<$crate::object::ObjectRef> for $name {
731 fn into(self) -> $crate::object::ObjectRef {
732 self.0
733 }
734 }
735
736 #[doc(hidden)]
737 impl $crate::object::UnsafeFrom<$crate::object::ObjectRef> for $name {
738 #[allow(clippy::missing_safety_doc)]
739 unsafe fn unsafe_from(t: $crate::object::ObjectRef) -> Self {
740 $name(t, ::std::marker::PhantomData)
741 }
742 }
743
744 #[doc(hidden)]
745 impl $crate::translate::GlibPtrDefault for $name {
746 type GlibType = *mut $ffi_name;
747 }
748
749 #[doc(hidden)]
750 unsafe impl $crate::object::ObjectType for $name {
751 type GlibType = $ffi_name;
752 type GlibClassType = $ffi_class_name;
753 type RustClassType = $rust_class_name;
754
755 fn as_object_ref(&self) -> &$crate::object::ObjectRef {
756 &self.0
757 }
758
759 fn as_ptr(&self) -> *mut Self::GlibType {
760 self.0.to_glib_none().0 as *mut _
761 }
762 }
763
764 #[doc(hidden)]
765 impl AsRef<$crate::object::ObjectRef> for $name {
766 fn as_ref(&self) -> &$crate::object::ObjectRef {
767 &self.0
768 }
769 }
770
771 #[doc(hidden)]
772 impl AsRef<$name> for $name {
773 fn as_ref(&self) -> &$name {
774 self
775 }
776 }
777
778 #[doc(hidden)]
779 unsafe impl $crate::object::IsA<$name> for $name { }
780
781 #[doc(hidden)]
782 impl<'a> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name {
783 type Storage = <$crate::object::ObjectRef as
784 $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;
785
786 #[inline]
787 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
788 let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.0);
789 $crate::translate::Stash(stash.0 as *const _, stash.1)
790 }
791
792 #[inline]
793 fn to_glib_full(&self) -> *const $ffi_name {
794 $crate::translate::ToGlibPtr::to_glib_full(&self.0) as *const _
795 }
796 }
797
798 #[doc(hidden)]
799 impl<'a> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name {
800 type Storage = <$crate::object::ObjectRef as
801 $crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;
802
803 #[inline]
804 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
805 let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.0);
806 $crate::translate::Stash(stash.0 as *mut _, stash.1)
807 }
808
809 #[inline]
810 fn to_glib_full(&self) -> *mut $ffi_name {
811 $crate::translate::ToGlibPtr::to_glib_full(&self.0) as *mut _
812 }
813 }
814
815 #[doc(hidden)]
816 impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *mut *mut $ffi_name> for $name {
817 type Storage = (Vec<$crate::translate::Stash<'a, *mut $ffi_name, $name>>, Option<Vec<*mut $ffi_name>>);
818
819 fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut *mut $ffi_name, Self::Storage) {
820 let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
821 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
822 v_ptr.push(::std::ptr::null_mut() as *mut $ffi_name);
823
824 (v_ptr.as_ptr() as *mut *mut $ffi_name, (v, Some(v_ptr)))
825 }
826
827 fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut *mut $ffi_name, Self::Storage) {
828 let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
829
830 let v_ptr = unsafe {
831 let v_ptr = $crate::glib_sys::g_malloc0(::std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
832
833 for (i, s) in v.iter().enumerate() {
834 ::std::ptr::write(v_ptr.add(i), s.0);
835 }
836
837 v_ptr
838 };
839
840 (v_ptr, (v, None))
841 }
842
843 fn to_glib_full_from_slice(t: &[$name]) -> *mut *mut $ffi_name {
844 unsafe {
845 let v_ptr = $crate::glib_sys::g_malloc0(::std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
846
847 for (i, s) in t.iter().enumerate() {
848 ::std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
849 }
850
851 v_ptr
852 }
853 }
854 }
855
856 #[doc(hidden)]
857 impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *const *mut $ffi_name> for $name {
858 type Storage = (Vec<$crate::translate::Stash<'a, *mut $ffi_name, $name>>, Option<Vec<*mut $ffi_name>>);
859
860 fn to_glib_none_from_slice(t: &'a [$name]) -> (*const *mut $ffi_name, Self::Storage) {
861 let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *mut $ffi_name>::to_glib_none_from_slice(t);
862 (ptr as *const *mut $ffi_name, stash)
863 }
864
865 fn to_glib_container_from_slice(_: &'a [$name]) -> (*const *mut $ffi_name, Self::Storage) {
866 // Can't have consumer free a *const pointer
867 unimplemented!()
868 }
869
870 fn to_glib_full_from_slice(_: &[$name]) -> *const *mut $ffi_name {
871 // Can't have consumer free a *const pointer
872 unimplemented!()
873 }
874 }
875
876 #[doc(hidden)]
877 impl $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name {
878 #[inline]
879 #[allow(clippy::cast_ptr_alignment)]
880 #[allow(clippy::missing_safety_doc)]
881 unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
882 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
883 $name($crate::translate::from_glib_none(ptr as *mut _), ::std::marker::PhantomData)
884 }
885 }
886
887 #[doc(hidden)]
888 impl $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name {
889 #[inline]
890 #[allow(clippy::cast_ptr_alignment)]
891 #[allow(clippy::missing_safety_doc)]
892 unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
893 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
894 $name($crate::translate::from_glib_none(ptr as *mut _), ::std::marker::PhantomData)
895 }
896 }
897
898 #[doc(hidden)]
899 impl $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name {
900 #[inline]
901 #[allow(clippy::cast_ptr_alignment)]
902 #[allow(clippy::missing_safety_doc)]
903 unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
904 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
905 $name($crate::translate::from_glib_full(ptr as *mut _), ::std::marker::PhantomData)
906 }
907 }
908
909 #[doc(hidden)]
910 impl $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name {
911 #[inline]
912 #[allow(clippy::cast_ptr_alignment)]
913 #[allow(clippy::missing_safety_doc)]
914 unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> $crate::translate::Borrowed<Self> {
915 debug_assert!($crate::types::instance_of::<Self>(ptr as *const _));
916 $crate::translate::Borrowed::new(
917 $name(
918 $crate::translate::from_glib_borrow::<_, $crate::object::ObjectRef>(ptr as *mut _).into_inner(),
919 ::std::marker::PhantomData,
920 )
921 )
922 }
923 }
924
925 #[doc(hidden)]
926 impl $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name {
927 #[inline]
928 #[allow(clippy::cast_ptr_alignment)]
929 #[allow(clippy::missing_safety_doc)]
930 unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> $crate::translate::Borrowed<Self> {
931 $crate::translate::from_glib_borrow::<_, $name>(ptr as *mut $ffi_name)
932 }
933 }
934
935 #[doc(hidden)]
936 impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
937 #[allow(clippy::missing_safety_doc)]
938 unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
939 if num == 0 || ptr.is_null() {
940 return Vec::new();
941 }
942
943 let mut res = Vec::with_capacity(num);
944 for i in 0..num {
945 res.push($crate::translate::from_glib_none(::std::ptr::read(ptr.add(i))));
946 }
947 res
948 }
949
950 #[allow(clippy::missing_safety_doc)]
951 unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
952 let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
953 $crate::glib_sys::g_free(ptr as *mut _);
954 res
955 }
956
957 #[allow(clippy::missing_safety_doc)]
958 unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
959 if num == 0 || ptr.is_null() {
960 return Vec::new();
961 }
962
963 let mut res = Vec::with_capacity(num);
964 for i in 0..num {
965 res.push($crate::translate::from_glib_full(::std::ptr::read(ptr.add(i))));
966 }
967 $crate::glib_sys::g_free(ptr as *mut _);
968 res
969 }
970 }
971
972 #[doc(hidden)]
973 impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
974 #[allow(clippy::missing_safety_doc)]
975 unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
976 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
977 }
978
979 #[allow(clippy::missing_safety_doc)]
980 unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
981 $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
982 }
983
984 #[allow(clippy::missing_safety_doc)]
985 unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
986 $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
987 }
988 }
989
990 #[doc(hidden)]
991 impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name {
992 #[allow(clippy::missing_safety_doc)]
993 unsafe fn from_glib_none_num_as_vec(ptr: *const *mut $ffi_name, num: usize) -> Vec<Self> {
994 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
995 }
996
997 #[allow(clippy::missing_safety_doc)]
998 unsafe fn from_glib_container_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
999 // Can't free a *const
1000 unimplemented!()
1001 }
1002
1003 #[allow(clippy::missing_safety_doc)]
1004 unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
1005 // Can't free a *const
1006 unimplemented!()
1007 }
1008 }
1009
1010 #[doc(hidden)]
1011 impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name {
1012 #[allow(clippy::missing_safety_doc)]
1013 unsafe fn from_glib_none_as_vec(ptr: *const *mut $ffi_name) -> Vec<Self> {
1014 $crate::translate::FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
1015 }
1016
1017 #[allow(clippy::missing_safety_doc)]
1018 unsafe fn from_glib_container_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1019 // Can't free a *const
1020 unimplemented!()
1021 }
1022
1023 #[allow(clippy::missing_safety_doc)]
1024 unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
1025 // Can't free a *const
1026 unimplemented!()
1027 }
1028 }
1029
1030 impl $crate::types::StaticType for $name {
1031 fn static_type() -> $crate::types::Type {
1032 #[allow(unused_unsafe)]
1033 unsafe { $crate::translate::from_glib($get_type_expr) }
1034 }
1035 }
1036
1037 impl<T: $crate::object::ObjectType> ::std::cmp::PartialEq<T> for $name {
1038 #[inline]
1039 fn eq(&self, other: &T) -> bool {
1040 $crate::translate::ToGlibPtr::to_glib_none(&self.0).0 == $crate::translate::ToGlibPtr::to_glib_none($crate::object::ObjectType::as_object_ref(other)).0
1041 }
1042 }
1043
1044 impl ::std::cmp::Eq for $name { }
1045
1046 impl<T: $crate::object::ObjectType> ::std::cmp::PartialOrd<T> for $name {
1047 #[inline]
1048 fn partial_cmp(&self, other: &T) -> Option<::std::cmp::Ordering> {
1049 $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)
1050 }
1051 }
1052
1053 impl ::std::fmt::Debug for $name {
1054 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1055 f.debug_struct(stringify!($name))
1056 .field("inner", &self.0)
1057 .finish()
1058 }
1059 }
1060
1061 #[doc(hidden)]
1062 impl<'a> $crate::value::FromValueOptional<'a> for $name {
1063 #[allow(clippy::missing_safety_doc)]
1064 unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
1065 let obj = $crate::gobject_sys::g_value_get_object($crate::translate::ToGlibPtr::to_glib_none(value).0);
1066
1067 // Attention: Don't use from_glib_none() here because we don't want to steal any
1068 // floating references that might be owned by someone else.
1069 if !obj.is_null() {
1070 $crate::gobject_sys::g_object_ref(obj);
1071 }
1072
1073 // And take the reference to the object from above to pass it to the caller
1074 Option::<$name>::from_glib_full(obj as *mut $ffi_name).map(|o| $crate::object::Cast::unsafe_cast(o))
1075 }
1076 }
1077
1078 #[doc(hidden)]
1079 impl $crate::value::SetValue for $name {
1080 #[allow(clippy::cast_ptr_alignment)]
1081 #[allow(clippy::missing_safety_doc)]
1082 unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
1083 $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)
1084 }
1085 }
1086
1087 #[doc(hidden)]
1088 impl $crate::value::SetValueOptional for $name {
1089 #[allow(clippy::cast_ptr_alignment)]
1090 #[allow(clippy::missing_safety_doc)]
1091 unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
1092 $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)
1093 }
1094 }
1095
1096 $crate::glib_weak_impl!($name);
1097 };
1098
1099 (@munch_impls $name:ident, ) => { };
1100
1101 (@munch_impls $name:ident, $super_name:path) => {
1102 unsafe impl $crate::object::IsA<$super_name> for $name { }
1103
1104 #[doc(hidden)]
1105 impl AsRef<$super_name> for $name {
1106 fn as_ref(&self) -> &$super_name {
1107 $crate::object::Cast::upcast_ref(self)
1108 }
1109 }
1110 };
1111
1112 (@munch_impls $name:ident, $super_name:path, $($implements:tt)*) => {
1113 $crate::glib_object_wrapper!(@munch_impls $name, $super_name);
1114 $crate::glib_object_wrapper!(@munch_impls $name, $($implements)*);
1115 };
1116
1117 // If there is no parent class, i.e. only glib::Object
1118 (@munch_first_impl $name:ident, $rust_class_name:ident, ) => {
1119 $crate::glib_object_wrapper!(@munch_impls $name, );
1120
1121 impl ::std::ops::Deref for $rust_class_name {
1122 type Target = <$crate::object::Object as $crate::object::ObjectType>::RustClassType;
1123
1124 fn deref(&self) -> &Self::Target {
1125 $crate::object::IsClassFor::upcast_ref(self)
1126 }
1127 }
1128
1129 impl ::std::ops::DerefMut for $rust_class_name {
1130 fn deref_mut(&mut self) -> &mut Self::Target {
1131 $crate::object::IsClassFor::upcast_ref_mut(self)
1132 }
1133 }
1134 };
1135
1136 // If there is only one parent class
1137 (@munch_first_impl $name:ident, $rust_class_name:ident, $super_name:path) => {
1138 $crate::glib_object_wrapper!(@munch_impls $name, $super_name);
1139
1140 impl ::std::ops::Deref for $rust_class_name {
1141 type Target = <$super_name as $crate::object::ObjectType>::RustClassType;
1142
1143 fn deref(&self) -> &Self::Target {
1144 $crate::object::IsClassFor::upcast_ref(self)
1145 }
1146 }
1147
1148 impl ::std::ops::DerefMut for $rust_class_name {
1149 fn deref_mut(&mut self) -> &mut Self::Target {
1150 $crate::object::IsClassFor::upcast_ref_mut(self)
1151 }
1152 }
1153 };
1154
1155 // If there is more than one parent class
1156 (@munch_first_impl $name:ident, $rust_class_name:ident, $super_name:path, $($implements:tt)*) => {
1157 $crate::glib_object_wrapper!(@munch_impls $name, $super_name);
1158
1159 impl ::std::ops::Deref for $rust_class_name {
1160 type Target = <$super_name as $crate::object::ObjectType>::RustClassType;
1161
1162 fn deref(&self) -> &Self::Target {
1163 $crate::object::IsClassFor::upcast_ref(self)
1164 }
1165 }
1166
1167 impl ::std::ops::DerefMut for $rust_class_name {
1168 fn deref_mut(&mut self) -> &mut Self::Target {
1169 $crate::object::IsClassFor::upcast_ref_mut(self)
1170 }
1171 }
1172
1173 $crate::glib_object_wrapper!(@munch_impls $name, $($implements)*);
1174 };
1175
1176 (@class_impl $name:ident, $ffi_class_name:path, $rust_class_name:ident) => {
1177 #[repr(C)]
1178 #[derive(Debug)]
1179 pub struct $rust_class_name($ffi_class_name);
1180
1181 unsafe impl $crate::object::IsClassFor for $rust_class_name {
1182 type Instance = $name;
1183 }
1184
1185 unsafe impl Send for $rust_class_name { }
1186 unsafe impl Sync for $rust_class_name { }
1187 };
1188
1189 // This case is only for glib::Object itself below. All other cases have glib::Object in its
1190 // parent class list
1191 (@object [$($attr:meta)*] $name:ident, $ffi_name:path, $ffi_class_name:path, $rust_class_name:ident, @get_type $get_type_expr:expr) => {
1192 $crate::glib_object_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name, $ffi_class_name, $rust_class_name,
1193 @get_type $get_type_expr);
1194 $crate::glib_object_wrapper!(@class_impl $name, $ffi_class_name, $rust_class_name);
1195 };
1196
1197 (@object [$($attr:meta)*] $name:ident, $ffi_name:path, $ffi_class_name:path, $rust_class_name:ident,
1198 @get_type $get_type_expr:expr, @extends [$($extends:tt)*], @implements [$($implements:tt)*]) => {
1199 $crate::glib_object_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name, $ffi_class_name, $rust_class_name,
1200 @get_type $get_type_expr);
1201 $crate::glib_object_wrapper!(@munch_first_impl $name, $rust_class_name, $($extends)*);
1202 $crate::glib_object_wrapper!(@munch_impls $name, $($implements)*);
1203 $crate::glib_object_wrapper!(@class_impl $name, $ffi_class_name, $rust_class_name);
1204
1205 #[doc(hidden)]
1206 impl AsRef<$crate::object::Object> for $name {
1207 fn as_ref(&self) -> &$crate::object::Object {
1208 $crate::object::Cast::upcast_ref(self)
1209 }
1210 }
1211
1212 #[doc(hidden)]
1213 unsafe impl $crate::object::IsA<$crate::object::Object> for $name { }
1214 };
1215
1216 (@interface [$($attr:meta)*] $name:ident, $ffi_name:path, @get_type $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1217 $crate::glib_object_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name, $crate::wrapper::Void, $crate::wrapper::Void,
1218 @get_type $get_type_expr);
1219 $crate::glib_object_wrapper!(@munch_impls $name, $($requires)*);
1220
1221 #[doc(hidden)]
1222 impl AsRef<$crate::object::Object> for $name {
1223 fn as_ref(&self) -> &$crate::object::Object {
1224 $crate::object::Cast::upcast_ref(self)
1225 }
1226 }
1227
1228 #[doc(hidden)]
1229 unsafe impl $crate::object::IsA<$crate::object::Object> for $name { }
1230 };
1231 }
1232
1233 glib_object_wrapper!(@object
1234 [doc = "The base class in the object hierarchy."]
1235 Object, GObject, GObjectClass, ObjectClass, @get_type gobject_sys::g_object_get_type()
1236 );
1237
1238 impl Object {
new(type_: Type, properties: &[(&str, &dyn ToValue)]) -> Result<Object, BoolError>1239 pub fn new(type_: Type, properties: &[(&str, &dyn ToValue)]) -> Result<Object, BoolError> {
1240 use std::ffi::CString;
1241
1242 if !type_.is_a(&Object::static_type()) {
1243 return Err(glib_bool_error!(
1244 "Can't instantiate non-GObject type '{}'",
1245 type_
1246 ));
1247 }
1248
1249 unsafe {
1250 if gobject_sys::g_type_test_flags(
1251 type_.to_glib(),
1252 gobject_sys::G_TYPE_FLAG_INSTANTIATABLE,
1253 ) == glib_sys::GFALSE
1254 {
1255 return Err(glib_bool_error!("Can't instantiate type '{}'", type_));
1256 }
1257
1258 if gobject_sys::g_type_test_flags(type_.to_glib(), gobject_sys::G_TYPE_FLAG_ABSTRACT)
1259 != glib_sys::GFALSE
1260 {
1261 return Err(glib_bool_error!(
1262 "Can't instantiate abstract type '{}'",
1263 type_
1264 ));
1265 }
1266 }
1267
1268 let klass = ObjectClass::from_type(type_)
1269 .ok_or_else(|| glib_bool_error!("Can't retrieve class for type '{}'", type_))?;
1270 let pspecs = klass.list_properties();
1271
1272 let params = properties
1273 .iter()
1274 .map(|&(name, value)| {
1275 let pspec = pspecs
1276 .iter()
1277 .find(|p| p.get_name() == name)
1278 .ok_or_else(|| {
1279 glib_bool_error!("Can't find property '{}' for type '{}'", name, type_)
1280 })?;
1281
1282 let mut value = value.to_value();
1283 validate_property_type(type_, true, &pspec, &mut value)?;
1284 Ok((CString::new(name).unwrap(), value))
1285 })
1286 .collect::<Result<Vec<_>, _>>()?;
1287
1288 let params_c = params
1289 .iter()
1290 .map(|&(ref name, ref value)| gobject_sys::GParameter {
1291 name: name.as_ptr(),
1292 value: unsafe { *value.to_glib_none().0 },
1293 })
1294 .collect::<Vec<_>>();
1295
1296 unsafe {
1297 let ptr = gobject_sys::g_object_newv(
1298 type_.to_glib(),
1299 params_c.len() as u32,
1300 mut_override(params_c.as_ptr()),
1301 );
1302 if ptr.is_null() {
1303 Err(glib_bool_error!(
1304 "Can't instantiate object for type '{}'",
1305 type_
1306 ))
1307 } else if type_.is_a(&InitiallyUnowned::static_type()) {
1308 // Attention: This takes ownership of the floating reference
1309 Ok(from_glib_none(ptr))
1310 } else {
1311 Ok(from_glib_full(ptr))
1312 }
1313 }
1314 }
1315 }
1316
1317 pub trait ObjectExt: ObjectType {
1318 /// Returns `true` if the object is an instance of (can be cast to) `T`.
is<T: StaticType>(&self) -> bool1319 fn is<T: StaticType>(&self) -> bool;
1320
get_type(&self) -> Type1321 fn get_type(&self) -> Type;
get_object_class(&self) -> &ObjectClass1322 fn get_object_class(&self) -> &ObjectClass;
1323
set_property<'a, N: Into<&'a str>>( &self, property_name: N, value: &dyn ToValue, ) -> Result<(), BoolError>1324 fn set_property<'a, N: Into<&'a str>>(
1325 &self,
1326 property_name: N,
1327 value: &dyn ToValue,
1328 ) -> Result<(), BoolError>;
set_properties(&self, property_values: &[(&str, &dyn ToValue)]) -> Result<(), BoolError>1329 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]) -> Result<(), BoolError>;
get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError>1330 fn get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError>;
has_property<'a, N: Into<&'a str>>(&self, property_name: N, type_: Option<Type>) -> bool1331 fn has_property<'a, N: Into<&'a str>>(&self, property_name: N, type_: Option<Type>) -> bool;
get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type>1332 fn get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type>;
find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec>1333 fn find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec>;
list_properties(&self) -> Vec<::ParamSpec>1334 fn list_properties(&self) -> Vec<::ParamSpec>;
1335
1336 /// # Safety
1337 ///
1338 /// This function doesn't store type information
set_qdata<QD: 'static>(&self, key: Quark, value: QD)1339 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD);
1340
1341 /// # Safety
1342 ///
1343 /// The caller is responsible for ensuring the returned value is of a suitable type
get_qdata<QD: 'static>(&self, key: Quark) -> Option<&QD>1344 unsafe fn get_qdata<QD: 'static>(&self, key: Quark) -> Option<&QD>;
1345
1346 /// # Safety
1347 ///
1348 /// The caller is responsible for ensuring the returned value is of a suitable type
steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>1349 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>;
1350
1351 /// # Safety
1352 ///
1353 /// This function doesn't store type information
set_data<QD: 'static>(&self, key: &str, value: QD)1354 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD);
1355
1356 /// # Safety
1357 ///
1358 /// The caller is responsible for ensuring the returned value is of a suitable type
get_data<QD: 'static>(&self, key: &str) -> Option<&QD>1359 unsafe fn get_data<QD: 'static>(&self, key: &str) -> Option<&QD>;
1360
1361 /// # Safety
1362 ///
1363 /// The caller is responsible for ensuring the returned value is of a suitable type
steal_data<QD: 'static>(&self, key: &str) -> Option<QD>1364 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD>;
1365
block_signal(&self, handler_id: &SignalHandlerId)1366 fn block_signal(&self, handler_id: &SignalHandlerId);
unblock_signal(&self, handler_id: &SignalHandlerId)1367 fn unblock_signal(&self, handler_id: &SignalHandlerId);
stop_signal_emission(&self, signal_name: &str)1368 fn stop_signal_emission(&self, signal_name: &str);
1369
connect<'a, N, F>( &self, signal_name: N, after: bool, callback: F, ) -> Result<SignalHandlerId, BoolError> where N: Into<&'a str>, F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static1370 fn connect<'a, N, F>(
1371 &self,
1372 signal_name: N,
1373 after: bool,
1374 callback: F,
1375 ) -> Result<SignalHandlerId, BoolError>
1376 where
1377 N: Into<&'a str>,
1378 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static;
connect_local<'a, N, F>( &self, signal_name: N, after: bool, callback: F, ) -> Result<SignalHandlerId, BoolError> where N: Into<&'a str>, F: Fn(&[Value]) -> Option<Value> + 'static1379 fn connect_local<'a, N, F>(
1380 &self,
1381 signal_name: N,
1382 after: bool,
1383 callback: F,
1384 ) -> Result<SignalHandlerId, BoolError>
1385 where
1386 N: Into<&'a str>,
1387 F: Fn(&[Value]) -> Option<Value> + 'static;
1388 #[allow(clippy::missing_safety_doc)]
connect_unsafe<'a, N, F>( &self, signal_name: N, after: bool, callback: F, ) -> Result<SignalHandlerId, BoolError> where N: Into<&'a str>, F: Fn(&[Value]) -> Option<Value>1389 unsafe fn connect_unsafe<'a, N, F>(
1390 &self,
1391 signal_name: N,
1392 after: bool,
1393 callback: F,
1394 ) -> Result<SignalHandlerId, BoolError>
1395 where
1396 N: Into<&'a str>,
1397 F: Fn(&[Value]) -> Option<Value>;
emit<'a, N: Into<&'a str>>( &self, signal_name: N, args: &[&dyn ToValue], ) -> Result<Option<Value>, BoolError>1398 fn emit<'a, N: Into<&'a str>>(
1399 &self,
1400 signal_name: N,
1401 args: &[&dyn ToValue],
1402 ) -> Result<Option<Value>, BoolError>;
disconnect(&self, handler_id: SignalHandlerId)1403 fn disconnect(&self, handler_id: SignalHandlerId);
1404
connect_notify<F: Fn(&Self, &::ParamSpec) + Send + Sync + 'static>( &self, name: Option<&str>, f: F, ) -> SignalHandlerId1405 fn connect_notify<F: Fn(&Self, &::ParamSpec) + Send + Sync + 'static>(
1406 &self,
1407 name: Option<&str>,
1408 f: F,
1409 ) -> SignalHandlerId;
1410 #[allow(clippy::missing_safety_doc)]
connect_notify_unsafe<F: Fn(&Self, &::ParamSpec)>( &self, name: Option<&str>, f: F, ) -> SignalHandlerId1411 unsafe fn connect_notify_unsafe<F: Fn(&Self, &::ParamSpec)>(
1412 &self,
1413 name: Option<&str>,
1414 f: F,
1415 ) -> SignalHandlerId;
notify<'a, N: Into<&'a str>>(&self, property_name: N)1416 fn notify<'a, N: Into<&'a str>>(&self, property_name: N);
notify_by_pspec(&self, pspec: &::ParamSpec)1417 fn notify_by_pspec(&self, pspec: &::ParamSpec);
1418
downgrade(&self) -> WeakRef<Self>1419 fn downgrade(&self) -> WeakRef<Self>;
1420
bind_property<'a, O: ObjectType, N: Into<&'a str>, M: Into<&'a str>>( &'a self, source_property: N, target: &'a O, target_property: M, ) -> BindingBuilder<'a>1421 fn bind_property<'a, O: ObjectType, N: Into<&'a str>, M: Into<&'a str>>(
1422 &'a self,
1423 source_property: N,
1424 target: &'a O,
1425 target_property: M,
1426 ) -> BindingBuilder<'a>;
1427
ref_count(&self) -> u321428 fn ref_count(&self) -> u32;
1429 }
1430
1431 impl<T: ObjectType> ObjectExt for T {
is<U: StaticType>(&self) -> bool1432 fn is<U: StaticType>(&self) -> bool {
1433 self.get_type().is_a(&U::static_type())
1434 }
1435
get_type(&self) -> Type1436 fn get_type(&self) -> Type {
1437 self.get_object_class().get_type()
1438 }
1439
get_object_class(&self) -> &ObjectClass1440 fn get_object_class(&self) -> &ObjectClass {
1441 unsafe {
1442 let obj: *mut gobject_sys::GObject = self.as_object_ref().to_glib_none().0;
1443 let klass = (*obj).g_type_instance.g_class as *const ObjectClass;
1444 &*klass
1445 }
1446 }
1447
set_properties(&self, property_values: &[(&str, &dyn ToValue)]) -> Result<(), BoolError>1448 fn set_properties(&self, property_values: &[(&str, &dyn ToValue)]) -> Result<(), BoolError> {
1449 use std::ffi::CString;
1450
1451 let pspecs = self.list_properties();
1452
1453 let params = property_values
1454 .iter()
1455 .map(|&(name, value)| {
1456 let pspec = pspecs
1457 .iter()
1458 .find(|p| p.get_name() == name)
1459 .ok_or_else(|| {
1460 glib_bool_error!(
1461 "Can't find property '{}' for type '{}'",
1462 name,
1463 self.get_type()
1464 )
1465 })?;
1466
1467 let mut value = value.to_value();
1468 validate_property_type(self.get_type(), false, &pspec, &mut value)?;
1469 Ok((CString::new(name).unwrap(), value))
1470 })
1471 .collect::<Result<Vec<_>, _>>()?;
1472
1473 for (name, value) in params {
1474 unsafe {
1475 gobject_sys::g_object_set_property(
1476 self.as_object_ref().to_glib_none().0,
1477 name.as_ptr(),
1478 value.to_glib_none().0,
1479 );
1480 }
1481 }
1482
1483 Ok(())
1484 }
1485
set_property<'a, N: Into<&'a str>>( &self, property_name: N, value: &dyn ToValue, ) -> Result<(), BoolError>1486 fn set_property<'a, N: Into<&'a str>>(
1487 &self,
1488 property_name: N,
1489 value: &dyn ToValue,
1490 ) -> Result<(), BoolError> {
1491 let property_name = property_name.into();
1492 let mut property_value = value.to_value();
1493
1494 let pspec = match self.find_property(property_name) {
1495 Some(pspec) => pspec,
1496 None => {
1497 return Err(glib_bool_error!(
1498 "property '{}' of type '{}' not found",
1499 property_name,
1500 self.get_type()
1501 ));
1502 }
1503 };
1504
1505 validate_property_type(self.get_type(), false, &pspec, &mut property_value)?;
1506 unsafe {
1507 gobject_sys::g_object_set_property(
1508 self.as_object_ref().to_glib_none().0,
1509 property_name.to_glib_none().0,
1510 property_value.to_glib_none().0,
1511 );
1512 }
1513
1514 Ok(())
1515 }
1516
get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError>1517 fn get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError> {
1518 let property_name = property_name.into();
1519
1520 let pspec = match self.find_property(property_name) {
1521 Some(pspec) => pspec,
1522 None => {
1523 return Err(glib_bool_error!(
1524 "property '{}' of type '{}' not found",
1525 property_name,
1526 self.get_type()
1527 ));
1528 }
1529 };
1530
1531 if !pspec.get_flags().contains(::ParamFlags::READABLE) {
1532 return Err(glib_bool_error!(
1533 "property '{}' of type '{}' is not readable",
1534 property_name,
1535 self.get_type()
1536 ));
1537 }
1538
1539 unsafe {
1540 let mut value = Value::from_type(pspec.get_value_type());
1541 gobject_sys::g_object_get_property(
1542 self.as_object_ref().to_glib_none().0,
1543 property_name.to_glib_none().0,
1544 value.to_glib_none_mut().0,
1545 );
1546
1547 // This can't really happen unless something goes wrong inside GObject
1548 if value.type_() == ::Type::Invalid {
1549 Err(glib_bool_error!(
1550 "Failed to get property value for property '{}' of type '{}'",
1551 property_name,
1552 self.get_type()
1553 ))
1554 } else {
1555 Ok(value)
1556 }
1557 }
1558 }
1559
set_qdata<QD: 'static>(&self, key: Quark, value: QD)1560 unsafe fn set_qdata<QD: 'static>(&self, key: Quark, value: QD) {
1561 unsafe extern "C" fn drop_value<QD>(ptr: glib_sys::gpointer) {
1562 debug_assert!(!ptr.is_null());
1563 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
1564 drop(value)
1565 }
1566
1567 let ptr = Box::into_raw(Box::new(value)) as glib_sys::gpointer;
1568 gobject_sys::g_object_set_qdata_full(
1569 self.as_object_ref().to_glib_none().0,
1570 key.to_glib(),
1571 ptr,
1572 Some(drop_value::<QD>),
1573 );
1574 }
1575
get_qdata<QD: 'static>(&self, key: Quark) -> Option<&QD>1576 unsafe fn get_qdata<QD: 'static>(&self, key: Quark) -> Option<&QD> {
1577 let ptr =
1578 gobject_sys::g_object_get_qdata(self.as_object_ref().to_glib_none().0, key.to_glib());
1579 if ptr.is_null() {
1580 None
1581 } else {
1582 Some(&*(ptr as *const QD))
1583 }
1584 }
1585
steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD>1586 unsafe fn steal_qdata<QD: 'static>(&self, key: Quark) -> Option<QD> {
1587 let ptr =
1588 gobject_sys::g_object_steal_qdata(self.as_object_ref().to_glib_none().0, key.to_glib());
1589 if ptr.is_null() {
1590 None
1591 } else {
1592 let value: Box<QD> = Box::from_raw(ptr as *mut QD);
1593 Some(*value)
1594 }
1595 }
1596
set_data<QD: 'static>(&self, key: &str, value: QD)1597 unsafe fn set_data<QD: 'static>(&self, key: &str, value: QD) {
1598 self.set_qdata::<QD>(Quark::from_string(key), value)
1599 }
1600
get_data<QD: 'static>(&self, key: &str) -> Option<&QD>1601 unsafe fn get_data<QD: 'static>(&self, key: &str) -> Option<&QD> {
1602 self.get_qdata::<QD>(Quark::from_string(key))
1603 }
1604
steal_data<QD: 'static>(&self, key: &str) -> Option<QD>1605 unsafe fn steal_data<QD: 'static>(&self, key: &str) -> Option<QD> {
1606 self.steal_qdata::<QD>(Quark::from_string(key))
1607 }
1608
block_signal(&self, handler_id: &SignalHandlerId)1609 fn block_signal(&self, handler_id: &SignalHandlerId) {
1610 unsafe {
1611 gobject_sys::g_signal_handler_block(
1612 self.as_object_ref().to_glib_none().0,
1613 handler_id.to_glib(),
1614 );
1615 }
1616 }
1617
unblock_signal(&self, handler_id: &SignalHandlerId)1618 fn unblock_signal(&self, handler_id: &SignalHandlerId) {
1619 unsafe {
1620 gobject_sys::g_signal_handler_unblock(
1621 self.as_object_ref().to_glib_none().0,
1622 handler_id.to_glib(),
1623 );
1624 }
1625 }
1626
stop_signal_emission(&self, signal_name: &str)1627 fn stop_signal_emission(&self, signal_name: &str) {
1628 unsafe {
1629 gobject_sys::g_signal_stop_emission_by_name(
1630 self.as_object_ref().to_glib_none().0,
1631 signal_name.to_glib_none().0,
1632 );
1633 }
1634 }
1635
disconnect(&self, handler_id: SignalHandlerId)1636 fn disconnect(&self, handler_id: SignalHandlerId) {
1637 unsafe {
1638 gobject_sys::g_signal_handler_disconnect(
1639 self.as_object_ref().to_glib_none().0,
1640 handler_id.to_glib(),
1641 );
1642 }
1643 }
1644
connect_notify<F: Fn(&Self, &::ParamSpec) + Send + Sync + 'static>( &self, name: Option<&str>, f: F, ) -> SignalHandlerId1645 fn connect_notify<F: Fn(&Self, &::ParamSpec) + Send + Sync + 'static>(
1646 &self,
1647 name: Option<&str>,
1648 f: F,
1649 ) -> SignalHandlerId {
1650 unsafe { self.connect_notify_unsafe(name, f) }
1651 }
1652
connect_notify_unsafe<F: Fn(&Self, &::ParamSpec)>( &self, name: Option<&str>, f: F, ) -> SignalHandlerId1653 unsafe fn connect_notify_unsafe<F: Fn(&Self, &::ParamSpec)>(
1654 &self,
1655 name: Option<&str>,
1656 f: F,
1657 ) -> SignalHandlerId {
1658 unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &::ParamSpec)>(
1659 this: *mut gobject_sys::GObject,
1660 param_spec: *mut gobject_sys::GParamSpec,
1661 f: glib_sys::gpointer,
1662 ) where
1663 P: ObjectType,
1664 {
1665 let f: &F = &*(f as *const F);
1666 f(
1667 Object::from_glib_borrow(this).unsafe_cast_ref(),
1668 &from_glib_borrow(param_spec),
1669 )
1670 }
1671
1672 let signal_name = if let Some(name) = name {
1673 format!("notify::{}\0", name)
1674 } else {
1675 "notify\0".into()
1676 };
1677
1678 let f: Box<F> = Box::new(f);
1679 ::signal::connect_raw(
1680 self.as_object_ref().to_glib_none().0,
1681 signal_name.as_ptr() as *const _,
1682 Some(mem::transmute::<_, unsafe extern "C" fn()>(
1683 notify_trampoline::<Self, F> as *const (),
1684 )),
1685 Box::into_raw(f),
1686 )
1687 }
1688
notify<'a, N: Into<&'a str>>(&self, property_name: N)1689 fn notify<'a, N: Into<&'a str>>(&self, property_name: N) {
1690 let property_name = property_name.into();
1691
1692 unsafe {
1693 gobject_sys::g_object_notify(
1694 self.as_object_ref().to_glib_none().0,
1695 property_name.to_glib_none().0,
1696 );
1697 }
1698 }
1699
notify_by_pspec(&self, pspec: &::ParamSpec)1700 fn notify_by_pspec(&self, pspec: &::ParamSpec) {
1701 unsafe {
1702 gobject_sys::g_object_notify_by_pspec(
1703 self.as_object_ref().to_glib_none().0,
1704 pspec.to_glib_none().0,
1705 );
1706 }
1707 }
1708
has_property<'a, N: Into<&'a str>>(&self, property_name: N, type_: Option<Type>) -> bool1709 fn has_property<'a, N: Into<&'a str>>(&self, property_name: N, type_: Option<Type>) -> bool {
1710 self.get_object_class().has_property(property_name, type_)
1711 }
1712
get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type>1713 fn get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type> {
1714 self.get_object_class().get_property_type(property_name)
1715 }
1716
find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec>1717 fn find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec> {
1718 self.get_object_class().find_property(property_name)
1719 }
1720
list_properties(&self) -> Vec<::ParamSpec>1721 fn list_properties(&self) -> Vec<::ParamSpec> {
1722 self.get_object_class().list_properties()
1723 }
1724
connect<'a, N, F>( &self, signal_name: N, after: bool, callback: F, ) -> Result<SignalHandlerId, BoolError> where N: Into<&'a str>, F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,1725 fn connect<'a, N, F>(
1726 &self,
1727 signal_name: N,
1728 after: bool,
1729 callback: F,
1730 ) -> Result<SignalHandlerId, BoolError>
1731 where
1732 N: Into<&'a str>,
1733 F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static,
1734 {
1735 unsafe { self.connect_unsafe(signal_name, after, callback) }
1736 }
1737
connect_local<'a, N, F>( &self, signal_name: N, after: bool, callback: F, ) -> Result<SignalHandlerId, BoolError> where N: Into<&'a str>, F: Fn(&[Value]) -> Option<Value> + 'static,1738 fn connect_local<'a, N, F>(
1739 &self,
1740 signal_name: N,
1741 after: bool,
1742 callback: F,
1743 ) -> Result<SignalHandlerId, BoolError>
1744 where
1745 N: Into<&'a str>,
1746 F: Fn(&[Value]) -> Option<Value> + 'static,
1747 {
1748 let callback = crate::ThreadGuard::new(callback);
1749
1750 unsafe {
1751 self.connect_unsafe(signal_name, after, move |values| {
1752 (callback.get_ref())(values)
1753 })
1754 }
1755 }
1756
connect_unsafe<'a, N, F>( &self, signal_name: N, after: bool, callback: F, ) -> Result<SignalHandlerId, BoolError> where N: Into<&'a str>, F: Fn(&[Value]) -> Option<Value>,1757 unsafe fn connect_unsafe<'a, N, F>(
1758 &self,
1759 signal_name: N,
1760 after: bool,
1761 callback: F,
1762 ) -> Result<SignalHandlerId, BoolError>
1763 where
1764 N: Into<&'a str>,
1765 F: Fn(&[Value]) -> Option<Value>,
1766 {
1767 let signal_name: &str = signal_name.into();
1768
1769 let type_ = self.get_type();
1770
1771 let mut signal_id = 0;
1772 let mut signal_detail = 0;
1773
1774 let found: bool = from_glib(gobject_sys::g_signal_parse_name(
1775 signal_name.to_glib_none().0,
1776 type_.to_glib(),
1777 &mut signal_id,
1778 &mut signal_detail,
1779 true.to_glib(),
1780 ));
1781
1782 if !found {
1783 return Err(glib_bool_error!(
1784 "Signal '{}' of type '{}' not found",
1785 signal_name,
1786 type_
1787 ));
1788 }
1789
1790 let mut details = mem::MaybeUninit::zeroed();
1791 gobject_sys::g_signal_query(signal_id, details.as_mut_ptr());
1792 let details = details.assume_init();
1793 if details.signal_id != signal_id {
1794 return Err(glib_bool_error!(
1795 "Signal '{}' of type '{}' not found",
1796 signal_name,
1797 type_
1798 ));
1799 }
1800
1801 // This is actually G_SIGNAL_TYPE_STATIC_SCOPE
1802 let return_type: Type =
1803 from_glib(details.return_type & (!gobject_sys::G_TYPE_FLAG_RESERVED_ID_BIT));
1804 let closure = Closure::new_unsafe(move |values| {
1805 let ret = callback(values);
1806
1807 if return_type == Type::Unit {
1808 if let Some(ret) = ret {
1809 panic!(
1810 "Signal '{}' of type '{}' required no return value but got value of type '{}'",
1811 signal_name,
1812 type_,
1813 ret.type_()
1814 );
1815 }
1816 None
1817 } else {
1818 match ret {
1819 Some(mut ret) => {
1820 let valid_type: bool = from_glib(gobject_sys::g_type_check_value_holds(
1821 mut_override(ret.to_glib_none().0),
1822 return_type.to_glib(),
1823 ));
1824
1825 // If it's not directly a valid type but an object type, we check if the
1826 // actual typed of the contained object is compatible and if so create
1827 // a properly typed Value. This can happen if the type field in the
1828 // Value is set to a more generic type than the contained value
1829 if !valid_type && ret.type_().is_a(&Object::static_type()) {
1830 match ret.get::<Object>() {
1831 Ok(Some(obj)) => {
1832 if obj.get_type().is_a(&return_type) {
1833 ret.0.g_type = return_type.to_glib();
1834 } else {
1835 panic!(
1836 "Signal '{}' of type '{}' required return value of type '{}' but got '{}' (actual '{}')",
1837 signal_name,
1838 type_,
1839 return_type,
1840 ret.type_(),
1841 obj.get_type()
1842 );
1843 }
1844 }
1845 Ok(None) => {
1846 // If the value is None then the type is compatible too
1847 ret.0.g_type = return_type.to_glib();
1848 }
1849 Err(_) => unreachable!("ret type conformity already checked"),
1850 }
1851 } else if !valid_type {
1852 panic!(
1853 "Signal '{}' of type '{}' required return value of type '{}' but got '{}'",
1854 signal_name,
1855 type_,
1856 return_type,
1857 ret.type_()
1858 );
1859 }
1860 Some(ret)
1861 }
1862 None => {
1863 panic!(
1864 "Signal '{}' of type '{}' required return value of type '{}' but got None",
1865 signal_name,
1866 type_,
1867 return_type.name()
1868 );
1869 }
1870 }
1871 }
1872 });
1873 let handler = gobject_sys::g_signal_connect_closure_by_id(
1874 self.as_object_ref().to_glib_none().0,
1875 signal_id,
1876 signal_detail,
1877 closure.to_glib_none().0,
1878 after.to_glib(),
1879 );
1880
1881 if handler == 0 {
1882 Err(glib_bool_error!(
1883 "Failed to connect to signal '{}' of type '{}'",
1884 signal_name,
1885 type_
1886 ))
1887 } else {
1888 Ok(from_glib(handler))
1889 }
1890 }
1891
emit<'a, N: Into<&'a str>>( &self, signal_name: N, args: &[&dyn ToValue], ) -> Result<Option<Value>, BoolError>1892 fn emit<'a, N: Into<&'a str>>(
1893 &self,
1894 signal_name: N,
1895 args: &[&dyn ToValue],
1896 ) -> Result<Option<Value>, BoolError> {
1897 let signal_name: &str = signal_name.into();
1898 unsafe {
1899 let type_ = self.get_type();
1900
1901 let mut signal_id = 0;
1902 let mut signal_detail = 0;
1903
1904 let found: bool = from_glib(gobject_sys::g_signal_parse_name(
1905 signal_name.to_glib_none().0,
1906 type_.to_glib(),
1907 &mut signal_id,
1908 &mut signal_detail,
1909 true.to_glib(),
1910 ));
1911
1912 if !found {
1913 return Err(glib_bool_error!(
1914 "Signal '{}' of type '{}' not found",
1915 signal_name,
1916 type_
1917 ));
1918 }
1919
1920 let mut details = mem::MaybeUninit::zeroed();
1921 gobject_sys::g_signal_query(signal_id, details.as_mut_ptr());
1922 let details = details.assume_init();
1923 if details.signal_id != signal_id {
1924 return Err(glib_bool_error!(
1925 "Signal '{}' of type '{}' not found",
1926 signal_name,
1927 type_
1928 ));
1929 }
1930
1931 if details.n_params != args.len() as u32 {
1932 return Err(
1933 glib_bool_error!(
1934 "Incompatible number of arguments for signal '{}' of type '{}' (expected {}, got {})",
1935 signal_name,
1936 type_,
1937 details.n_params,
1938 args.len(),
1939 )
1940 );
1941 }
1942
1943 for (i, item) in args.iter().enumerate() {
1944 let arg_type =
1945 *(details.param_types.add(i)) & (!gobject_sys::G_TYPE_FLAG_RESERVED_ID_BIT);
1946 if arg_type != item.to_value_type().to_glib() {
1947 return Err(
1948 glib_bool_error!(
1949 "Incompatible argument type in argument {} for signal '{}' of type '{}' (expected {}, got {})",
1950 i,
1951 signal_name,
1952 type_,
1953 arg_type,
1954 item.to_value_type(),
1955 )
1956 );
1957 }
1958 }
1959
1960 let mut v_args: Vec<Value>;
1961 let mut s_args: [Value; 10] = mem::zeroed();
1962 let self_v = {
1963 let mut v = Value::uninitialized();
1964 gobject_sys::g_value_init(v.to_glib_none_mut().0, self.get_type().to_glib());
1965 gobject_sys::g_value_set_object(
1966 v.to_glib_none_mut().0,
1967 self.as_object_ref().to_glib_none().0,
1968 );
1969 v
1970 };
1971 let args = if args.len() < 10 {
1972 s_args[0] = self_v;
1973 for (i, arg) in args.iter().enumerate() {
1974 s_args[i + 1] = arg.to_value();
1975 }
1976 &s_args[0..=args.len()]
1977 } else {
1978 v_args = Vec::with_capacity(args.len() + 1);
1979 v_args.push(self_v);
1980 for arg in args {
1981 v_args.push(arg.to_value());
1982 }
1983 v_args.as_slice()
1984 };
1985
1986 let mut return_value = Value::uninitialized();
1987 if details.return_type != gobject_sys::G_TYPE_NONE {
1988 gobject_sys::g_value_init(return_value.to_glib_none_mut().0, details.return_type);
1989 }
1990
1991 gobject_sys::g_signal_emitv(
1992 mut_override(args.as_ptr()) as *mut gobject_sys::GValue,
1993 signal_id,
1994 signal_detail,
1995 return_value.to_glib_none_mut().0,
1996 );
1997
1998 if return_value.type_() != Type::Unit && return_value.type_() != Type::Invalid {
1999 Ok(Some(return_value))
2000 } else {
2001 Ok(None)
2002 }
2003 }
2004 }
2005
downgrade(&self) -> WeakRef<T>2006 fn downgrade(&self) -> WeakRef<T> {
2007 unsafe {
2008 let w = WeakRef(Box::new(mem::zeroed()), PhantomData);
2009 gobject_sys::g_weak_ref_init(
2010 mut_override(&*w.0),
2011 self.as_object_ref().to_glib_none().0,
2012 );
2013 w
2014 }
2015 }
2016
bind_property<'a, O: ObjectType, N: Into<&'a str>, M: Into<&'a str>>( &'a self, source_property: N, target: &'a O, target_property: M, ) -> BindingBuilder<'a>2017 fn bind_property<'a, O: ObjectType, N: Into<&'a str>, M: Into<&'a str>>(
2018 &'a self,
2019 source_property: N,
2020 target: &'a O,
2021 target_property: M,
2022 ) -> BindingBuilder<'a> {
2023 let source_property = source_property.into();
2024 let target_property = target_property.into();
2025
2026 BindingBuilder::new(self, source_property, target, target_property)
2027 }
2028
ref_count(&self) -> u322029 fn ref_count(&self) -> u32 {
2030 let stash = self.as_object_ref().to_glib_none();
2031 let ptr: *mut gobject_sys::GObject = stash.0;
2032
2033 unsafe { glib_sys::g_atomic_int_get(&(*ptr).ref_count as *const u32 as *const i32) as u32 }
2034 }
2035 }
2036
2037 // Validate that the given property value has an acceptable type for the given property pspec
2038 // and if necessary update the value
validate_property_type( type_: Type, allow_construct_only: bool, pspec: &::ParamSpec, property_value: &mut Value, ) -> Result<(), BoolError>2039 fn validate_property_type(
2040 type_: Type,
2041 allow_construct_only: bool,
2042 pspec: &::ParamSpec,
2043 property_value: &mut Value,
2044 ) -> Result<(), BoolError> {
2045 if !pspec.get_flags().contains(::ParamFlags::WRITABLE)
2046 || (!allow_construct_only && pspec.get_flags().contains(::ParamFlags::CONSTRUCT_ONLY))
2047 {
2048 return Err(glib_bool_error!(
2049 "property '{}' of type '{}' is not writable",
2050 pspec.get_name(),
2051 type_
2052 ));
2053 }
2054
2055 unsafe {
2056 // While GLib actually allows all types that can somehow be transformed
2057 // into the property type, we're more restrictive here to be consistent
2058 // with Rust's type rules. We only allow the exact same type, or if the
2059 // value type is a subtype of the property type
2060 let valid_type: bool = from_glib(gobject_sys::g_type_check_value_holds(
2061 mut_override(property_value.to_glib_none().0),
2062 pspec.get_value_type().to_glib(),
2063 ));
2064
2065 // If it's not directly a valid type but an object type, we check if the
2066 // actual type of the contained object is compatible and if so create
2067 // a properly typed Value. This can happen if the type field in the
2068 // Value is set to a more generic type than the contained value
2069 if !valid_type && property_value.type_().is_a(&Object::static_type()) {
2070 match property_value.get::<Object>() {
2071 Ok(Some(obj)) => {
2072 if obj.get_type().is_a(&pspec.get_value_type()) {
2073 property_value.0.g_type = pspec.get_value_type().to_glib();
2074 } else {
2075 return Err(
2076 glib_bool_error!(
2077 "property '{}' of type '{}' can't be set from the given object type (expected: '{}', got: '{}')",
2078 pspec.get_name(),
2079 type_,
2080 pspec.get_value_type(),
2081 obj.get_type(),
2082 )
2083 );
2084 }
2085 }
2086 Ok(None) => {
2087 // If the value is None then the type is compatible too
2088 property_value.0.g_type = pspec.get_value_type().to_glib();
2089 }
2090 Err(_) => unreachable!("property_value type conformity already checked"),
2091 }
2092 } else if !valid_type {
2093 return Err(glib_bool_error!(format!(
2094 "property '{}' of type '{}' can't be set from the given type (expected: '{}', got: '{}')",
2095 pspec.get_name(),
2096 type_,
2097 pspec.get_value_type(),
2098 property_value.type_(),
2099 )));
2100 }
2101
2102 let changed: bool = from_glib(gobject_sys::g_param_value_validate(
2103 pspec.to_glib_none().0,
2104 property_value.to_glib_none_mut().0,
2105 ));
2106 let change_allowed = pspec.get_flags().contains(::ParamFlags::LAX_VALIDATION);
2107 if changed && !change_allowed {
2108 return Err(glib_bool_error!(
2109 "property '{}' of type '{}' can't be set from given value, it is invalid or out of range",
2110 pspec.get_name(),
2111 type_,
2112 ));
2113 }
2114 }
2115
2116 Ok(())
2117 }
2118
2119 impl ObjectClass {
has_property<'a, N: Into<&'a str>>( &self, property_name: N, type_: Option<Type>, ) -> bool2120 pub fn has_property<'a, N: Into<&'a str>>(
2121 &self,
2122 property_name: N,
2123 type_: Option<Type>,
2124 ) -> bool {
2125 let property_name = property_name.into();
2126 let ptype = self.get_property_type(property_name);
2127
2128 match (ptype, type_) {
2129 (None, _) => false,
2130 (Some(_), None) => true,
2131 (Some(ptype), Some(type_)) => ptype == type_,
2132 }
2133 }
2134
get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type>2135 pub fn get_property_type<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<Type> {
2136 self.find_property(property_name)
2137 .map(|pspec| pspec.get_value_type())
2138 }
2139
find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec>2140 pub fn find_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Option<::ParamSpec> {
2141 let property_name = property_name.into();
2142 unsafe {
2143 let klass = self as *const _ as *const gobject_sys::GObjectClass;
2144
2145 from_glib_none(gobject_sys::g_object_class_find_property(
2146 klass as *mut _,
2147 property_name.to_glib_none().0,
2148 ))
2149 }
2150 }
2151
list_properties(&self) -> Vec<::ParamSpec>2152 pub fn list_properties(&self) -> Vec<::ParamSpec> {
2153 unsafe {
2154 let klass = self as *const _ as *const gobject_sys::GObjectClass;
2155
2156 let mut n_properties = 0;
2157
2158 let props =
2159 gobject_sys::g_object_class_list_properties(klass as *mut _, &mut n_properties);
2160 FromGlibContainer::from_glib_container_num(props, n_properties as usize)
2161 }
2162 }
2163 }
2164
2165 glib_wrapper! {
2166 pub struct InitiallyUnowned(Object<gobject_sys::GInitiallyUnowned, gobject_sys::GInitiallyUnownedClass, InitiallyUnownedClass>);
2167
2168 match fn {
2169 get_type => || gobject_sys::g_initially_unowned_get_type(),
2170 }
2171 }
2172
2173 #[derive(Debug)]
2174 pub struct WeakRef<T: ObjectType>(Box<gobject_sys::GWeakRef>, PhantomData<*const T>);
2175
2176 impl<T: ObjectType> WeakRef<T> {
new() -> WeakRef<T>2177 pub fn new() -> WeakRef<T> {
2178 unsafe {
2179 let w = WeakRef(Box::new(mem::zeroed()), PhantomData);
2180 gobject_sys::g_weak_ref_init(mut_override(&*w.0), ptr::null_mut());
2181 w
2182 }
2183 }
2184
upgrade(&self) -> Option<T>2185 pub fn upgrade(&self) -> Option<T> {
2186 unsafe {
2187 let ptr = gobject_sys::g_weak_ref_get(mut_override(&*self.0));
2188 if ptr.is_null() {
2189 None
2190 } else {
2191 let obj: Object = from_glib_full(ptr);
2192 Some(T::unsafe_from(obj.into()))
2193 }
2194 }
2195 }
2196 }
2197
2198 impl<T: ObjectType> Drop for WeakRef<T> {
drop(&mut self)2199 fn drop(&mut self) {
2200 unsafe {
2201 gobject_sys::g_weak_ref_clear(mut_override(&*self.0));
2202 }
2203 }
2204 }
2205
2206 impl<T: ObjectType> Clone for WeakRef<T> {
clone(&self) -> Self2207 fn clone(&self) -> Self {
2208 unsafe {
2209 let c = WeakRef(Box::new(mem::zeroed()), PhantomData);
2210
2211 let o = gobject_sys::g_weak_ref_get(mut_override(&*self.0));
2212 gobject_sys::g_weak_ref_init(mut_override(&*c.0), o);
2213 if !o.is_null() {
2214 gobject_sys::g_object_unref(o);
2215 }
2216
2217 c
2218 }
2219 }
2220 }
2221
2222 impl<T: ObjectType> Default for WeakRef<T> {
default() -> Self2223 fn default() -> Self {
2224 Self::new()
2225 }
2226 }
2227
2228 unsafe impl<T: ObjectType + Sync + Sync> Sync for WeakRef<T> {}
2229 unsafe impl<T: ObjectType + Send + Sync> Send for WeakRef<T> {}
2230
2231 /// A weak reference to the object it was created for that can be sent to
2232 /// different threads even for object types that don't implement `Send`.
2233 ///
2234 /// Trying to upgrade the weak reference from another thread than the one
2235 /// where it was created on will panic but dropping or cloning can be done
2236 /// safely from any thread.
2237 #[derive(Debug)]
2238 pub struct SendWeakRef<T: ObjectType>(WeakRef<T>, Option<usize>);
2239
2240 impl<T: ObjectType> SendWeakRef<T> {
new() -> SendWeakRef<T>2241 pub fn new() -> SendWeakRef<T> {
2242 SendWeakRef(WeakRef::new(), None)
2243 }
2244
into_weak_ref(self) -> WeakRef<T>2245 pub fn into_weak_ref(self) -> WeakRef<T> {
2246 if self.1.is_some() && self.1 != Some(get_thread_id()) {
2247 panic!("SendWeakRef dereferenced on a different thread");
2248 }
2249
2250 self.0
2251 }
2252 }
2253
2254 impl<T: ObjectType> ops::Deref for SendWeakRef<T> {
2255 type Target = WeakRef<T>;
2256
deref(&self) -> &WeakRef<T>2257 fn deref(&self) -> &WeakRef<T> {
2258 if self.1.is_some() && self.1 != Some(get_thread_id()) {
2259 panic!("SendWeakRef dereferenced on a different thread");
2260 }
2261
2262 &self.0
2263 }
2264 }
2265
2266 // Deriving this gives the wrong trait bounds
2267 impl<T: ObjectType> Clone for SendWeakRef<T> {
clone(&self) -> Self2268 fn clone(&self) -> Self {
2269 SendWeakRef(self.0.clone(), self.1)
2270 }
2271 }
2272
2273 impl<T: ObjectType> Default for SendWeakRef<T> {
default() -> Self2274 fn default() -> Self {
2275 Self::new()
2276 }
2277 }
2278
2279 impl<T: ObjectType> From<WeakRef<T>> for SendWeakRef<T> {
from(v: WeakRef<T>) -> SendWeakRef<T>2280 fn from(v: WeakRef<T>) -> SendWeakRef<T> {
2281 SendWeakRef(v, Some(get_thread_id()))
2282 }
2283 }
2284
2285 unsafe impl<T: ObjectType> Sync for SendWeakRef<T> {}
2286 unsafe impl<T: ObjectType> Send for SendWeakRef<T> {}
2287
2288 #[derive(Debug)]
2289 pub struct BindingBuilder<'a> {
2290 source: &'a ObjectRef,
2291 source_property: &'a str,
2292 target: &'a ObjectRef,
2293 target_property: &'a str,
2294 flags: ::BindingFlags,
2295 transform_to: Option<::Closure>,
2296 transform_from: Option<::Closure>,
2297 }
2298
2299 impl<'a> BindingBuilder<'a> {
new<S: ObjectType, T: ObjectType>( source: &'a S, source_property: &'a str, target: &'a T, target_property: &'a str, ) -> Self2300 fn new<S: ObjectType, T: ObjectType>(
2301 source: &'a S,
2302 source_property: &'a str,
2303 target: &'a T,
2304 target_property: &'a str,
2305 ) -> Self {
2306 Self {
2307 source: source.as_object_ref(),
2308 source_property,
2309 target: target.as_object_ref(),
2310 target_property,
2311 flags: ::BindingFlags::DEFAULT,
2312 transform_to: None,
2313 transform_from: None,
2314 }
2315 }
2316
transform_closure<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>( func: F, ) -> ::Closure2317 fn transform_closure<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>(
2318 func: F,
2319 ) -> ::Closure {
2320 ::Closure::new(move |values| {
2321 assert_eq!(values.len(), 3);
2322 let binding = values[0].get::<::Binding>().unwrap_or_else(|_| {
2323 panic!(
2324 "Type mismatch with the first argument in the closure: expected: `Binding`, got: {:?}",
2325 values[0].type_(),
2326 )
2327 })
2328 .unwrap_or_else(|| {
2329 panic!("Found `None` for the first argument in the closure, expected `Some`")
2330 });
2331 let from = unsafe {
2332 let ptr = gobject_sys::g_value_get_boxed(mut_override(
2333 &values[1] as *const Value as *const gobject_sys::GValue,
2334 ));
2335 assert!(!ptr.is_null());
2336 &*(ptr as *const gobject_sys::GValue as *const Value)
2337 };
2338
2339 match func(&binding, &from) {
2340 None => Some(false.to_value()),
2341 Some(value) => {
2342 unsafe {
2343 gobject_sys::g_value_set_boxed(
2344 mut_override(&values[2] as *const Value as *const gobject_sys::GValue),
2345 &value as *const Value as *const _,
2346 );
2347 }
2348
2349 Some(true.to_value())
2350 }
2351 }
2352 })
2353 }
2354
transform_from<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>( self, func: F, ) -> Self2355 pub fn transform_from<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>(
2356 self,
2357 func: F,
2358 ) -> Self {
2359 Self {
2360 transform_from: Some(Self::transform_closure(func)),
2361 ..self
2362 }
2363 }
2364
transform_to<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>( self, func: F, ) -> Self2365 pub fn transform_to<F: Fn(&::Binding, &Value) -> Option<Value> + Send + Sync + 'static>(
2366 self,
2367 func: F,
2368 ) -> Self {
2369 Self {
2370 transform_to: Some(Self::transform_closure(func)),
2371 ..self
2372 }
2373 }
2374
flags(self, flags: ::BindingFlags) -> Self2375 pub fn flags(self, flags: ::BindingFlags) -> Self {
2376 Self { flags, ..self }
2377 }
2378
build(self) -> Option<::Binding>2379 pub fn build(self) -> Option<::Binding> {
2380 unsafe {
2381 from_glib_none(gobject_sys::g_object_bind_property_with_closures(
2382 self.source.to_glib_none().0,
2383 self.source_property.to_glib_none().0,
2384 self.target.to_glib_none().0,
2385 self.target_property.to_glib_none().0,
2386 self.flags.to_glib(),
2387 self.transform_to.to_glib_none().0,
2388 self.transform_from.to_glib_none().0,
2389 ))
2390 }
2391 }
2392 }
2393