A GTK+ update

You may have noticed that GTK+ master has a large number of changes in the CSS area. As some like to put it:

Oh NO! they’re breaking themes again!

Which is certainly one way to look at it, but I think it misses the point a little bit – since the effort is actually meant to make life easier for anybody who wants to change the appearance of GTK+ widgets.

What changes are we making ?

As a first step, we are introducing CSS nodes. A CSS node has an element name, a state and it can have style classes.  Each widget has one or more CSS nodes, and they are organized in a tree.  GTK+’s CSS machinery matches CSS selectors on this CSS node tree, and as a result, each node carries a full set of CSS properties.

The transition to CSS nodes is mostly done in GTK+ 3.19.2.

In a  second step, we will integrate CSS nodes into size allocation and rendering. This will bring consistent support for margins, padding and min-width/height for all widgets. This step is currently being prepared on the wip/otte/gadget branch.

None of this is exposed as API yet  (with some small exceptions, such as gtk_widget_path_iter_set_object_name ) . It needs more time to prove itself before we are ready to offer this as stable API.

Why are we doing this ?

There are a number of reasons for doing these changes. In no particular order,

  • Element names and style classes use by widgets for their CSS nodes (and their tree relationships) are now documented and provide a stable interface for themes and custom CSS.
  • Element names provide a level of abstraction over the direct use of type names, and will allow reuse of CSS. You wil be able to add a “check” node to your own widget, whereas you can’t call your own widget GtkCheckButton.
  • CSS nodes are permanent. This implies that they can carry state, e.g. for running CSS animations. They can also notify on state changes.Spinning
  • CSS nodes can explored and manipulated in GtkInspector.Inspect!
  • CSS nodes (in particular, the second phase) force us to clean up all the irregularities of the current widget rendering and move to a much more regular model, where every node draws a background and a  frame. Fancy Switches
  • Positional selectors such as :first-child now work everywhere, including parts of a widget. You can e.g., use :nth-child(even) to style notebook tabs.Fancy Tabs

What do you have to do ?

If you maintain a theme or custom CSS for an application,  update your selectors to use the documented element names and classes. The changes in Adwaita can serve as an example for the kind of changes that are needed.

If you use GTK+’s style machinery to render non-widget content (like mutter does for window decorations), use
gtk_widget_path_iter_set_object_name to make your widget paths look like the widgets they imitate.

If you have code that pokes colors out of GtkStyleContext to do your own rendering, you should really port to use the gtk_render APIs and custom CSS. If you want to keep your existing code working for now, you need to minimally fix gtk_style_context_get_color calls to use the correct state.  Ie. go from

gtk_style_context_get_color (context,
                        GTK_STATE_FLAG_SELECTED,
                        &color);

to

gtk_style_context_save (context);
gtk_style_context_set_state (contexts,
                        GTK_STATE_FLAG_SELECTED);
gtk_style_context_get_color (context,
          gtk_style_context_get_state (context),
          &color);
gtk_style_context_restore (context);

What else is new ?

Support for help overlays Shortcuts got merged into GTK+ and is available in 3.19.1. We’ve gotten some feedback from early adopters and added a few more features, so things should be in good shape for wider adoption: please add it to your favorite GTK+ application, and update this page if you do so.

Wayland support is progressing. So far in 3.19, the focus has been on straightening out issues with window and popup sizing and positioning. Many of the remaining gaps will be fixed by integrating the protocols that have been under discussion for a while now: DND actions, tablet support, pointer lock,…  Jonas just revamped the Wayland protocol development process, which should lead to faster progress on this front. For more details, see Jonas’ mail.

5 thoughts on “A GTK+ update”

  1. There are shims for the existing selectors to retain compatibility with themes for 3.18 though, right?

    Because if there aren’t, the next version of GTK+ should be 4.0.0 according to http://semver.org. I’m just assuming here that you have adopted semantic versioning by now like many other projects, so that people can look at the version number and either say “sure, I’ll upgrade – everything will still work anyway” or “hmm, breaking changes – let’s look at the release notes and see whether this is for me”.

    1. That is a good question. For a while now, GTK+ looks in versioned subdirectories for theme css, so you can ship

      MyFancyTheme/gtk-3.18/gtk.css
      MyFancyTheme/gtk-3.20/gtk.css

      and so on. I would like to hear from 3rd party theme authors how well that works in practice – it is obviously not relevant for the themes that GTK+ ships as resources inside the library.

      Regarding the semantic versioning: As always, read the small print… it really depends on your definition of “everything” in “everything will still work”.

      1. I was wondering about semver as well. Until I realized that I suddenly realized that GTK+ might not be treating their themes as need to be compatible with previous version.

        Which even kinda makes sense, you don’t expect your old (3.X) themes to work with newer versions for GTK, if new widgets are introduced…

        (Although having some sort of commitment not to break everything every 6 months obviously will be appreciated by theme authors :))

      2. Using
        MyFancyTheme/gtk-3.18/gtk.css
        does not work in fedora rawhide.
        Tested with BlueMenta theme from mate-themes

        Why not branching gtk+ to gtk4 for such a massive breakage?

        1. Can you be more specific as to how it is not working ?

          I just tried, and it worked fine here. What I did is copy the Greybird theme into ~/.themes, then duplicate the gtk-3.0/ directory as gtk-3.18/ and gtk-3.20/, and make some random tweaks to the gtk.css in each of them.

          Now running

          GTK_THEME=Greybird ~/gtk-3.{18,20}/demos/gtk-demo/gtk3-demo

          will pick up the version-specific tweaks I made.

Comments are closed.