@@ -947,7 +947,7 @@ impl<T: ObjectType> ObjectExt for T {
947
947
948
948
fn set_property < ' a , N : Into < & ' a str > > ( & self , property_name : N , value : & ToValue ) -> Result < ( ) , BoolError > {
949
949
let property_name = property_name. into ( ) ;
950
- let property_value = value. to_value ( ) ;
950
+ let mut property_value = value. to_value ( ) ;
951
951
952
952
let pspec = match self . find_property ( property_name) {
953
953
Some ( pspec) => pspec,
@@ -968,12 +968,28 @@ impl<T: ObjectType> ObjectExt for T {
968
968
let valid_type: bool = from_glib ( gobject_ffi:: g_type_check_value_holds (
969
969
mut_override ( property_value. to_glib_none ( ) . 0 ) ,
970
970
pspec. get_value_type ( ) . to_glib ( ) ) ) ;
971
- if !valid_type {
971
+
972
+ // If it's not directly a valid type but an object type, we check if the
973
+ // actual type of the contained object is compatible and if so create
974
+ // a properly type Value. This can happen if the type field in the
975
+ // Value is set to a more generic type than the contained value
976
+ if !valid_type && property_value. type_ ( ) . is_a ( & Object :: static_type ( ) ) {
977
+ if let Some ( obj) = property_value. get :: < Object > ( ) {
978
+ if obj. get_type ( ) . is_a ( & pspec. get_value_type ( ) ) {
979
+ property_value. 0 . g_type = pspec. get_value_type ( ) . to_glib ( ) ;
980
+ } else {
981
+ return Err ( glib_bool_error ! ( "property can't be set from the given object type" ) ) ;
982
+ }
983
+ } else {
984
+ // Otherwise if the value is None then the type is compatible too
985
+ property_value. 0 . g_type = pspec. get_value_type ( ) . to_glib ( ) ;
986
+ }
987
+ } else if !valid_type {
972
988
return Err ( glib_bool_error ! ( "property can't be set from the given type" ) ) ;
973
989
}
974
990
975
991
let changed: bool = from_glib ( gobject_ffi:: g_param_value_validate (
976
- pspec. to_glib_none ( ) . 0 , mut_override ( property_value. to_glib_none ( ) . 0 ) ) ) ;
992
+ pspec. to_glib_none ( ) . 0 , property_value. to_glib_none_mut ( ) . 0 ) ) ;
977
993
let change_allowed = pspec. get_flags ( ) . contains ( :: ParamFlags :: LAX_VALIDATION ) ;
978
994
if changed && !change_allowed {
979
995
return Err ( glib_bool_error ! (
@@ -1139,11 +1155,28 @@ impl<T: ObjectType> ObjectExt for T {
1139
1155
None
1140
1156
} else {
1141
1157
match ret {
1142
- Some ( ret) => {
1158
+ Some ( mut ret) => {
1143
1159
let valid_type: bool = from_glib ( gobject_ffi:: g_type_check_value_holds (
1144
1160
mut_override ( ret. to_glib_none ( ) . 0 ) ,
1145
1161
return_type. to_glib ( ) ) ) ;
1146
- if !valid_type {
1162
+
1163
+ // If it's not directly a valid type but an object type, we check if the
1164
+ // actual typed of the contained object is compatible and if so create
1165
+ // a properly typed Value. This can happen if the type field in the
1166
+ // Value is set to a more generic type than the contained value
1167
+ if !valid_type && ret. type_ ( ) . is_a ( & Object :: static_type ( ) ) {
1168
+ if let Some ( obj) = ret. get :: < Object > ( ) {
1169
+ if obj. get_type ( ) . is_a ( & return_type) {
1170
+ ret. 0 . g_type = return_type. to_glib ( ) ;
1171
+ } else {
1172
+ panic ! ( "Signal required return value of type {} but got {} (actual {})" ,
1173
+ return_type. name( ) , ret. type_( ) . name( ) , obj. get_type( ) . name( ) ) ;
1174
+ }
1175
+ } else {
1176
+ // Otherwise if the value is None then the type is compatible too
1177
+ ret. 0 . g_type = return_type. to_glib ( ) ;
1178
+ }
1179
+ } else if !valid_type {
1147
1180
panic ! ( "Signal required return value of type {} but got {}" ,
1148
1181
return_type. name( ) , ret. type_( ) . name( ) ) ;
1149
1182
}
0 commit comments