TLDR: more automation, cargo features are back, more breaking changes than ever, increased linking flexibility.

This update breaks just about everything. It might not leave a stone unturned in your code. It also discards a lot of technical debt from the rgtk times.

Object reform has landed

Thanks to @EPashkin’s work on gir the gtk crate is largely machine-generated now. At the time of this writing there are 155 autogenerated modules vs 28 manual ones. This makes refactorings much easier, which brings us to the long promised Object reform:

  • Unified smart pointers (see glib docs) implement dynamic casts and standard traits (Clone, Eq, Ord, Hash).

  • Extension trait suffix has changed from Trait to Ext (e.g. ButtonTrait -> ButtonExt).

  • The APIs have become more consistent with upstream in these respects:

    • Constructors never fail so they don’t return Option.

    • Generally, some parameters and return values became optional (notably Label::new, TreeView::set_model) while others lost the Option (e.g. TreeView::get_selection).

    • Spelling (e.g. Notebook, WindowExt::set_position).

    • Dialog APIs have reverted to more C-like form for the time being.

    We’re not reverting to C conventions indiscriminately though:

  • The APIs are also gradually getting Rust-yfied in these ways:

    • “Out” parameters are moved into return values. If the function returns a boolean, the return type becomes optional. Example from EditableExt:

      fn get_selection_bounds(&self) -> Option<(i32, i32)>

    • Represent i32s that can’t be negative (or only have special negative values) as u16, u32 or enums. This has been done for EntryBuffer, Notebook and TreeSortable, partially done for ListStore and TreeStore. The above method will eventually look like:

      fn get_selection_bounds(&self) -> Option<(u32, u32)>

    • File names take T: AsRef<Path> instead of &str now.

  • Added bindings for Application, ApplicationWindow, Gesture*, made Widget and Window bindings more comprehensive.

Note that the generator is far from being complete, there is still a lot of work to do.

Cargo features are back

I’ve realized that removing version features had, on balance, been a bad idea. The principal reason is that occasionally new upstream versions do introduce minor breaking changes. Consequently, simply updating the installed libraries could trigger confusing build failures.

Explicitly selecting the version avoids sudden breakage and keeps the user conscious and in control of their project’s requirements.

  • The version features have been reintroduced. The baseline GTK+ version is 3.4, you can opt into higher versions like this:

    version = "0.0.7"
    features = ["v3_8"]


    gtk = { version = "0.0.7", features = ["v3_8"] }
  • cairo-rs has got a non-version feature png.

Other breaking improvements


Last year we had to exile the API docs into the appropriately licensed lgpl-docs repo. @GuillaumeGomez has since taught rustdoc-stripper to put them back: you can embed the documentation into your local copy of the crates via the embed-lgpl-docs feature.

The documentation in the lgpl-docs repo is (for all crates but cairo) exclusively generated from upstream at this time. The upstream documentation was written in the C context so some bits won’t make sense for Rust. Correcting such bits is going to be our next documentation milestone.


  • Although the sys crates attempt to use pkg-config by default, if it’s not found the build proceeds expecting the linker to find them in the default search path.

  • Setting the GTK_LIB_DIR env variable bypasses pkg-config altogether, adding its value to the search path and using hard-coded library names.

  • On Windows as a work-around for the cannot find -limm32 issue the list of library names is always hardcoded even if pkg-config supplies the search paths and version checks. You no longer need to delete Rust’s bundled gcc.exe.