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.
Thanks for the more detailed explanations. For the things that need application changes, I see that they are documented in the README.in, but with less details. However I don’t think that everybody will look at the README or your blog, since we can install the gtk3-devel and gtk3-doc distro packages and look at the documentation in Devhelp.
So why not writing a porting guide to GTK+ 3.20 in the reference manual, in the “Part V. Migrating from Previous Versions of GTK+” ?
Maintaining software built on gtk and the gnome stack is a job for sisyphus.
First of all, thanks a lot for attempting to improve the CSS side. However, I noticed regressions and some theming problems (rendering logic) that suggest this major change should have had more testing and thinking before getting into master.
Just two examples:
1. How to easily theme a specific widget for a specific application?
Let’s take GNOME’s calculator and it’s headerbar. I want it to be green. The answer is (afaik) that it’s now no longer possible unless the application author modifies code, adds CSS node support and a new release is deployed. So suddenly, from being able to easily use selectors to taget anything on screen, theme authors need to speak to app devs or become coders to be able to target certain widgets. You have been writing yourself about how a bunch of work it was to adopt many GNOME apps already. I think that is a regression and makes things a lot harder, if not breaking a lot of themes completely or even make theme authors just resign. No, I don’t expect all those new apps and old apps in the wild to adopt and add CSS node names in a few months (or any acceptable timeframe for users…). This really removes the needed flexibility for theme authors by relying on new app releases and/or app authors. CSS on the web allows to style and target any element, this should be one of the important technical requirements for the GTK’s CSS engine, too.
2. Lack of fixed size elements (or problems with inconsistent widget scaling).
Due the the removal of private vendor properties to control widget properties (might be regarded as a hack) and the pure reliance on min-width and min-height, it is impossible to fix certain rendering situations when widgets span multiple cells (like in a box/grid) with a fill alignment. Think of the button on sliders or a switch, it will stretch now and look ugly while the idea is to have a consistent widget style and thus a coherent button/knob which scales at a fixed width/height ration. Fill alignment should mean that the widget fills the whole area, not that it’s child elements stretch visually. Even if I am wrong and it is expected correct behavior, I don’t expect a lot of apps in the wild to fix their UI just to look good in anything but Adwaita or even notice this issue.
That and more stuff is not visible directly with GTK’s widget factory and Adwaita, thus just shows my point that not enough testing might have been done for such a big change. In my point of view (please proove me wrong) it does not “improve” the GTK CSS features but (currently) cuts a lot of previous functionality/flexibility in regards to theming.
I hope this can be resolved so GTK CSS theming can be fun again as it was pre 3.20.x and to hear what you think about it. 🙂
These are terrific points.
Did you happen to file any bugs regarding these issues?
I agree with Liam, please file bugs because I think this has been overlooked.
sorry to be Captain Obvious, but what does this mean in case of stable Gtk4? as i remember scene graph was one of the requirements and so are new combo boxes which i know they are not there yet. is there anything else that is missing?
it would be really nice if there was some information on that topic since last bits of information on that were more than one year ago. in my case i would love nothing more than move on Gtk3 completely, but i simply can’t because as much as i could do that for my OSS apps, i can’t really dictate or control the environment for my commercial ones. this creates really bad position of being stuck between new and really old version. to make things even worse, 3 has made leaps of improvements over 2 and this is like watching ice cream melting trough the glass
i know that 3 is development release and all, but main problem is that 3 is in development for quite a while now and to make it worse Gtk2 was already 5 or 6 years old when it started. hope that asking for some info is not too much
GTK+ 4 will be as unstable as GTK+ 3 now. But once GTK+ 4 is released, the latest GTK+ 3.x version will be more stable (since there will be only bug fixes).
But with xdg-app, you can choose e.g. the GNOME 3.20 runtime, and when future GTK+ versions are released, your application can still run with GTK+ 3.20.
now all you need to do is to explain how can i do it in cross platform manner 😉
as i said, i already moved for my OSS work, i simply can’t for my bread and butter
as far as “GTK+ 4 will be as unstable as GTK+ 3 now”. that would be really bad decision from presentation side since 3 was so long in the works and 2 was on life support even longer. last thing you would ever want to do is saying “we developed 3, but here is 4”. marketing wise it is suicide
much better outlook would be to create 4 (promoted as stable and bugfixes only) and asap create 5 (development)
GTK 3 evolves like GTK 2 evolved in its time. What prevents you from switching to GTK 3 ? Unless you heavily rely on theming features on your commercial apps, I barely see why you wouldn’t switch to GTK 3.
mostly constant lack of builds for other platforms. and the fact that some languages completely abandoned tracking with bindings due to its unstable api. sadly, my commercial work needs .Net where gtk-sharp completely lost track and all it is available is some efforts from random people
on my OSS with Vala i have 0 complaints
Re: OpenGL based SceneGraph, please supply an OpenGL enabled build of Cairo as well, for Graphics based applications, there are lots of things that could be done with a fast Cairo renderer.
No, Cairo-GL is the wrong answer to a poorly worded question that nobody really asked.
Drawing with Cairo is fast enough; drawing multiple UI elements on the same Cairo surface is fast but CPU-intensive; we should be (and we are) moving that last part to the GPU. Ideally, we should also be moving more of the drawing on the GPU as well, but not with Cairo.
“Others who maintain GTK+ themes or applications may have a different take”
And others who uses GTK+ themes … (AKA the user)
Those of us using a rolling release distro that jumped the gun and release that version of GTK+ now have their “GTK+-but-not-GNOME” desktop broken.
What’s the current renderer based-on?
And have you ran any benchmarks so far to see how much of an improvement does the new GL-based renderer brings to the scene (no pun intended)?
Cheers,
Behrang
The CSS change to elements seems to break many 3rd party themes (e.g. Flatabulous). Is there a list of the rules that have changed from class to element – I’d be willing to write a conversion tool if so,