New Release
This is the blog post release for gtk4-rs 0.8
and gtk-rs-core 0.19
.
Although this release happened a few months ago, we finally had time to finish this release blog post!
This is a smaller release than usual, bringing some nice quality of life improvements.
Enjoy!
gtk3 §
Support for gtk3-rs crates was dropped. No more updates will be done on it. If you didn’t yet, please migrate to gtk4-rs.
gtk-rs-core §
Removal of glib channels §
In this release the glib::MainContext::channel()
function was removed, together with the corresponding sender/receiver types. In many cases this API has led to overly complicated code in applications because people tried to develop state machines via callbacks, instead of simply making use of async Rust for that purpose.
Instead of using the main context channel, the new way of passing values between other threads and the main thread is by using any of the many async channel implementations. Examples for this are the async-channel crate, the MPSC channels from tokio or async-std, the task/thread join handles of both, the flume crate, …
For example, the following code:
let (sender, receiver) = glib::MainContext::channel(glib::Priority::DEFAULT);
receiver.attach(Some(&glib::MainContext::default()), move |msg| do_things(msg));
sender.send(MyMessage);
Could be rewritten like this with the async-channel
crate:
let (sender, receiver) = async_channel::unbounded();
glib::MainContext::default().spawn_local(async move {
while let Ok(msg) = receiver.recv().await {
do_things(msg);
}
});
sender.send_blocking(MyMessage).expect("Channel closed");
Removal of re-exported once_cell crate, use std::cell::OnceCell
/ std::sync::OnceLock
§
If you need lazy initialization then once_cell::sync::Lazy
is still useful until LazyCell
/ LazyLock
from std
are finalized.
Re-organized traits in glib §
If you get a compiler error because of missing traits, usually the solution would be to make sure that the prelude of the crates (e.g. gtk::prelude::*
) is imported.
Dynamic types support §
Let’s say you want to create a plugin to add some features or to customize some application. object_class_dynamic
, object_interface_dynamic
, enum_dynamic
and flags_dynamic
are macro helper attributes to make your types dynamic.
// My object types
#[derive(Default)]
pub struct MyType;
#[glib::object_subclass]
#[object_subclass_dynamic]
impl ObjectSubclass for MyType { ... }
// My interfaces
pub struct MyInterface {
parent: glib::gobject_ffi::GTypeInterface,
}
#[glib::object_interface]
#[object_interface_dynamic]
unsafe impl ObjectInterface for MyInterface { ... }
// My enums
#[derive(Debug, Copy, Clone, PartialEq, Eq, glib::Enum)]
#[enum_type(name = "MyModuleEnum")]
#[enum_dynamic]
enum MyModuleEnum { ... }
// My flags
#[glib::flags(name = "MyFlags")]
#[flags_dynamic]
enum MyFlags { ... }
Your plugin code has to implement the TypePlugin
interface or to extend the TypeModule
type in order to register or unregister your dynamic types when the module (or plugin) is loaded or unloaded.
#[derive(Default)]
pub struct MyModule;
#[glib::object_subclass]
impl ObjectSubclass for MyModule { ... }
impl ObjectImpl for MyModule {}
impl TypePluginImpl for MyModule {}
impl TypeModuleImpl for MyModule {
fn load(&self) -> bool {
// registers my plugin types as dynamic types.
let my_module = self.obj();
let type_module: &glib::TypeModule = my_module.upcast_ref();
MyInterface::on_implementation_load(type_module)
&& MyType::on_implementation_load(type_module)
&& MyEnum::on_implementation_load(type_module)
&& MyFlags::on_implementation_load(type_module)
}
fn unload(&self) {
// marks my plugin types as unregistered.
let my_module = self.obj();
let type_module: &glib::TypeModule = my_module.upcast_ref();
MyFlags::on_implementation_unload(type_module);
MyEnum::on_implementation_unload(type_module);
MyType::on_implementation_unload(type_module);
MyInterface::on_implementation_unload(type_module);
}
}
By default dynamic types are registered when the system loads your plugin. In some cases, it could be useful to postpone the registration of a dynamic type on the first use. This can be done by setting lazy_registration = true
:
// My object types
#[derive(Default)]
pub struct MyType;
#[glib::object_subclass]
#[object_subclass_dynamic(lazy_registration = true)]
impl ObjectSubclass for MyType { ... }
For more complex cases, see the documentation glib::object_subclass, glib::object_interface, glib::Enum, glib::flags, glib::subclass::type_module::TypeModuleImpl and glib::subclass::type_plugin::TypePluginImpl.
gtk4-rs §
- GTK 4.14 APIs support
- Support
TemplateChild<T>
usage withglib::Properties
macro, allowingTemplateChild<T>
to be used as properties
- gtk: Don’t propagate unused argument
- examples: Add example for About Dialog
- gtk::show_about_dialog: Set hide_on_close
- Regen with ffi workspacecs usage
- Add missing installation step for Windows
- book: Use const consistently
- book: Less usage of once_cell
- Get rid of once_cell
- Use cargo workspace features
- Examples: async request no blocking main thread
- CI: add a cargo deny job
- Revert “book: Go back to 4_8 for now”
- examples: Add a menubar one
- examples: Add a gtk::Scale
- Various fixes
- image: Use modern way of publishing the container
- print_job: fix send() closure
- book: Fix link to GVariant docs
- docs: fix composite template internal_child -> internal
- Add clarification around creating tokio runtime
- book: Move to libadwaita 1.4
- book: Add setuptools installation
- book: Use new API spawn_future_local
- docker: Move to libadwaita 1.4
- book: Move to
install_action
- Migrate listings to action group
- book: Use bounded channels instead of unbounded
- book: Move to async-channel
- book: Disable playground globally
- book: Split book workflow in two
- examples: various cleanups
- Examples: Dialog’s response signal handling
- examples: Clean up, modernize and simplify virtual methods example
- gtk: Use glib enums instead of bools where it makes sense
- book: Extend main loop chapter with async section
- book: Rename action to correct name
- examples: Only require GTK 4.10 for the examples
- book: Fix typo in memory management chapter
- book: Run separate jobs for check and deploy
- book: Check links with lychee
- gtk: Implement HasParamSpec for TemplateChild<T>
- Regenerate with latest gir
- book: Add missing steps for installation in windows
- gdk: Simplify RGBA builder code
- gsk: Add builder for Stroke
- gdk: Rename
GdkCairoContextExt::set_source_{rgba => color}
- book: Add missing snippet for
new_task
- book: Move to
std::cell::OnceCell
- gdk: Make RGBA::new const and add with_* constructors
- Add new Path APIs
- book: Extend memory management chapter
- Untangle docsrs attribute from features
- Impl Write on text buffers
- gdk: Add missing Clipboard::set
- Use
derived_properties
macro - Use
gio::spawn_blocking
instead of thread::spawn - gtk: Add a GNOME 45 feature
- Use workspace features for ffi types
- Use cargo workspace features
- Replace
once_cell
usage with std::sync::OnceLock - Replace usage of macro
proc_macro_error
with explicit propagation ofsyn::Result
- glib: Mark panicky
BoxedAnyObject
methods astrack_caller
- add support of flags registered as dynamic types
- Fix concurrency issues
- Refactor macros to register dynamic types
- macros: generate GlibPtrDefault when deriving Boxed and SharedBoxed
- gio: return NULL from spawn_blocking’s underlying gtask
- gio: Don’t wrongly cast DataInputStream byte arrays to a const pointer
- Simplify pointer casts
- glib: Remove deprecated paramspec constructors
- Windows-specific API bindings that use Windows types were migrated from the unmaintained
winapi
crate towindow-sys
. This might need changes for users of these APIs and require them to migrate too. - Matchinfo lifetime
- Add
Cargo.lock
to git tracking - Add support of enums as dynamic types
- gio: fix UnixSocketAddress constructor with a path
- glib: Remove
MainContext::channel()
- glib: Allow variable expansion in format strings passed to bool_error & result_from_gboolean
- gio: Use weak reference to ActionMap when adding action entries
- Add _full and _local_full methods for idle and timeout callbacks that take priority
- Implement ext trait on IsA<T>, don’t generate overridden methods
- glib: Implement object class methods via a trait
- New
glib::spawn_future()
andglib::spawn_future_local()
convenience functions that directly spawn a future on the current thread default’s main context, without first having to retrieve it - glib-macros: Remove unused imports from Properties doc test
- glib-macros: Mark property getters as #[must_use]
- fix glyph string analysis methods that don’t need &mut
- cairo: Make it docs.rs friendly
- glib/GStringPtr: Add
as_str()
andDeref<Target=&str>
- CI: add a cargo deny job
- glib: Remove
#[doc(hidden)]
fromonce_cell
andbitflags
re-export - Use associated type in memory managers
- add support of module types
- image: Switch to latest fedora stable
- gio: Fix panics in
PollableInputStream
/PollableOutputStream
- Added bindings for Gio.DBusObjectManager, Gio.DBusObjectManagerClientFlags
- Disentangle docsrs and features
- Add typos workflow
- gio: Set missing annotations for new FileInfo apis
- Add support for ext_trait in properties macro
- glib: Bind
g_unichar
APIs - Add object_subclass example
- Fix docs of
glib::derived_properties
- Fix panic in gio InputStream
- Don’t generate unit tuple in clone macro as default-return value
- glib: prelude cleanup
- glib: Implement Regex
All this was possible thanks to the gtk-rs/gir project as well:
- codegen/sys: Don’t expect the crates are renamed
- CI/tests: Remove gtk3 related bits
- Replace once_cell crate with std::sync::OnceLock in a generated code
- Replace
once_cell
crate withstd::sync::OnceLock
- parser: Don’t error out for forever scope
- record: Differentiate disguised vs pointer types
- Remove unnecessary casts of function pointers through usize
- codegen: Generate a doc alias for aliases
- parser: Don’t require name/type for record types
- Fix various typos
- Make auto builders/traits/functions
pub(crate)
- config/codegen: Stop generating useless Display impls
- Generated sys tests: Better command error handling
- Fix inserting all-features in Cargo.toml for docs.rs
- Add trait_name to API docs
- Fix docsrs
- codegen: Replace ControlFlow with Propagation
- codegen: generate doc_alias for static_type
Thanks to all of our contributors for their (awesome!) work on this release:
- @AaronErhardt
- @andy128k
- @awused
- @bilelmoussaoui
- @bvinc
- @cgwalters
- @Claudio-code
- @davidmhewitt
- @erwinschrodinger1
- @evaporei
- @fbrouille
- @felinira
- @GuillaumeGomez
- @Hofer-Julian
- @JakeStanger
- @jf2048
- @jobale
- @nicopap
- @ocrete
- @pbor
- @pentamassiv
- @pieterdd
- @ranfdev
- @RealKC
- @redvimo
- @sdroege
- @SeaDve
- @vhakulinen
- @wroyca
- @zachs18
- @ZanderBrown
- @zecakeh