So, half a year after 1.1, libadwaita 1.2 has been released.
While it doesn’t contain everything I had planned (since I ended up being mostly unavailable for about half of the cycle for reasons outside my control), it still has a bunch of additions, so let’s take a look at the changes.
Entry Rows
First, we have a widget that was planned for 1.0, but didn’t make it because it still needed work. This cycle I took time to finish and land it.
Originally implemented by Maximiliano, AdwEntryRow
is a new type of boxed list rows, containing an inline entry. Its title doubles as the entry placeholder.
Entry rows can require confirmation via an apply button shown when its contents are edited. Otherwise, it’s similar to GtkEntry
API, and can have prefix and suffix widgets like AdwActionRow
.
There is also a companion widget AdwPasswordEntryRow
, mirroring GtkPasswordEntry
.
Message Dialogs
AdwMessageDialog
is a new widget that replaces GtkMessageDialog
. On the first glance, it looks more or less the same. However, it has a few important differences.
Adaptive Layout
GtkMessageDialog
tends to overflow off the screen very easily. AdwMessageDialog
doesn’t because it’s fully adaptive: when scaling down the window, it first restricts its own size to the parent’s size:
And if that’s not enough to fit, it arranges its buttons vertically:
Additionally, it always uses the vertical arrangement if the dialog would end up ridiculously wide otherwise, even when there is enough space to display it like that.
API
The second important thing is that it’s not a GtkDialog
subclass and, as such, has completely new API.
-
GtkMessageDialog
inherits the response API fromGtkDialog
. It relies on integer IDs that are provided by applications, except when they aren’t – theGtkResponseType
enum provides a few predefined responses. This is a very C-centric API (as it assumes enum values being interchangeable with integers), and it’s not overly convenient to use.AdwMessageDialog
replaces it with simple string IDs that are always provided by applications.This also allowed the
response
signal to be detailed, using the response ID as the detail.In addition,
AdwMessageDialog
is automatically closed on response, and doesn’t need to be closed manually. As such, common code like this:static void dialog_response_cb (GtkDialog *dialog, GtkResponseType response, MyObject *self) { if (response == GTK_RESPONSE_ACCEPT) my_object_foo (self); gtk_window_destroy (GTK_WINDOW (dialog); } ... g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), self);
can be replaced with just:
g_signal_connect_swapped (dialog, "response::accept", G_CALLBACK (my_object_foo), self);
-
Just as
AdwMessageDialog
doesn’t have predefined responses and leaves that to apps, it doesn’t useGtkButtonsType
. It seems counterproductive to have API to easily create buttons like “OK”, “Cancel”, “Yes” and “No” when we’ve been discouraging labels like this for just about two decades now, doesn’t it? -
No direct widget access.
GtkMessageDialog
required apps to poke into its widgetry to pack additional widgets, add style classes to its buttons and so on.AdwMessageDialog
can have a single extra child, displayed below the body text and managed with theextra-child
property, and natively supports changing button appearance instead. -
While the intention of
GtkMessageDialog
is to use its primary and secondary text, it also displays the window title, and many applications get it wrong, ending up with three labels or wrong styling:Primary text also changes its styles to look like a heading or body text, depending on whether secondary text is set.
AdwMessageDialog
does not do any of that. It just hasheading
andbody
, that’s it. -
Finally, it’s derivable. While making
GtkMessageDialog
final in GTK4 was consistent with most of the other GTK widgets, it has generally resulted in vastly more convoluted code for apps with complex dialogs – for example, the save dialog in GNOME Text Editor with its list of open files.
So now app developers have no excuses for shipping unpolished message dialogs anymore. 😉️
About Window
Another widget originally planned for 1.0 that didn’t make it was Adrien’s AdwAboutWindow
, replacing GtkAboutDialog
. This cycle I finished it up and merged it.
The new window is adaptive and natively provides a lot of details people were doing hacks with GtkAboutDialog
for before:
- Legal information for dependencies and other components;
- A list of acknowledgements in addition to credits — for example, for crowdfunding backers;
- A place to list recent changes in the application;
-
Links to the application’s website, issue tracker, support forum, as well as any additional links, as opposed to a single link in
GtkAboutDialog
; - Debugging information, along with easy ways to save or copy it.
Christopher Davis has ported core apps using libadwaita to AdwAboutWindow
, so it’s also pretty consistently used by now.
Tab View and Tab Bar Additions
AdwTabView
and AdwTabBar
have seen quite a few changes this cycle.
The most important change is with shortcut handling. AdwTabView
provides a lot of shortcuts for switching and reordering tabs, for example, Ctrl+Tab
to switch to the next tab, or Alt+1
– Alt+0
to switch to the first 10 tabs.
In Libhandy, these shortcuts were added via the shortcut-widget
property, with the idea that you set it to your toplevel window unless you have multiple tab views.
In Libadwaita 1.0, that property was removed, and instead the shortcuts were switched to the GTK4 shortcut engine, using global scope (really MANAGED
scope, but doesn’t matter). This means that they were available for the whole window automatically.
However, this also brought issues. For example, the Ctrl+Tab
shortcut stopped working, because GTK defines that shortcut itself, for changing widget focus. Similarly, GTK4 port of the VTE library handles all input on the CAPTURE
propagation phase, meaning none of the tab view shortcuts could work at all in the GTK4 port of GNOME Console.
Meanwhile in both libhandy and libadwaita 1.0.x-1.1.x, apps that want to disable some of the shortcuts had to do pretty terrible hacks to achieve it, for example, registering the same shortcuts on the toplevel window and redirecting input to the tab contents or whatever widget needs to handle them.
So, to fix that, AdwTabView
has switched its shortcuts to the CAPTURE
phase as well, and added an easy way to enable or disable shortcuts.
Other than that, AdwTabPage
now has a property to set the tooltip for its indicator icon, and AdwTabBar
tabs similarly has a tooltip on the tab close buttons – not customizable this time.
Toast Additions
- Kévin Commaille added a way to have custom widgets as toast titles. This allows, for example, to have avatar+name pills inside toasts in Fractal.
- Emmanuele Bassi added a helper function for creating a toast with formatted title.
- Jamie added
AdwToast::button-clicked
signal to make it possible to have toast buttons without actions. - Jonathan Blandford made it possible to add or dismiss toasts multiple times to make them easier to use. Dismissing toasts that have already been dismissed does nothing now, while adding toasts that have already been added resets the timeout for toasts that are currently shown, or bumps them forward in the queue otherwise. Previously doing that resulted in criticals being printed.
Other Additions
AdwPropertyAnimationTarget
has been added to simplify animating object properties.AdwAnimation
can now change targets on the fly.- Sophie Herold added a property to allow disabling Pango markup in boxed list row titles (as well as subtitles in case of
AdwActionRow
etc). AdwSplitButton
can now have a separate tooltip for its dropdown button.AdwViewStack
has gained a helper function to add a child along with a title and an icon.- JCWasmx86 added plumbing to
AdwStyleManager
to allow GNOME Builder to launch apps with light/default/dark color scheme, as well as in high contrast. This has also been backported to Libhandy, and is available in 1.8.0 (which doesn’t have a blog post as it’s the only noteworthy change there).
Styles
A few styles have been tweaked. In particular, AdwTabBar
has seen big changes, mainly to improve contrast in dark variant and make it clearer which tab is selected.
The lack of full height separators has also allowed to remove the distracting light borders from header bars and search bars in favor of dark borders using @headerbar_shade_color
and add a proper backdrop style consistent with header bars.
In addition, GtkActionbar
and AdwViewSwitcherBar
now have the same style as header bars, search bars and tab bars, while boxed lists use dark separators.
The .large-title
style class is now documented as deprecated and apps should use .title-1
instead.
There are also a few smaller changes, for example:
- Toasts without buttons are smaller now, instead of taking a fixed width.
AdwActionRow
child spacing is now smaller, matching toolbars and the newAdwEntryRow
.AdwExpanderRow
arrows have changed orientation to look less like rows that open subpages on click.- Lots of fixes, some of them have been backported to libadwaita 1.1.x as well.
As it happens, quite a lot didn’t make it because it needed more work, or the timing just didn’t work out. This also means that there’s a lot to look forward to in the next release though, so stay tuned.
Thanks to all the contributors, and thanks to my employer, Purism, for letting me work on Libadwaita and GTK to make this release happen.