Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.17 backports #1116

Merged
merged 10 commits into from
Jun 6, 2023
3 changes: 2 additions & 1 deletion cairo/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,11 @@ mod test {
*surface.finish_output_stream().unwrap().downcast().unwrap()
}

#[track_caller]
fn assert_len_close_enough(len_a: usize, len_b: usize) {
// It seems cairo randomizes some element IDs which might make one svg slightly
// larger than the other. Here we make sure the difference is within ~10%.
let len_diff = (len_a as isize - len_b as isize).abs() as usize;
let len_diff = usize::abs_diff(len_a, len_b);
assert!(len_diff < len_b / 10);
}

Expand Down
2 changes: 1 addition & 1 deletion gdk-pixbuf/sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ name = "gdk_pixbuf_sys"
authors = ["The gtk-rs Project Developers"]
build = "build.rs"
description = "FFI bindings to libgdk_pixbuf-2.0"
homepage = "http://gtk-rs.org/"
homepage = "https://gtk-rs.org/"
keywords = ["gdk-pixbuf", "ffi", "gtk-rs", "gnome"]
license = "MIT"
name = "gdk-pixbuf-sys"
Expand Down
3 changes: 3 additions & 0 deletions gio/Gir.toml
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ manual_traits = ["DebugControllerDBusExtManual"]
[[object]]
name = "Gio.DesktopAppInfo"
status = "generate"
manual_traits = ["DesktopAppInfoExtManual"]
cfg_condition = "all(not(windows),not(target_os = \"macos\"))"
[[object.function]]
name = "get_boolean"
Expand Down Expand Up @@ -845,6 +846,7 @@ concurrency = "send+sync"
[[object]]
name = "Gio.InetAddress"
status = "generate"
manual_traits = ["InetAddressExtManual"]
concurrency = "send+sync"
[[object.function]]
name = "new_from_bytes"
Expand Down Expand Up @@ -1121,6 +1123,7 @@ status = "generate"
[[object]]
name = "Gio.Settings"
status = "generate"
manual_traits = ["SettingsExtManual"]
[[object.signal]]
name = "writable-change-event"
inhibit = true
Expand Down
2 changes: 1 addition & 1 deletion gio/sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ name = "gio_sys"
authors = ["The gtk-rs Project Developers"]
build = "build.rs"
description = "FFI bindings to libgio-2.0"
homepage = "http://gtk-rs.org/"
homepage = "https://gtk-rs.org/"
keywords = ["gio", "ffi", "gtk-rs", "gnome"]
license = "MIT"
name = "gio-sys"
Expand Down
7 changes: 4 additions & 3 deletions glib-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {

/// This macro enables you to derive object properties in a quick way.
///
/// # Supported #[property] attributes
/// # Supported `#[property]` attributes
/// | Attribute | Description | Default | Example |
/// | --- | --- | --- | --- |
/// | `name = "literal"` | The name of the property | field ident where `_` (leading and trailing `_` are trimmed) is replaced into `-` | `#[property(name = "prop-name")]` |
Expand All @@ -862,7 +862,8 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
/// | `override_interface = expr` | The type of interface of which to override the property from | | `#[property(override_interface = SomeInterface)]` |
/// | `nullable` | Whether to use `Option<T>` in the wrapper's generated setter | | `#[property(nullable)]` |
/// | `member = ident` | Field of the nested type where property is retrieved and set | | `#[property(member = author)]` |
/// | `builder(<required-params>)[.ident]*` | Used to input required params or add optional Param Spec builder fields | | `#[property(builder(SomeEnum::default()))]`, `#[builder().default_value(1).construct_only()]`, etc. |
/// | `construct_only` | Specify that the property is construct only. This will not generate a public setter and only allow the property to be set during object construction. The use of a custom internal setter is supported. | | `#[property(get, construct_only)]` or `#[property(get, set = set_prop, construct_only)]` |
/// | `builder(<required-params>)[.ident]*` | Used to input required params or add optional Param Spec builder fields | | `#[property(builder(SomeEnum::default()))]`, `#[builder().default_value(1).minimum(0).maximum(5)]`, etc. |
/// | `default` | Sets the `default_value` field of the Param Spec builder | | `#[property(default = 1)]` |
/// | `<optional-pspec-builder-fields> = expr` | Used to add optional Param Spec builder fields | | `#[property(minimum = 0)` , `#[property(minimum = 0, maximum = 1)]`, etc. |
/// | `<optional-pspec-builder-fields>` | Used to add optional Param Spec builder fields | | `#[property(explicit_notify)]` , `#[property(construct_only)]`, etc. |
Expand All @@ -883,7 +884,7 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
///
/// # Internal getters and setters
/// By default, they are generated for you. However, you can use a custom getter/setter
/// by assigning an expression to `get`/`set` #[property] attributes: `#[property(get = |_| 2, set)]` or `#[property(get, set = custom_setter_func)]`.
/// by assigning an expression to `get`/`set` `#[property]` attributes: `#[property(get = |_| 2, set)]` or `#[property(get, set = custom_setter_func)]`.
///
/// # Supported types
/// Every type implementing the trait `Property` is supported.
Expand Down
14 changes: 11 additions & 3 deletions glib-macros/src/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ struct PropDesc {
member: Option<syn::Ident>,
builder: Option<(Punctuated<syn::Expr, Token![,]>, TokenStream2)>,
builder_fields: HashMap<syn::Ident, Option<syn::Expr>>,
is_construct_only: bool,
}

impl PropDesc {
Expand All @@ -248,7 +249,7 @@ impl PropDesc {
let ReceivedAttrs {
nullable,
get,
set,
mut set,
override_class,
override_interface,
ty,
Expand All @@ -258,6 +259,12 @@ impl PropDesc {
builder_fields,
} = attrs;

let is_construct_only = builder_fields.iter().any(|(k, _)| *k == "construct_only");
if is_construct_only && set.is_none() {
// Insert a default internal setter automatically
set = Some(MaybeCustomFn::Default);
}

if get.is_none() && set.is_none() {
return Err(syn::Error::new(
attrs_span,
Expand Down Expand Up @@ -295,6 +302,7 @@ impl PropDesc {
member,
builder,
builder_fields,
is_construct_only,
})
}
}
Expand Down Expand Up @@ -534,8 +542,8 @@ fn expand_wrapper_getset_properties(props: &[PropDesc]) -> TokenStream2 {
self.property::<<#ty as #crate_ident::Property>::Value>(#stripped_name)
})
});
let is_construct_only = p.builder_fields.iter().any(|(k, _)| *k == "construct_only");
let setter = (p.set.is_some() && !is_construct_only).then(|| {

let setter = (p.set.is_some() && !p.is_construct_only).then(|| {
let ident = format_ident!("set_{}", ident);
let target_ty = quote!(<<#ty as #crate_ident::Property>::Value as #crate_ident::HasParamSpec>::SetValue);
let set_ty = if p.nullable {
Expand Down
26 changes: 25 additions & 1 deletion glib-macros/tests/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ mod foo {
weak_ref_prop: glib::WeakRef<glib::Object>,
#[property(get, set)]
send_weak_ref_prop: glib::SendWeakRef<glib::Object>,
#[property(get, default_value = 0, construct_only)]
construct_only_cell: OnceCell<u32>,
#[property(get, set = Self::set_construct_only_custom, construct_only)]
construct_only_custom_setter: OnceCell<Option<String>>,
}

impl ObjectImpl for Foo {
Expand Down Expand Up @@ -194,6 +198,11 @@ mod foo {
fn overridden(&self) -> u32 {
43
}
fn set_construct_only_custom(&self, value: Option<String>) {
self.construct_only_custom_setter
.set(value.map(|v| format!("custom set: {}", v)))
.expect("Setter to be only called once");
}
}
}

Expand Down Expand Up @@ -382,7 +391,22 @@ fn props() {
// object subclass
let myobj = glib::BoxedAnyObject::new("");
myfoo.set_object(Some(myobj.upcast_ref()));
assert_eq!(myfoo.object(), Some(myobj.upcast()))
assert_eq!(myfoo.object(), Some(myobj.upcast()));

// construct_only
let myfoo: foo::Foo = glib::object::Object::builder()
.property("construct-only-cell", 1u32)
.build();
assert_eq!(myfoo.construct_only_cell(), 1u32);

// construct_only with custom setter
let myfoo: foo::Foo = glib::object::Object::builder()
.property("construct-only-custom-setter", "foo")
.build();
assert_eq!(
myfoo.construct_only_custom_setter(),
Some("custom set: foo".to_owned())
);
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion glib/gobject-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ name = "gobject_sys"
authors = ["The gtk-rs Project Developers"]
build = "build.rs"
description = "FFI bindings to libgobject-2.0"
homepage = "http://gtk-rs.org/"
homepage = "https://gtk-rs.org/"
keywords = ["gobject", "ffi", "gtk-rs", "gnome"]
license = "MIT"
name = "gobject-sys"
Expand Down
3 changes: 2 additions & 1 deletion glib/src/collections/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ impl<T: TransparentPtrType> List<T> {
/// Consumes the list and returns the underlying pointer.
#[inline]
pub fn into_raw(mut self) -> *mut ffi::GList {
mem::replace(&mut self.ptr, None)
self.ptr
.take()
.map(|p| p.as_ptr())
.unwrap_or(ptr::null_mut())
}
Expand Down
3 changes: 2 additions & 1 deletion glib/src/collections/slist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,8 @@ impl<T: TransparentPtrType> SList<T> {
/// Consumes the list and returns the underlying pointer.
#[inline]
pub fn into_raw(mut self) -> *mut ffi::GSList {
mem::replace(&mut self.ptr, None)
self.ptr
.take()
.map(|p| p.as_ptr())
.unwrap_or(ptr::null_mut())
}
Expand Down
33 changes: 32 additions & 1 deletion glib/src/collections/strv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,21 @@ impl<'a, const N: usize> From<[&'a str; N]> for StrV {
}
}

impl<'a, const N: usize> From<[&'a GStr; N]> for StrV {
#[inline]
fn from(value: [&'a GStr; N]) -> Self {
unsafe {
let mut s = Self::with_capacity(value.len());
for (i, item) in value.iter().enumerate() {
*s.ptr.as_ptr().add(i) = GString::from(*item).into_glib_ptr();
}
s.len = value.len();
*s.ptr.as_ptr().add(s.len) = ptr::null_mut();
s
}
}
}

impl<'a> From<&'a [&'a str]> for StrV {
#[inline]
fn from(value: &'a [&'a str]) -> Self {
Expand Down Expand Up @@ -446,8 +461,10 @@ impl StrV {
if len == 0 {
StrV::default()
} else {
// Allocate space for len + 1 pointers, one pointer for each string and a trailing
// null pointer.
let new_ptr =
ffi::g_malloc(mem::size_of::<*mut c_char>() * len + 1) as *mut *mut c_char;
ffi::g_malloc(mem::size_of::<*mut c_char>() * (len + 1)) as *mut *mut c_char;

// Need to clone every item because we don't own it here
for i in 0..len {
Expand Down Expand Up @@ -1396,6 +1413,20 @@ mod test {
}
}

#[test]
fn test_from_slice() {
let items = [
crate::gstr!("str1"),
crate::gstr!("str2"),
crate::gstr!("str3"),
];

let slice1 = StrV::from(&items[..]);
let slice2 = StrV::from(items);
assert_eq!(slice1.len(), 3);
assert_eq!(slice1, slice2);
}

#[test]
fn test_safe_api() {
let items = [
Expand Down
3 changes: 1 addition & 2 deletions glib/src/main_context_futures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,11 +620,10 @@ impl MainContext {
pub fn block_on<F: Future>(&self, f: F) -> F::Output {
let mut res = None;
let l = MainLoop::new(Some(self), false);
let l_clone = l.clone();

let f = async {
res = Some(panic::AssertUnwindSafe(f).catch_unwind().await);
l_clone.quit();
l.quit();
};

let f = unsafe {
Expand Down
Loading