GTK+ 3.20 was released a while ago; we’re up to 3.20.3 now. As I tried to explain in earlier posts here and here, this was a pretty active development cycle for GTK+. We landed a lot of of new stuff, and many things have changed.
I’m using the neutral term changed here for a reason. How you view changes depends a lot on your perspective. Us, who implemented the changes, are of course convinced that they are great improvements. Others who maintain GTK+ themes or applications may have a different take, since changes often imply that they have to do work to adapt.
What changed in GTK+
A big set of changes is related to the inner workings of GTK+ CSS.
The CSS box model is much better supported in widgets. This includes padding, margins, borders, shadows, and the min-width and min-height properties. Since many widgets are complex, they typically have many CSS boxes. Here is how the box tree GtkNotebook looks:
In the past (up to and including GTK+ 3.18), we used a mixture of widget class names (like GtkNotebook), style classes (like .button) and widget names (like #cancel_button) for matching styles to widgets. Now, we are using element names for each box (e.g. header, tabs and tab in the screenshot above). Style classes are still used for optional things and variants.
The themes that are included in GTK+ (Adwaita, Adwaita dark, HighContrast, HighContrastInverse and the win32 theme) have of course been updated to follow this new naming scheme. Third-party themes need and application-specific CSS need to be updated for this too.
To help with this, we have expanded both the general documentation about CSS support in GTK+ here and here, and we have documented the element names, style classes and the node hierarchy for each widget. Here, for example, is the notebook documentation.
The documentation is also a good place to learn about style properties that have been deprecated in favor of equivalent CSS properties, like the secondary cursor color property. We warn about deprecated style properties that are used in themes or custom CSS, so it is easy to find and replace them:
(gtk3-demo:14116): Gtk-WARNING **: Theme parsing error: gtk-contained.css:18:37: The style property GtkWidget:secondary-cursor-color is deprecated and shouldn't be used anymore. It will be removed in a future version
There’s also a number of new features in CSS. We do support the CSS syntax for radial gradients, we let you load and recolor symbolic icons, image() and calc() are supported, as well as the rem (‘root em’) unit.
Beyond CSS, the drag-and-drop code as been rearchitected to move the drag cancel animation and most input handling into GDK, thereby dropping most of the platform-dependent code out of GTK+. The main reason for doing this was to enable a complete DND implementation for Wayland. As a side-effect, we gained the ability to use non-toplevel widgets as drag icons, and we dropped the X11 specific feature to use RGBA cursors as drag icons.
The Wayland backend has grown most features that it was missing compared to X11: the already mentioned full DND support, kinetic scrolling, startup notification, primary selection, presenting windows, a bell.
Changes in applications
Here is an unsorted list of issues that may show up in applications with GTK+ 3.20, with some advice on how to handle them.
One of the motivations for the changes is to enable animations and transitions. If you use gtk_style_context_save/restore in your draw() function, that prevents GTK+ from keeping the state that is needed to support animations; so you should avoid it when you can.
There is one place where you need to use gtk_style_context_save(), though: when using “theme colors”. The function gtk_style_context_get_color() will warn when you pass a state other than the current state of the context. To avoid the warning, save the context and set the state:
gtk_style_context_save (context);
gtk_style_context_set_state (context, state);
gtk_style_context_get_color (context, state, &color);
gtk_style_context_restore (context);
And yes, it has been pointed out repeatedly that this change makes the state parameter of gtk_style_context_get_color() and similar functions largely useless – this API has been around sinc e 3.0, when the CSS machinery was much less developed than it is now. Back then, passing in a different state was not a problem (because animations were not really supported).
Another word of caution about “theme colors”: CSS has no concept of foreground/background color pairs. The CSS background is just an image, which is why gtk_style_context_get_background_color() is deprecated and we cannot generally make it return a useful color. The proper way to have a theme-provided background in a widget is to call gtk_widget_render_background() in your draw() function.
If you are using type names of GTK+ widgets in your CSS, look up the element names in the documentation and use them instead. For your own widgets, use gtk_widget_class_set_css_name() to give them an element name, and use it in the CSS.
A problem that we’ve seen in some applications is the interaction between size_allocate() and draw(). GTK+’s CSS boxes need to know their size before they can draw. If you derive from a GTK+ widget and override size_allocate without chaining up, then GTK+ does not get a chance to assign sizes to the boxes. This will lead to critical warnings from GTK+’s draw() function if you don’t override it. The possible solutions to this problem are either to chain up in size_allocate or to provide your own draw implementation.
If you are using GTK+ just for themed drawing without using GTK+ widgets, you probably need to make some changes in the way you are getting theme information. We have added a foreing drawing example to gtk3-demo that shows how this can be done. The example was written with the help of libreoffice and firefox developers, and we intend to keep it up-to-date to ensure that this use case is not neglected.
A plea
If you are maintaining a GTK+ application (in particular, a big one like, say, inkscape), and you are looking at porting from GTK+ 2 to GTK+ 3, or updating it to keep up with the changes in 3.20, please let us know about the issues you find. Such feedback will be useful input for us when we get together for a GTK+ hackfest in a few weeks.
Whats coming
One of the big incoming changes for 3.22 is a GL-based renderer and scene graph. Emmanuele has been working on this on-and-off for quite a while – you may have seen some of his earlier presentations. Together with the recent merge of (copies of) clutter and cogl into mutter, this will put clutter on the path towards retirement.