Paths in GTK, part 2

In the first part of this series, we introduced the concept of paths and looked at how to create a GskPath. But there’s more to paths than that.

Path Points

Many interesting properties of paths can change as you move along the trajectory of the path. To query such properties, we first need a way to pin down the point on the path that we are interested in.

GTK has the GskPathPoint struct for this purpose, and provides a number of functions to obtain them, such as gsk_path_get_closest_point(), which lets you find the point on the path that is closest to a given point.

Once you have a GskPathPoint, you can query the properties of the path at that point. The most basic property is the position, but you can also get the tangent, the curvature, or the distance from the beginning of the path.


Another interesting question when using paths in a user interface is:

Is the mouse pointer hovering over the path?

You need the answer to this question if you want to highlight a path that the pointer is over, or if you want to react to the user clicking a path.

For a filled path, GTK provides the answer with the gsk_path_in_fill() method.

For a stroked path, it is much more complicated to provide a 100% accurate answer (in particular, if the stroke is using a dash pattern), but we can provide an approximate answer that is often good enough: a point is inside the stroke, if the distance to the closest point on the path is less than half the line width.


The next part of this series will look at rendering with paths.

Paths in GTK

It is no secret that we want to get rid of cairo as the drawing API in GTK, so we can move more of our drawing onto the GPU.

While People have found creative ways to draw things with render nodes, they don’t provide a comprehensive drawing API like Skia or, yes, cairo. Not a very satisfying state of affairs.

A few years ago, we started to investigate how to change this, by making paths available as first-class objects in GTK. This effort is finally starting to come to fruition, and you can see the first results in GTK 4.13.0.


So, what is a path? A rough definition could be:

A sequence of line segments or curves that may or may not be connected at their endpoints.

When we say curves, we specifically mean quadratic or cubic Bézier curves. On top of cairo, we also support rational quadratic Béziers (or as Skia calls them: conics), since they let us model circles and rounded rectangles precisely.

This picture shows a typical path, consisting of 4 curves and 2 lines, some of which are connected. As you can see, paths can be closed (like the 4 curves here) or open (like the 2 lines), with a start- and endpoint.

And how are paths useful for drawing? First, you can use a path to define an area (the part that’s inside the path) and fill it with a color, a gradient or some more complex content.

Alternatively, you can stroke the path with various properties such as line width, color or dash pattern.

Paths in GTK

The object that we use for paths in GTK is GskPath. It is a compact, immutable representation that is optimized for rendering. To create a GskPath, you need to use a GskPathBuilder, which has many convenience methods to create paths, either from individual curves or from predefined shapes.

This example creates a path that is a closed triangle:

builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, 0, 50);
gsk_path_builder_line_to (builder, 100, 50);
gsk_path_builder_line_to (builder, 50, 0);
gsk_path_builder_close (builder);
path = gsk_path_builder_free_to_path (builder);

And this one creates a circular path with the given center and radius:

builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, center, radius);
path = gsk_path_builder_free_to_path (builder);


In the next post, we’ll look at properties of paths, and how to query them.

Evolving accessibility

Our last post on accessibility in GTK4 was a while ago, time for an update.

Thankfully, we have Lukáš Tyrychtr at Red Hat working on accessibility now.

Accessibility – How does it work?

One of the bigger changes in accessibility from GTK3 to GTK4 was that we have a new application API that is modeled on the ARIA specs from the web.

The high-level picture to keep in mind is

app → ARIA → AT-SPI → accessibility bus → AT

AT stands for accessibility technology here. In practice, that mainly means orca, the well-known screen reader (although there is a new contender, with the odilia project).

The new layer provides APIs such as

