Hi everyone, time for a new release!

Today, it’s all about improving APIs and providing the GdkX11 bindings. Let’s see it more in details!

Change of minimum supported Rust version

The minimum supported Rust version is now 1.40. All the enums provided by the gtk-rs crates now make use of the #[non_exhaustive] attribute to indicate that there might be more values being added in the future.

Updated library versions

All the crates were updated to the latest library versions, that is, APIs that are newly available since GNOME 3.36 are provided by the bindings.

No more new_from_...() and new_with_...()

In GLib-based APIs, a common pattern for constructors is to call them new_from_...() or new_with_...(). In Rust the new_ prefix is usually omitted, so all bindings were changed according to that too.

There might still be a few new_...() functions in the bindings. If you find one and think a different name would be better, please create an issue.

glib-macros

There’s a new crate glib-macros now, which is re-exported by the glib crate and provides a couple of proc-macros

  • #[derive(GBoxed) for easily deriving a boxed type for any Rust type the implements the Clone trait. This can be used to store values of that type in e.g. in glib::Value.
  • #[derive(GEnum)] for integer representation Rust enums, which registers GLib type for them and allows to use them e.g. in a glib::Value.
  • #[gflags], which registers a GLib type for bitflags and wraps around the bitflags crate. Same as above this can then be used e.g. in a glib::Value.

Check the documentation for details about the above.

GdkX11

GTK and its companion library GDK provide various API for interoperability with platform interfaces, like X11 or Wayland or the equivalent APIs on Windows and macOS.

With this release a crate for the X11 integration API for GDK is included.

glib::ThreadPool

GLib provides a thread-pool API, which is now included in the bindings. There are many crates that provide similar functionality but nothing that is part of std yet, as such the addition seemed useful unlike adding bindings for the threading primitives in GLib.

The ThreadPool bindings allow to create shared or exclusive thread pools, where the shared thread pools are sharing their threads with other shared ones. The maximum number of threads and various other parameters can be configured on each thread pool, see the docs.

After creation, new tasks can be pushed on the thread pool as a closure. Optionally a Future can be returned to get notified about the completion of the task.

let pool = ThreadPool::new_exclusive(1)?;

// Runs `do_something()` on the thread pool and doesn't wait
pool.push(|| {
    do_something();
});

// Runs `do_something_else()` on the thread pool and returns its
// return value via a `Future`
let fut = pool.push_future(|| {
    let res = do_something_else();
    res
});

// Asynchronously await the result of `do_something_else()`
let res = fut.await;

Storage of arbitrary data in glib::Objects

In C, GObject provides the ability to store arbitrary data on any object. Until this release this was not provided by the bindings as it generally is used as a workaround for a suboptimal architecture, and most importantly because all type information for the stored data is lost.

In this release unsafe API for making use of this is provided but it’s the caller’s responsibility to ensure that the types are matching.

let button = gtk::Button::with_label("test");

unsafe {
    button.set_data("my-data", String::new("my-data-value"));
    let my_data = button.get_data("my-data");
}

Before using this please make sure there is no better solution for what you’re trying to achieve.

cairo::Error instead of cairo::Status

Previously all cairo functions that could fail were returning a Status enum in one way or another. This lead to unidiomatic error handling in Rust applications.

In this release the Status enum was replaced by an Error enum that only includes errors cases and is returned as part of the error case of Results. This allows doing normal Rust error handling via the ? operator, for example.

cairo features

The FreeType and script features of the cairo bindings are now optional with this release. It was already possible to compile the cairo C library without them but the bindings assumed these features to always exist.

If you make use of these features you now need to enable them when depending on the cairo crate.

GDBus

GLib comes with its own DBus IPC implementation. Starting with this release big parts of the API are included in the bindings and it is for example possible to create DBus services or use existing DBus services.

The API is very close to the C API and as such not very convenient to use yet, but more convenient APIs can be built on top of this in external crates or maybe in future versions of the bindings. More to see later!

No more Widget::destroy()

The gtk::Widget::destroy() function is marked as unsafe starting from this release. Calling it on arbitrary widgets can cause all kinds of negative side-effects and should be prevented.

Most usages of destroy() were related to dialogs or other windows. Instead of destroy() the safer close() can be used now, which also allows the window to handle the event.

More subclassing support in gtk

This new release features subclassing support for many additional types: IconView, CellRenderers (Pixbuf, Text, Spinner, Progress, Toggle, Accel, Combo, Spin), DrawingArea, Plug, Socket and Fixed.

Together with all the ones that existed in previous releases, the most commonly used types in GTK where subclassing is useful should be covered. If some are missing, please open issues so we can add them.

Conclusion

This release took us a lot of time but as you can see, it was definitely worth it. We expect to provide even more tools to make gtk-rs development as fun as possible and to continue to improve the bindings. More to come soon!

Changes

For the interested ones, here is the list of the merged pull requests:

sys:

glib:

cairo:

sourceview:

atk:

gio:

pango:

gdk-pixbuf:

gdk:

gtk:

pangocairo:

gtk-test:

All this was possible thanks to the gtk-rs/gir project as well:

Thanks to all of our contributors for their (awesome!) work on this release: