I said that I would post regular updates on what is happening in GTK+ 4 land. This was a while ago, so an update is overdue.
So, whats new ?
Cleanup
Deprecation cleanup has continued, and is mostly done at this point. We have the beginning of a porting guide that mentions some of the required changes for early adopters who want to stick their toes into the GTK+ 4 waters. Sadly, I haven’t gotten the GTK+ 4 docs up on the website yet, so no link…
Among the things that have been dropped as part of our ongoing cleanup has been the pixel cache, which should no longer be needed. This is nice since the pixel cache was causing problems, in particular on connection with transparency and component alpha (in font rendering).
Not really a cleanup, but we also got rid of the split into multiple shared objects (libgtk, libgdk, libgsk). Now, we just install a single libgtk, which also provides the gdk and gsk APIs. This has some small performance benefits, but mainly, it makes it easier for us to have private APIs that cross the gtk/gdk boundary.
Widget APIs
Some of the core APIs that are important when you are creating your own widgets have been changed around a bit:
- The five different virtual functions that are used for size requisition have been replaced by a single new vfunc, measure(). This is using the same approach that we are already using for gadgets, where it has worked well.
- The draw() virtual function that lets widget render themselves onto a cairo surface has been replaced by the new snapshot() vfunc, which lets widget create render nodes. This is essentially the change from direct to indirect rendering. Most widgets and gadgets have been ported over to this new wayof doing things.
These changes are only important to you if you create your own widgets.
Window APIs
GdkWindow has gained a few new constructors to replace the old libX11-style gdk_window_new. Their names should indicate what they are good for:
- gdk_window_new_toplevel
- gdk_window_new_popup
- gdk_window_new_temp
- gtk_window_new_child
- gdk_window_new_input
- gdk_wayland_window_new_subsurface
- gdk_x11_window_foreign_new_for_display
The last two are worth mentioning as examples where we move backend-specific functionality to backend APIs.
In the medium term, we are moving towards a world with only toplevel windows. As a first step towards this, we no longer support native child windows, and gdk_window_reparent() is gone. This allowed us to considerably simply the GdkWindow code.
Renderers
When we initially merged GSK, it had a GL renderer and a software fallback (using cairo). Since then, Benjamin has created a Vulkan renderer. The renderer can be selected using the GSK_RENDERER environment variable.
So, for example, this is how to run gtk4-demo with the cairo renderer and the X11 backend:
GSK_RENDERER=cairo GDK_BACKEND=x11 gtk4-demo
After the GSK merge, we struggled a bit to come up with a working approach to converting all our widget and CSS rendering to render nodes. With the introduction of the snapshot() vfunc, we’ve been able to make progress on this front. As part of this effort, Benjamin changed the GSK API around a bit. There are now a bunch of special-purpose render node subclasses that let us effectively translate the CSS rendering, e.g.
- gsk_linear_gradient_node_new
- gsk_texture_node_new
- gsk_color_node_new
- gsk_border_node_new
- gsk_transform_node_new
…and so on. More node types will be created as we discover the need for them.
New fun
As an example of new functionality that would be very hard to support adequately in GTK+ 3, Benjamin recently added gsk_color_matrix_node_new and used it to implement the CSS filter spec, which is good for a few screenshots:
Since this is all done on the GPU (unless you are using the software renderer), applying one of these filters does not affect performance much, as can be seen in this screencast of the fishbox demo:
Expect to see more uses of these new capabilities in GTK+ as things progress. Fun times ahead!