void gtk_accessible_update_state (GtkAccessible *self,
                                  GtkAccessibleState first_state,

that let apps set accessible attributes of their widgets.

ARIA layer improvements

Since we’ve introduced it in GTK4, the application API layer has only seen moderate changes. That has started to change over the last 9 months or so, since Lukáš is working on it.

One thing that he has started to do is adding public interfaces so that third-party widgets (such as libadwaita) can provide full accessibility support. The first such interface is GtkAccessibleRange (new in 4.10), for range widgets like GtkScale. We are looking at adding more, notably a text interface. It will be needed to make terminals accessible.

In the 4.12 cycle, we have done some work to make our implementation match the ARIA specs more closely. This involved changing the roles of some widgets: our default role is now ‘generic’, and toplevel windows use the ‘application’ role. We’ve also redone the way accessible names and descriptions (i.e. the things you hear orca read) are computed, to match the spec.

Another improvement is that most of our widgets now have the necessary labels and relations to make orca read them. If you find that there are still things missing, please let us know!

AT-SPI translation improvements

It is no secret that we would like to see some modernization of the AT-SPI D-Bus APIs. But for now, it is what we have to work with. Our translation layer works by lazily putting just the objects on the bus that ATs have asked for, to avoid creating too much bus traffic.

One of the recent improvements in our translation is that we are now using GtkAccessibleRange, so third-party range widgets can be accessible.

We have also fixed problems with the selection implementations for GtkNotebook and GtkStackSwitcher, so ATs can now change the selected tab in notebooks and stacks.


All of this is nice to hear, but if you are an app developer, you may want to know how you can find and fix accessibility problems in your app.

It is very instructive to just turn on the Screen Reader and see what it says as you navigate through your app. But we also have some tools to help you evaluate the accessibility support of your app.

The GTK inspector has a page that shows accessibility information:

The accessibility tab in the GTK inspectorIt recently was improved to show not just the properties, states and relations that are set on each widgets, but also the name and description that GTK computes and passes to ATs 
- that is the text that orca reads.

Another tool in the inspector is brand new: the accessibility overlay shows warnings and recommendations that are based on the ARIA authoring guidelines.

It looks like this:

A window showing warnings from the Accessibility overlay, and the inspector window with the switch to enable the overlay.It is not perfect, but it should give some quick insights on where you can improve accessibility.


GTK 4.12 will have better out-of-the-box accessibility and new tools to help you make your app accessible.

Enjoy! ❤️

GTK 4.11.1

Here is the first GTK snapshot of the new development cycle. A lot of things fell into place recently, so it is worth taking some time to go through the details of what is new, and what you can expect to see in 4.12.

List View Improvements

The family of GtkListView, GtkColumnView and GtkGridView widgets was one of the big additions in GTK 4. They are meant to replace GtkTreeView, but up until now, this was clearly still a bit aspirational.

In GTK 4.10, we’ve finally taken the big step to port GtkFileChooser away from tree views—a sign that list views are ready for prime time. And the next GTK 4 release will bring a number of missing features:

  • Finally, a fix for the longstanding scrolling bug
  • Better keyboard navigation, with customizable tab behavior
  • Focus control
  • Programmatic scrolling
  • Sections, maybe

Some of these are already available in 4.11.1. We even managed to backport the scrolling fix to 4.10.1.

Better Textures

Textures are used frequently in GTKs GL renderer—for icons and images, for glyphs, and for intermediate offscreen rendering. Most of the time, we don’t have to think about them, they just work. But if the texture is the main content of your app, such as in an image viewer, you need a bit more control over it, and it is important that the corner cases work correctly.

In GTK 4.10, we introduced a GskTextureScale node, which gives applications control over the filtering that is applied when scaling a texture up or down. This lets apps request the use of mipmaps with GSK_SCALING_FILTER_TRILINEAR. GTK 4.12 will automatically use mipmaps when it is beneficial.

One corner case that we’ve recently explored is texture slicing. Whenever a texture is bigger than the GL stack supports, GSK will break it into smaller slices and use separate GL textures for each. Modern GPUs support enormous textures (on my system, the max. texture size is 16384), which means that the slicing support is rarely tested in practice and not well covered by our unit tests either.

We added support for artificially limiting the texture size (with the GSK_MAX_TEXTURE_SIZE environment variable), and promptly discovered that our texture slicing support needed some love. It will work much better in 4.12.

Fractional Scaling

It landed on April 1st, but it is not a joke.

We’ve added support for the experimental wp_fractional_scale_manager_v1 protocol to the Wayland backend, and use the wp_viewporter protocol to tell the compositor  about the scaling that the buffer is using.  It is nice that this was easy to fit into our rendering stack, but don’t expect miracles. It works well with the cairo renderer (as you can see in the video), but we still consider it experimental with the GL and Vulkan renderers.

To try fractional scaling with the GL renderer, set


in the environment.


There’s lots of new things to explore in GTK 4.11. Please try them and let us know what you think, in gitlab or on Discourse.

Updates from inside GTK

Some of the core GTK developers recently got together for a few days to do some focused work and talk about current and future plans.

It is difficult to summarize three days of discussions in a blog post, but here are some of the highlights.

Icon themes

The GtkIconTheme code has been with us for a long time. It implements the icon theme spec, and comes from an era when we were shipping big sets of icons with the desktop and themes were expected to switch them out. That is not really how icons are made or used today.

We need a better solution for the workflow from a designer making icons a set of icons in a sheet to the developer copying individual icons into their app.

Inside GTK, this will need some form of “asset manager” to maintain the mapping from icon name to image / file / resource.


While we can’t get away from providing a C interface with gobject-introspection metadata for all our language bindings, it could be nice to use a more expressive language and a more powerful compiler than C has to offer.

Of course we can’t and won’t rewrite all of GTK in a different language. It would be nice to experiment with replacing smaller parts. Allowing new code to be written in different languages would also potentially bring in new contributors.


We discussed the scroll speed question, and decided to write up an explanatory comment in the issue about what we consider the right solution:

  • treat wheel and touchpad scrolling separately
  • inject configuration from the control-center/compositor into libinput
  • gtk gets it via events

The other big input question we talked about is ‘asynchronous event handling’ and its problems. The two main cases where this comes up are webkit, with its ui<>web process communication, and IBus. In both cases, we think that there is no actual interest in reinjecting unhandled events into the GTK capture/bubble propagation. Instead, such leftover event should just be handled ‘locally’ (in the IBus case, adding/removing characters to the entry, or moving the cursor).

Platform libraries

With GTK4, we’ve made the intentional change to move away from having everything in GTK itself, and instead introduced the idea of  ‘platform libraries’ like libadwaita to carry the more platform-specific widgetry.

Overall, we are happy with how this has turned out, and we would like to continue with this approach. There is maybe room for moving some things that are more plumbing than widgetry back into GTK itself.

GTK5 ?

We need to open a .90 branch to do things that would break the APIs that we have deprecated now (like the file chooser, and more general the chooser dialog/widget split). Some of us have been itching to start on that work. But there’s also still a lot of work to be done in 4.x (GtkListView fixes, for example).

With an eye towards the color management work that is planned to land in 4.12, the suggestion is to open a 4.90 development branch after 4.12. That would put it towards the end of this year, and 3 years after the 4.0 release, which seems reasonable.

The End

On the last day, we had the pleasure of hosting both the documentation and the tracker teams at our place.

Three hackfests in a room!

We’d like to thank the GNOME foundation for supporting our meeting. ❤️

A grid for the file chooser

In the last post, we discussed deprecating treeviews and cell renderers, among other things. All these deprecations cause a lot of work for applications and libraries using these APIs, so why are we doing this?

One of the reasons is to enable new features. Such as a grid view for the file chooser. It only took us 18 years! You can see the original feature request in Bugzilla. This is easily possible now because GtkListView and GtkGridView can use the same data models.

Here is the file chooser, with a new view toggle:

And here is the grid view itself:
Judging from the number of likes on the merge request, this is a popular feature. We hope you enjoy it. ❤️

If you want to support this work, please consider donating to the GNOME Foundation, which supports GTK development. You can do so by going here.

On deprecations

If you are paying attention to GTK’s git repository, you may have noticed a change in the last weeks.

We have a directory gtk/deprecations, which is destined to contain source files that implement deprecated APIs and will be dropped in the next major release. For the 4.0 release, we emptied it out, and it has been empty ever since. But recently, it started to accumulate files again.

This is a good opportunity to remind folks how we are using deprecations in GTK. But first, lets take a look at the details.

The details, part 1: cell renderers

In GTK 4, we introduced a new family of list and grid widgets that are based around list models: GtkListView, GtkColumnView, GtkGridView. There is also a new combo box implementation using list models, called GtkDropDown. Taken together, these are meant to provide replacements for everything you can do with cell renderers in GTK 3.

The ultimate goal was to remove cell renderers, since they are a whole separate rendering and layout system that tends to interfere with GTK’s CSS and layout machinery, and makes everything more complicated.

But we did not quite get to the finish line for 4.0, mainly because we still had significant uses of treeviews in GTK itself. First and foremost, the file chooser.  Since the filechooser is getting ported to use a GtkColumnView in 4.10, now is the right time to deprecate the cell renderer machinery and all the widgets that use them.

This is a significant amount of code, more than 75.000 lines.

The details, part 2: dialogs

In GTK 4, we dropped gtk_main() and gtk_dialog_run(), since recursive mainloops are best avoided. Again, we did not get to the finish line and could not remove GtkDialog itself, since it is used as the base class for all our complex dialogs.

GTK 4.10 introduces replacement APIs for our ‘Chooser’ dialogs. The new APIs follow the gio async pattern. Here is an example:

GtkFileDialog * gtk_file_dialog_new (void);

void            gtk_file_dialog_open (GtkFileDialog *self,
                                      GtkWindow *parent,
                                      GFile *current_file,
                                      GCancellable *cancellable,
                                      GAsyncReadyCallback callback,
                                      gpointer user_data);

GFile *        gtk_file_dialog_open_finish (GtkFileDialog *self,
                                            GAsyncResult *result,
                                            GError **error);

This may look a bit unwieldy in C, but it translates very nicely to languages that have a concept of promises and exceptions:

try {
  const file = await, ...);
} catch (e) {

To learn more about the new APIs, you can look at their online docs: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkAlertDialog.

With these replacements in place, we could deprecate the Chooser interfaces, their widget implementations, and their base class GtkDialog.

No need to panic

Deprecations in GTK are an early outlook at changes that will appear in the next major release that is breaking API compatibility.  But the eventual GTK 5 release is still far away. We have not even made a plan for it yet.

There is absolutely no need to rush towards ‘deprecation cleanup’. You only need to remove all uses of deprecations when you want to port to GTK 5 – which does not exist yet.

There are still things you can do, though. We are introducing deprecations in 4.10 as a way to give our users time to adapt, and to provide feedback on our ideas. If you want to do so, you can file an issue in gitlab, start a discussion in discourse, or find us on matrix.

In the meantime…

Deprecation warnings can be annoying, but thankfully there are easy ways to turn them off. For the occasional call to a deprecated function, it is best to just wrap it in G_GNUC_BEGIN/END_IGNORE_DEPRECATIONS:

gtk_dialog_add_button (dialog, "Apply", GTK_RESPONSE_APPLY);

If you are sure that you never ever want to see any deprecation warnings, you can also just pass -Wno-deprecated-declarations to gcc.

Inside the GTK font chooser

I’ve written about the handling of fonts in GTK before. This post is going to focus on how to use the more advanced font (and font chooser) features in your application.

Finding fonts

The most prominent end-user feature of the file chooser is of course that you can search for fonts by name, using the search entry:

A more hidden feature is that you can filter the list by various criteria. One criterium is to show only monospace fonts, another is to only show fonts covering a certain language:

A little detail to notice here is that GTK automatically changes the preview text to match the language you are filtering by.

Less is more

The font chooser returns a PangoFontDescription which contains the full details of the selected font: family, style, size, etc. If your application only needs the family, then it is confusing to let the user select a style and size only to have them be ignored.

If this is the case for your application, you can instruct GTK about the font details you need, using gtk_font_chooser_set_level(), and the GtkFontChooserLevel flags:

typedef enum {
} GtkFontChooserLevel;

For example, after

gtk_font_chooser_set_level (chooser, 

the font chooser looks like this:

Much simpler!

Into the abyss

Modern fonts are complicated beasts, and there’s much that’s lurking under the surface. The GTK font chooser can make many of these font features available if you tell it to.

First, there are font variations. These let you continuously vary the characteristics of a font (as long as those characteristics are exposed as variation axes).


Typical variation axes are weight, width and slant of a font, but there can others (such as Optical Size in this example).

The selected variations are part of the PangoFontDescription that the font chooser returns, applications don’t have to do any extra work to apply them. Just use the font description as usual.

To enable the font variation support in the GTK file chooser, use GTK_FONT_CHOOSER_LEVEL_VARIATIONS flag:

gtk_font_chooser_set_level (chooser, level);

More features

Fonts contain not just the glyph contours, but lots of other data that can be applied in various ways when rendering those glyphs. This includes traditional data like kerning and ligatures, but also things like optional glyph shape or positioning variants or even color palettes. Many of these can be enabled by the user with the help of OpenType features.

Here is an example of an OpenType feature for glyph shape variations:

The feature that is toggled on here when going from left to right is called ss12. Thankfully, the font provides the more meaningful name “Single-story g” as well.

This example shows the effect of the frac feature on the display of fractions.

In the GTK font chooser, OpenType features are presented on the same page as variations. As you see, there can be quite a few of them:

Note that Pango treats OpenType features as separate from the font itself. They are not part of the font description, but have to be applied to text either with PangoAttributes or via Pango markup.

To apply the selected font features from a GTK font chooser, call gtk_font_chooser_get_font_features () and pass the returned string to pango_attr_font_features_new().

To enable the OpenType features support in the GTK file chooser, use GTK_FONT_CHOOSER_LEVEL_FEATURES flag:

gtk_font_chooser_set_level (chooser, level);


In summary, you can use the level property of GtkFontChooser to influence the granularity of font selection you offer to users of your application. If you include font features in it, don’t forget to apply the selected features, using PangoAttributes or markup.

All of this is enabled by harfbuzz providing us with a cross-platform API to fonts and all their features. It would not be possible otherwise. It is worth pointing out that this is done by accessing harfbuzz objects directly, rather than wrapping all the harfbuzz APIs in Pango.



sizable news

For the upcoming GTK 4.6, we have overhauled a lot of the sizing infrastructure to make widgets fit even tighter and to make sure our sizing infrastructure actually does what it says.


When using the GtkWidget::halign or GtkWidget::valign properties, GTK 4.4 would look at the default size of the widget and then place the widget accordingly. This leaves a lot of extra space when one of the values was set to fill. In GTK 4.6, GTK will measure the size of the other dimension relative to the filled dimension. This makes the widget thinner but avoids extra space.

A centered label with empty space in GTK 4.4
A centered label with empty space in GTK 4.4

A centered label with no extra space in GTK 4.6
A centered label with no extra space in GTK 4.6

What if you like the old behavior?

If you do not use fill in either direction, the behavior will be as before. So update the other dimension to not be the default fill and you should get the old behavior back.


GtkBox has learned to assign size to widgets as needed. In GTK 4.4, size was always distributed equally among children that had the same default size. GTK 4.6 will query the children for their actual size to decide which child to distribute how much of the extra size to.

You can see this in the example, where the box was given enough space for 3, 4, 5 or 6 lines of text.

A left-aligned box in GTK 4.4
A left-aligned box in GTK 4.6


As you could see above, GtkLabel also learned to properly wrap to any given number of lines. This allows labels to take a lot less widths as before, so they no longer take up empty space when they can just line-break.

xalign and halign

It’s worth pointing out that in a lot of cases applications used GtkWidget::halign = GTK_HALIGN_START; when they should have used GtkLabel::xalign = 0.0;. The first aligns the widget as far to the left as possible while the seconds aligns the text inside the assigned space to the left. So if your widgets suddenly look glued to the left edge, you might want to look into that.


GtkWindow has learned how to adapt minimum size to the aspect ratio. So you can now resize your windows any way you like and they will never get too small, but they will always get as small as possible, no matter if you want to make them flat and wide or thin and high.

a new warning

While doing this work, we figured out that a few widgets do not conform to measuring requirements and added a new warning. So if you see something like:
Gtk-CRITICAL **: 00:48:33.319: gtk_widget_measure: assertion 'for_size >= minimum opposite size' failed: 23 >= 42
It means you have a widget that reports an minimum size for size -1 that is larger than the minimum size it reports for a different size, and that should never happen. You can use GTK_DEBUG=size-request and redirect to a file to find the offending widget. We also added code to work around any problems that warning, but it should be fixed nonetheless. After all, if a widget reports a wrong size, it’s likely it’s doing something wrong.

GTK 4.4

GTK 4.4.0 is now available for download in the usual places. Here are some highlights of the work that has gone into it.

The NGL renderer and GL support

The NGL renderer has continued to see improvements. This includes speedups, fixes for transformed rendering, avoiding huge intermediate textures, and correct handling of partial color fonts. After some help from driver developers, NGL now works correctly with the Mali driver. We are planning to drop the original GL renderer in the next cycle.

Outside of GSK, our OpenGL setup code has been cleaned up and simplified. We increasingly rely on EGL, and require EGL 1.4 now. On X11 we use EGL, falling back to GLX if needed. On Windows, we default to using WGL.

Our GL support works fine with the latest NVidia driver.


The included themes have been reorganized and renamed. We now ship themes that are called Default, Default-dark, Default-hc and Default-hc-dark. The Adwaita theme is moving to libadwaita.

Among the smaller theme improvements are new error underlines (they are now dotted instead of squiggly) and support for translucent text selections.


Input handling has seen active development this cycle. We’ve matched the behavior of the built-in input method with IBus for displaying and handling compose sequences and dead keys. As part of this, we now support multiple dead keys and dead key combinations that don’t produce a single Unicode character (such as ẅ).

We fully support 32-bit keysyms now, so using Unicode keysyms (e.g. for combining marks) works.


Our Emoji data has been updated to CLDR 39, and we can are looking for translated Emoji data by both language and territory (e.g. it-ch).


The Inspector is now enabled by default, so debugging GTK applications should be a litte easier.


Apart from the WGL improvements that were already mentioned, we now use GL for media playback on Windows. A big change that landed late in 4.4 is that we use the WinPointer API for tablets and other input devices now, replacing the outdated wintab API. DND support on Windows is also improved, and the local DND protocol has been dropped.

The numbers

GTK 4.4 is the result of 5 months of development, with 838 individual commits from 71 developers; a total of 88133 lines were added and 63094 removed.

Developers with the most changesets
Matthias Clasen 456 54.4%
Benjamin Otte 82 9.8%
Emmanuele Bassi 48 5.7%
Alexander Mikhaylenko 35 4.2%
Chun-wei Fan 30 3.6%
Christian Hergert 18 2.1%
Luca Bacci 17 2.0%
Carlos Garnacho 10 1.2%
Bilal Elmoussaoui 10 1.2%
Florian Müllner 7 0.8%
Yuri Chornoivan 6 0.7%
Maximiliano Sandoval R 6 0.7%
Marc-André Lureau 5 0.6%
Marco Trevisan (Treviño) 5 0.6%
Pawan Chitrakar 5 0.6%
Piotr Drąg 4 0.5%
Timm Bäder 4 0.5%
Xavier Claessens 4 0.5%
Zhi 4 0.5%
Sebastian Cherek 4 0.5%