diff --git a/glib-macros/src/properties.rs b/glib-macros/src/properties.rs index 1645f1365511..88490b9198d4 100644 --- a/glib-macros/src/properties.rs +++ b/glib-macros/src/properties.rs @@ -379,13 +379,24 @@ fn expand_property_fn(props: &[PropDesc]) -> TokenStream2 { ), (None, MaybeCustomFn::Default) => quote!( DerivedPropertiesEnum::#enum_ident => - #crate_ident::PropertyGet::get(&self.#field_ident, |v| ::std::convert::From::from(v)) + #crate_ident::PropertyGet::get( + &self.#field_ident, + |v| #crate_ident::PropertyGet::get( + v, + |v| ::std::convert::From::from(v) + ) + ) ), (Some(member), MaybeCustomFn::Default) => quote!( DerivedPropertiesEnum::#enum_ident => - #crate_ident::PropertyGet::get(&self.#field_ident, |v| ::std::convert::From::from(&v.#member)) - + #crate_ident::PropertyGet::get( + &self.#field_ident, + |v| #crate_ident::PropertyGet::get( + &v.#member, + |v| ::std::convert::From::from(v) + ) + ) ), }; quote_spanned!(span=> #body) @@ -415,6 +426,7 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 { field_ident, member, set, + ty, .. } = p; @@ -426,22 +438,28 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 { let body = match (member, set) { (_, MaybeCustomFn::Custom(expr)) => quote!( DerivedPropertiesEnum::#enum_ident => { - (#expr)(&self, #crate_ident::Value::get(value)#expect); + let value: <#ty as #crate_ident::Property>::Value = + #crate_ident::Value::get(value)#expect; + (#expr)(&self, ::std::convert::From::from(value)); } ), (None, MaybeCustomFn::Default) => quote!( DerivedPropertiesEnum::#enum_ident => { + let value: <#ty as #crate_ident::Property>::Value = + #crate_ident::Value::get(value)#expect; #crate_ident::PropertySet::set( &self.#field_ident, - #crate_ident::Value::get(value)#expect + ::std::convert::From::from(value) ); } ), (Some(member), MaybeCustomFn::Default) => quote!( DerivedPropertiesEnum::#enum_ident => { + let value: <#ty as #crate_ident::Property>::Value = + #crate_ident::Value::get(value)#expect; #crate_ident::PropertySetNested::set_nested( &self.#field_ident, - move |v| v.#member = #crate_ident::Value::get(value)#expect + move |v| v.#member = ::std::convert::From::from(value) ); } ), diff --git a/glib-macros/tests/properties.rs b/glib-macros/tests/properties.rs index ba0c0df40361..5a8a612e6987 100644 --- a/glib-macros/tests/properties.rs +++ b/glib-macros/tests/properties.rs @@ -68,6 +68,7 @@ mod foo { use std::sync::Mutex; use super::base::Base; + use glib::thread_guard::ThreadGuard; #[derive(Clone, Default, Debug, PartialEq, Eq, glib::Boxed)] #[boxed_type(name = "SimpleBoxedString")] @@ -86,6 +87,24 @@ mod foo { nick: String, } + // Custom type, behaving as the inner type + #[derive(Default)] + pub struct MyInt(i32); + impl glib::Property for MyInt { + type Value = i32; + } + impl glib::PropertyGet for MyInt { + type Value = i32; + fn get R>(&self, f: F) -> R { + f(&self.0) + } + } + impl From for MyInt { + fn from(v: i32) -> Self { + MyInt(v) + } + } + pub mod imp { use glib::{ParamSpec, Value}; use std::rc::Rc; @@ -101,10 +120,16 @@ mod foo { double: RefCell, #[property(get = |_| 42.0, set)] infer_inline_type: RefCell, + #[property(get, set)] + custom_type: RefCell, // The following property doesn't store any data. The value of the property is calculated // when the value is accessed. #[property(get = Self::hello_world)] _buzz: PhantomData, + #[property(get, set)] + thread_guard_wrapped: Mutex>, + #[property(get, set)] + thread_guard_wrapping: ThreadGuard>, #[property(get, set = Self::set_fizz, name = "fizz", nick = "fizz-nick", blurb = "short description stored in the GLib type system" )] @@ -220,6 +245,15 @@ fn props() { let author_name: String = myfoo.property("author-nick"); assert_eq!(author_name, "freddy-nick".to_string()); + // Complex wrapping + myfoo.set_property("thread-guard-wrapped", 2u32.to_value()); + let v: u32 = myfoo.property("thread-guard-wrapped"); + assert_eq!(v, 2); + + myfoo.set_property("thread-guard-wrapping", 3u32.to_value()); + let v: u32 = myfoo.property("thread-guard-wrapping"); + assert_eq!(v, 3); + // read_only assert_eq!( myfoo.find_property("read_only_text").unwrap().flags(), diff --git a/glib/src/property.rs b/glib/src/property.rs index 2183b9b4c867..4eed6bdf6abd 100644 --- a/glib/src/property.rs +++ b/glib/src/property.rs @@ -1,5 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. +use crate::thread_guard::ThreadGuard; use std::cell::Cell; use std::cell::RefCell; use std::marker::PhantomData; @@ -37,6 +38,9 @@ impl Property for Mutex { impl Property for RwLock { type Value = T::Value; } +impl Property for ThreadGuard { + type Value = T::Value; +} impl Property for once_cell::sync::OnceCell { type Value = T::Value; } @@ -138,6 +142,19 @@ impl PropertySetNested for RwLock { } } +impl PropertyGet for ThreadGuard { + type Value = T::Value; + fn get R>(&self, f: F) -> R { + self.get_ref().get(f) + } +} +impl PropertySetNested for ThreadGuard { + type SetNestedValue = T::SetNestedValue; + fn set_nested(&self, f: F) { + self.get_ref().set_nested(f) + } +} + impl PropertyGet for once_cell::sync::OnceCell { type Value = T; fn get R>(&self, f: F) -> R { diff --git a/glib/src/thread_guard.rs b/glib/src/thread_guard.rs index f3b4c6175076..67c58e4396e2 100644 --- a/glib/src/thread_guard.rs +++ b/glib/src/thread_guard.rs @@ -112,3 +112,15 @@ impl Drop for ThreadGuard { } unsafe impl Send for ThreadGuard {} + +impl Default for ThreadGuard { + fn default() -> Self { + Self::new(T::default()) + } +} + +impl From for ThreadGuard { + fn from(value: T) -> Self { + ThreadGuard::new(value) + } +}