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.

Themes

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

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.

Emoji

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).

Debugging

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

Windows

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%

The GTK Documentation

As you may have noticed, there have been various changes in the GNOME developer documentation website, as of late. These changes also affected the API references for GTK and its core dependencies.

What has changed

The main change is that GTK moved to a new documentation tool for its API reference and ancillary documentation, called gi-docgen. Unlike the previous documentation tool, gtk-doc, gi-docgen uses the introspection data that is generated by GObject-based libraries to build the API reference. This has multiple benefits:

  • gi-docgen is simpler to run and integrate within an existing library, as it only has a single project description file and relies on the introspection data for everything else; additionally, it can be easily included as a Meson sub-project
  • gi-docgen uses Markdown everywhere, instead of DocBook
  • gi-docgen is considerably faster, as it does not perform an additional source code parsing step; it does not have the bottleneck of the XML to HTML conversion via xsltproc; and it does not have to parse Devhelp files to fix cross-references to other libraries after generating the reference
  • gi-docgen can infer much more information about an API, as it has access to the entire introspection data for a library, including its dependencies; this allows the automatic generation of more accurate and consistent documentation, instead of relying on humans to do this job
  • gi-docgen generates stable URLs for all the API entry points and additional documentation, which means it’s easier to link to and from it without using obscure references
  • the default documentation template is usable on different form factors and layouts; it respects the dark theme options on web browsers that support it; and provides an in-tree live search functionality that does not depend on third party services
  • gi-docgen can also be run out of tree—this will come in handy later

Outside of these improvements, using the introspection data as the source for the documentation has additional benefits: it keeps us honest in the type of API we expose to non-C users; and it makes the C API reference closer to the reference in other languages that consume the same data.

GTK4, Pango, and GdkPixbuf have been migrated to this new tool, and while we were at it, we also reviewed the documentation to improve its consistency and accuracy—especially for the older sections of the API.

The new API references can be used offline through Devhelp 41, which will be released next September alongside GNOME 41.

Online documentation

The canonical online location for the GTK references is now docs.gtk.org. There you will find the API references for:

The API references for GTK3 and ATK have been moved to docs.gtk.org as well.

The docs.gtk.org website is generated by the GTK CI pipeline, so it is always up to date with the state of the repository; thanks to gi-docgen supporting out of tree builds, the website can also generate documentation for various libraries that have not been ported to gi-docgen yet, like GLib, GTK3, and ATK.

Known issues

Of course, with any large change come side effects.

The main issue is the change in the URLs for the documentation; existing documentation referencing locations on developer.gnome.org will have to be fixed. Thanks to the GNOME system administrators we have some redirects in place, and there are ideas on how to improve them without creating an unmaintainable mess of static redirections.

The new documentation website is in the process of being indexed by various search engines; the more you use it, and link to it, the easier it will be for the new references to raise in ranking. In any case, we strongly encourage you to use the search feature: simply press ‘s’ to start searching for symbols and types, or even content inside the extra documentation pages.

Unfortunately, GLib’s introspection data has some issues, given how low level the C API is; we are working on improving that, which will have an impact not only in the documentation but also in the overall bindability of the API in other languages.

The documentation for GLib, GObject, GIO, and GTK3 is also still written for gtk-doc; this means that cross-links in the documentation may not work; the content may not be rendered as nicely; or there can be redundant paragraphs. This will be fixed in the future, both by changes in gi-docgen (wherever possible) and by updating the documentation inside the libraries themselves. This will also improve the language bindings documentation, as they consume the same introspection data as gi-docgen. Help in this effort is very much welcome.

Text input in GTK 4

To wrap up the recent series of posts about input topics, lets talk about text editing in GTK 4.

The simple: shortcuts

Maybe you just need to handle a few keys as editing commands, for example Ctrl-z to undo. In that case, you can just use a shortcut with an action, and set it all up in your widgets class_init:

/* install an undo action */ 
gtk_widget_class_install_action (widget_class,
                                  "text.undo", NULL,
                                  my_undo_func);

/* bind Ctrl-z to the undo action */
 gtk_widget_class_add_binding_action (widget_class,
                                      GDK_KEY_z, GDK_CONTROL_MASK,
                                      "text.undo", NULL);

The complex: a text editor

When you need full text editing, the best approach is to re-use one of the ready-made widgets in GTK for this purpose: one of the entries, or if you need a full-blown text editor, GtkTextView.

If none of the existing entries fit your use case, you can also wrap your own GtkEditable implementation around a GtkText widget, and get all the hard parts of a text editing widget for free. The GTK docs explain how to do that.

The middle ground

But what if you don’t want an entry, but still need to let your users enter individual Unicode characters such as ñ or Å conveniently? I’ll let you come up with a use case for this (although I have one in mind).

One thing you can do is to use a GtkIMContext directly, and let it process key events for you. The way this works is that you attach a key event controller to your widget and connect an input method context to it:

controller = gtk_event_controller_key_new ();
gtk_widget_add_controller (widget, controller);

im_context = gtk_im_multicontext_new ();
gtk_event_controller_key_set_im_context (controller, im_context);

Now key events that reach your widget will be passed to the input method context. Connect a handler to its ::commit signal to receive the completed input:

static void
commit_cb (GtkIMContext *context,
           const char   *str,
           DemoWidget   *demo)
{
  pango_layout_set_text (demo->layout, str, -1);
  pango_layout_set_attributes (demo->layout, NULL);
  gtk_widget_queue_draw (GTK_WIDGET (demo));
}

...

g_signal_connect (im_context, "commit",
                  G_CALLBACK (commit_cb), demo);

You can connect a similar handler to the ::preedit-changed signal to provide the user feedback during preedit like GtkEntry does.

The complete example for single-character input can be found here.

More on input

I’ve written about input before (here and here), and more recently, Carlos and myself gave a Guadec talk about input-related topics (slides). In those writings, I have explained how dead keys work, and how you can type

<dead_acute> A

to produce an Á character.

But input is full of surprises, and I’ve just learned about an alternative to dead keys that is worth presenting here.

Background

First lets recap what happens when you send the <dead_acute> A sequence to GTK.

We receive the first key event and notice that it is a dead key, so we stash it in what we call the preedit, and wait for the next event.  When the next key arrives, and it represents a letter (more precisely, is in one of the Unicode categories Ll, Lu, Lt, Lm or Lo), we look up the Unicode combining mark matching the dead_acute, which is U+301 COMBINING ACUTE ACCENT, and then we flip the sequence around. So the text that gets committed is

A <combining acute>

The reason that we have to flip things around is that combining marks go after the base character, while dead keys go before.

This works, but it is a bit unintuitive for writing multi-accented characters. You have to think about the accents you want to apply from top to bottom, since they get applied backwards. For example to create an  with an acute accent on top, you type

<dead_acute> <dead_circumflex> A

which then gets flipped around and ends up as:

A <combinining circumflex> <combining acute>

A better way

To me, it feels much more natural to specify the accents in that order:

  1. give me an A
  2. then put a ^ on top
  3. and then put an ´ on top

The good news is: we can do just that! Keyboard layouts can use any Unicode character as keysyms, so we can just use the combining marks directly, without the detour through dead keys.

For example, the “English (US,  Intl, AltGr Unicode combining)” layout contains keys for combining marks. A slight hurdle to using this layout is that it does not show up in the GNOME Settings keyboard panel by default. You have to run

gsettings set org.gnome.desktop.input-sources show-all-sources true

to make it show up.

The combining marks in this layout are placed in a “3rd level”. To use them, you need to set up a “3rd level chooser” key. In the keyboard panel, this is called the “Alternative Characters Key”. A common choice is the right Alt key.

After all these preparations, you can now type A Alt+^ Alt+’ to get an   with an   ́ on top. Neat!

Adventures in graphics APIs

Various people are working on porting desktop virtualization UIs to GTK4. This typically involves virgl, and the GTK3 solution was to use GtkGLArea.

With GTK4, rendering is happening in GL anyway, so it should be enough to just wrap your content in a GdkTexture and hand it to GTK, either by using it as a paintable with GtkPicture, or with a GskTextureNode in your own snapshot() implementation.

dmabuf detour

This is a nice theory, but the practice is more complicated – the content is typically available as a dmabuf object, and with 4k rendering, you really want to avoid extra copies if you can help it. So we had to look at the available solutions for importing dmabufs as textures into GL without copies.

This turned into a quick tour through the maze of graphics APIs: OpenGL, EGL, GL ES, GLX, DRI, … the list goes on. In the end, it turns out that you can use EGL  to wrap a dmabuf into an EGLImage, and use the GL_OES_EGL_image extension to create a GL texture from it.

GLX to EGL

This works fine with our Wayland backend, which uses EGL. Unfortunately, our much older X11 backend has a GL implementation using GLX, and there doesn’t seem to be a way to get a dmabuf imported into a GLX context.

So we had to do a little bit of extra work, and make our X11 backend use EGL as well. Thankfully Emmanuele had an old unfinished branch with  such a conversion from a few years ago, which could be made to work (after some initial head scratching why it would not render anything – as always the case when doing GL work).

The solution

It turns out that importing dmabufs with EGL can be done outside of GTK just fine, so we don’t need to add Linux-specific API for it. To save you the trouble of writing such code yourself, here is what I’ve come up with.

After we had already decided to port the X11 backend to EGL, I learned that another possibility for importing dmabufs might be to use DRI3PixmapFromBuffer to create  an X11 pixmap from a dmabuf, turn it in a GLXPixmap and use glxBindTexImageEXT to make a texture.

Aren’t graphics APIs wonderful! :-)

GTK 4.2.0

GTK 4.2.0 is now available for download in the usual places.

This release is the result of the initial round of feedback from the application developers porting their projects to GTK4, so it mostly consists of bug fixes and improvements to the API—but we also added new features, like a new GL renderer; various improvements in how the toolkit handles Compose and dead key sequences; build system improvements for compiling GTK on Windows and macOS; and a whole new API reference, generated from the same introspection data that language bindings also consume.

For more information, you can check the previous blog post about the 4.1 development cycle.

The NGL renderer

Thanks to the hard work of Christian Hergert, the NGL renderer is now the default renderer for Linux, Windows, and macOS. We’ve had really positive feedback from users on mobile platforms using drivers like Lima, with noticeable improvements in frames per second, as well as power and CPU usage; the latter two are also going to impact positively desktop and laptop users. The NGL renderer is just at the beginning: the new code base will allow us even more improvements down the line.

For the time being, we have kept the old GL renderer available; you can use export GSK_RENDERER=gl in your environment to go back to the 4.0 GL renderer—but make sure to file an issue if you need to do so, to give us the chance to fix the NGL renderer.

Input

Matthias wrote a whole blog post about the handling of Compose and dead keys input sequences, so you can just read it. The dead key handling has seen a few iterations, to deal with oddities and workarounds that have been introduced in the lower layers of the input stack.

There is one known issue with the handling of dead acute accents vs apostrophes in some keyboard layouts, which is still being investigated. If you notice other problems with keyboard input, specifically around Compose sequences or dead keys, please file an issue.

Portability

One of the goals of GTK is to have a “turn key” build system capable of going from a clone of the Git repository to a fully deployable installation of the toolkit, without having to go through all the dependencies manually, or using weird contraptions. You can see how this works on Windows, using native tools, in this article from our friends at Collabora.

Additionally, we now ensure that you can use GTK as a Meson sub-project; this means you can build GTK and all its dependencies as part of your own application’s build environment, and you can easily gather all the build artifacts for you to distribute alongside your application, using the toolchain of your choice.

Documentation

One of the most notorious issues for newcomers to GTK has been the documentation. Application developers not acquainted with our API have often found it hard to find information in our documentation; additionally, the style and structure of the API reference hasn’t been refreshed in ages. To improve the first impression, and the use of our documentation, GTK has switched to a new documentation generator, called gi-docgen. This new tool adds new features to the API reference, like client-side search of terms in the documentation; as well as nice little usability improvements, like:

  • a “Copy to clipboard” button for code fragments and examples
  • a visual hierarchy of ancestors and interfaces for each class
  • the list of inherited properties, signals, and methods in a class
  • a responsive design, which makes it easier to use the API reference on small screens

An API is only as good as it allows developers to use it in the most idiomatic way. GTK not only has a C API, it also exposes a whole API for language bindings to consume, through GObject-Introspection. The new documentation uses the same data, which not only allows us to cut down the built time in half, but it also generates common bits of documentation from the annotations in the source, making the API reference more consistent and reliable; finally, the C API reference matches what language binding authors see when consuming the introspection data, which means we are going to tighten the feedback loop between toolkit and bindings developers when introducing new API.

Pango and GdkPixbuf have also switched to gi-docgen, which allows us to build the API reference for various dependencies through our CI pipeline, and publish it to a whole new website: docs.gtk.org. You’ll always find the latest version of the GTK documentation there.

Odds and ends

Of course, alongside these visible changes we have smaller ones:

  • performance improvements all across the board, from GLSL shaders used to render our content, to the accessibility objects created on demand instead of upfront
  • sub-pixel positioning of text, when using a newer version of Cairo with the appropriate API
  • a responsive layout for the emoji chooser
  • improved rendering of shadows in popover widgets
  • localized digits in spin buttons
  • improved support for the Wayland input method protocol
  • improved scrolling performance of the text view widget

The numbers

GTK 4.2 is the result of four months of development, with 1268 individual changes from 54 developers; a total of 73950 lines were added, and 60717 removed.

Developers with the most changesets
Matthias Clasen 843 66.5%
Emmanuele Bassi 124 9.8%
Timm Bäder 87 6.9%
Christian Hergert 33 2.6%
Jakub Steiner 24 1.9%
Benjamin Otte 21 1.7%
Chun-wei Fan 15 1.2%
Alexander Mikhaylenko 14 1.1%
Fabio Lagalla 10 0.8%
Bilal Elmoussaoui 8 0.6%
Carlos Garnacho 6 0.5%
Ignacio Casal Quinteiro 6 0.5%
Michael Catanzaro 6 0.5%
Emmanuel Gil Peyrot 5 0.4%
Xavier Claessens 4 0.3%
David Lechner 4 0.3%
Jan Alexander Steffens (heftig) 4 0.3%
Kalev Lember 3 0.2%
wisp3rwind 3 0.2%
Mohammed Sadiq 2 0.2%
Developers with the most changed lines
Matthias Clasen 38475 42.6%
Emmanuele Bassi 15997 17.7%
Christian Hergert 13913 15.4%
Kalev Lember 9202 10.2%
Timm Bäder 5890 6.5%
Jakub Steiner 2397 2.7%
Benjamin Otte 902 1.0%
Chun-wei Fan 783 0.9%
Ignacio Casal Quinteiro 717 0.8%
Fabio Lagalla 292 0.3%
Marek Kasik 267 0.3%
Alexander Mikhaylenko 254 0.3%
Emmanuel Gil Peyrot 232 0.3%
Simon McVittie 214 0.2%
Jan Tojnar 83 0.1%
wisp3rwind 74 0.1%
Jan Alexander Steffens (heftig) 65 0.1%
Carlos Garnacho 62 0.1%
Michael Catanzaro 61 0.1%
Ungedummt 60 0.1%
Developers with the most lines removed
Emmanuele Bassi 8408 13.8%
Jakub Steiner 1890 3.1%
Timm Bäder 493 0.8%
Simon McVittie 203 0.3%
Emmanuel Gil Peyrot 146 0.2%
Chun-wei Fan 43 0.1%
Jan Tojnar 26 0.0%
Alexander Mikhaylenko 25 0.0%
Jonas Ådahl 17 0.0%
Luca Bacci 13 0.0%
Robert Mader 4 0.0%
Chris Mayo 3 0.0%
Bartłomiej Piotrowski 2 0.0%
Marc-André Lureau 2 0.0%
Jan Alexander Steffens (heftig) 1 0.0%
Tom Schoonjans 1 0.0%

Input, revisited

My last update talked about better visual feedback for Compose sequences in GTK’s input methods. I did not explicitly mention dead keys back then, but historically, X11 has treated dead keys and Compose sequences in exactly the same way.

Dead keys are a feature of certain keyboard layouts where you can hit a key that does not produce a character by itself, but modifies the next key you type. Typically, this is used for accents that can be combined with different base characters. For example, type <dead_acute> <a> to produce á or  <dead_acute> <o> to produce ó.

Traditionally, dead keys were really dead – you didn’t get any visual feedback before the final result appears. With the improvements described in the last update, we now show dead keys as they are entered:

That is a nice improvement. But as it turned out, not everybody was happy.

The shared treatment of Compose sequences and dead keys has some implications: one is that entering a non-existing sequence such as <dead_grave> <x> will produce a beep, and no output. That is acceptable for a Compose sequence that you explicitly started with the Compose key, but not so great when you maybe meant to enter `x.

The people who decided to use Compose sequences for dead keys foresaw the need to actually enter spacing accents every now and then, and added sequences such as <dead_grave> <space> and <dead_grave> <dead_grave> for producing a single ` character.

While that is a nice thought, it is still pretty inconvenient, since you need to type <dead_grave> six time to produce `‍`‍`, e.g. for entering code examples in markdown.

After thinking about this for a while and comparing what other systems do, we’ve made two changes, that will hopefully make dead keys as convenient to use as any other keys on your keyboard.

  • When a <dead key> <key> sequence does not match one of our Compose sequences, commit the individual keys
  • When a <dead key> follows another <dead key>, commit the first one, and treat the second as the beginning of a new Compose sequence

Together, this makes it so that typing <dead_acute> <a> produces á, typing <dead_grave> <x>  produces `x, and you only need to type <dead_grave> three times to enter `‍`‍`:

Much better!

GTK happenings

GTK 4.2 is due out in March – it will not be an enormous release, just incremental improvements. But besides the usual bug fixes and performance improvements, there are a few things that are worth calling out indvidually.

A new GL Renderer

Christian Hergert has been hard at work, creating a new GL renderer for GTK. The initial motivation for this work was the desire to improve our rendering performance on MacOS, where the GL drivers are not quite as forgiving as on Linux. Apart from that, starting over with a new renderer gives us a chance to apply all the things we’ve learned while working on our current GL renderer, and to reorganize the code with an eye towards future improvements, such as reordering and batching of draw commands.

The new renderer hasn’t been merged  yet, but it is closing in on feature parity and may well make it into 4.2. We will likely include both the old and the new renderer, at least for a while.

Popover Shadows

Ever since GtkPopover was introduced with its signature ‘beak’, popovers have clipped everything outside their border, since we needed the tip of the beak to be consistently placed. With the new xdg-popup based implementation in GTK4, we have an positioning protocol that is expressive enough to place popovers in a way that makes the ‘beak’ point where it is supposed to while allowing shadows underneath and around the popover. As with window shadows, the popover shadows are outside of the input region, so clicks go through to the underlying window.

This is a minor thing, but it may have a noticeable impact in giving the UI depth and structure.

Better Input

GtkIMContextSimple is the input method implementation that is built into GTK. It is used when we don’t have a platform method to use, such as the Wayland text protocol. GtkIMContextSimple only does a few things. One of them is to interpret hexadecimal input for Unicode characters, with Control-Shift-u. Another is that it handles Compose sequences, such as

<Compose Key> <a> <acute>

to enter an á  character.

Most Compose sequences start with that Compose Key, and the keyboard settings in GNOME 40 will include a way to assign a key on your keyboard to this function.

On the GTK side, we’ve addressed a few longstanding complaints with the Compose sequence support. Apart from its built-in sequences, GTK parses X11 Compose files. The format of these files is described in Compose(5), but until now, GTKs support for this format was pretty incomplete. With GTK 4.2, we’re improving this to

  • Allow sequences of up to 20 keys (previously, the limit was 7)
  • Generate multiple characters (notably, this allows Unicode Emoji sequences)
  • Support hexadecimal codepoints

These are nice improvements for people who make their own Compose sequences by editing ~/.Compose. But what about the rest of us? One traditionally difficult aspect of using Compose sequence is that you have to know the sequences by heart, and type them blindly. There is no visual feedback at all until the sequence is complete and the final character appears. A while ago, IBus improved on this by showing the characters of the incomplete sequence as underlined preedit text, similar to what we do for hexadecimal Unicode input.

After copying their approach for GTK, initial user feedback was mixed, mainly because the official glyph for the Compose Key (⎄) is a bit distracting when it appears unexpectedly. So I went back to the drawing board and came up with a different approach:

I hope this works better. Feedback welcome!

All of these input changes will also appear in GTK 3.24.26.

GTK 4.0.1

We all took a bit of a break after 4.0 and did some other things, but now it is time for GTK 4.0.1.

This is the first release after 4.0, and it naturally contains a lot of small bug fixes,  theme and documentation improvements, and the like. But there are a few highlights that are worth pointing out.

Better media support

Among the bigger advances in this release: we managed to make the gstreamer media backend use GL textures, which avoids bouncing frame data between gpu and cpu when using hardware acceleration for decoding, such as vaapi. This requires careful orchestration to bridge the differences in how gstreamer and GTK treat GL, but we managed to make it work in many cases.

Does this mean GtkVideo is now ready to support fully-featured media player applications? Far from it. It still just lets you play media from a file or url, and does not support multi-channel audio, video overlays, device selection, input, and other things that you probably want in a media player.

It would be really nice if somebody took the code in the GTK media backend and turned it inside out to make a GStreamer plugin with a sink that exposes its video frames as GdkPaintable. That would let you use gstreamer API to get all of the aforementioned features, while still integrating smoothly in GTK.

Better CI

In order to keep our new MacOS backend in working shape, we’ve started to set up CI builds for this platform, both for GTK itself, and for its dependencies (pango, gdk-pixbuf).

Who Wrote GTK4

GTK 4 has been a colossal, multi-year development endeavor that started in October 2016 and ended in December 2020. Now that the 4.0 release is finally out, it’s time to look back to the incredible amount of work done by hundreds of contributors over these four years.

Back in 2016 we were definitely a bit optimistic on the time table, and thought we would be able to release 4.0 in three years, by the end of 2019. The plan was to start by changing the rendering pipeline of GTK, by moving it to a retained graph of operations that could be submitted to the GPU, as opposed to the immediate mode rendering that we had since the very beginning of the toolkit, and which survived two major API cycles—first by abstracting Xlib drawing commands, and then by moving to Cairo operations. Of course, we also knew we wanted to improve other sub-systems, like input and the windowing system API, to move away from X11-isms and towards a design more in line with the requirements of Wayland (and other windowing systems). What we got, after all was said and done, is a deep redesign of the internals of the toolkit, as well as a different programming model that favors more delegation through ancillary objects, and fewer leaky abstractions and deep type hierarchies; additionally, we pared down the exposed internals, to ensure that the toolkit, and the applications using it, will be more maintainable in the future. The downside is that GTK is less of a “meta toolkit”, whose internal state can be poked at from the outside while expecting to work across multiple releases; that approach was, in the long term, unsustainable given the available resources, and left us unable to optimise or improve the internals of GTK, to the detriment of every user.

We don’t expect the next major development cycle to take this much time, but you know as they say: no plan of operations extends with any certainty beyond the first contact with the main hostile force. The important thing, though, is that we still see potential for improvement; and while we want to celebrate the release of GTK4, as well as everyone who contributed to it, we also want to communicate that the plan outlined in 2016 is still very much in effect. We already started collecting items for a GTK5 development cycle in our GitLab project page, and we plan to have more discussions with various stakeholders for future work in that direction.

Some statistics

Starting from commit 4cce6104 on October 5th, 2016:

  • Total commits: 16852
  • Developers: 256
  • Employers: 10
  • Lines added: 1053492, removed: 1053542 (delta: -50)

The most interesting thing is that, for all that work, we ended up with a total of 50 lines of code removed from the existing code base, which includes tests and documentation.

Per year breakdown

Year Developers Commits Lines added Lines removed Delta
2016 50 1422 64014 152103 -88089
2017 84 3446 186024 166198 19826
2018 111 2332 129726 140526 -10800
2019 85 3244 200476 207623 -7147
2020 109 6384 470907 386761 84206

We only had a couple of months in 2016, and the largest effort between October and December was the removal of the deprecated API, and various changes to cope with the renaming from GTK3 to GTK4. Nevertheless, GSK initially landed in November/December. On November 21st, GTK 3.89.1 was released, the first development snapshot of the new GTK 4 API.

In 2017, GSK had with multiple iterations over its API: new render nodes were added to implement CSS drawing primitives, and widgets were moved to the GtkSnapshot API from the old Cairo rendering primitives. Additionally, the new clipboard API was introduced, with a stream-based implementation. On March 31st, GTK 3.90.0 was released, followed by 3.92.0 in October.

In 2018, things seem to slow down, but mostly because we moved to GitLab. Suddenly, we had access to a CI pipeline and merge requests, and we became progressively more confident in our development process; lots of work happened in development branches, especially large refactorings, like the renaming of GdkWindow to GdkSurface; the move to GtkGesture objects and the removal of per-widget event signals; or making leaf classes not derivable. GTK 3.94.0 was released in June.

In 2019, development pace picked up once again:

  • widget transformations
  • layout managers
  • constraint layouts
  • no more GtkMenu
  • scope object for GtkBuilder
  • GtkText widget
  • GtkNative and GtkRoot interfaces
  • per-widget actions
  • simplified GdkSurface sub-types

Plus, of course, lots of performance and functionality improvements in the rendering pipeline. GTK 3.96.0 was released in May.

Finally, we arrive at 2020:

  • new drag and drop API, based on event controllers
  • new macOS backend in GDK, replacing the old Quartz one
  • new accessibility API, dropping ATK
  • no more GtkContainer
  • no more GtkRadioButton
  • simplified GdkDevice API
  • new keyboard shortcuts API
  • new expressions and filter models
  • new model-based list and tree widgets

GTK 3.98.0 was released in February; and, finally, 3.99.0 in July, as the first true beta towards GTK 4.0.

 

Developers

Top 20 by commit
Matthias Clasen 6519 (38.7%)
Timm Bäder 3229 (19.2%)
Benjamin Otte 2596 (15.4%)
Emmanuele Bassi 1094 (6.0%)
Carlos Garnacho 494 (2.9%)
Daniel Boles 383 (2.3%)
Alexander Larsson 313 (1.9%)
Jonas Ådahl 167 (1.0%)
Chun-wei Fan 162 (1.0%)
Christian Hergert 158 (0.9%)
Jakub Steiner 134 (0.8%)
Piotr Drąg 132 (0.8%)
Руслан Ижбулатов 120 (0.7%)
Alexander Mikhaylenko 93 (0.6%)
Rico Tzschichholz 78 (0.5%)
nana-4 66 (0.4%)
Christoph Reiter 62 (0.4%)
Tim-Philipp Müller 60 (0.4%)
Mohammed Sadiq 57 (0.3%)
Olivier Fourdan 42 (0.2%)
Top 20 by changes
Matthias Clasen 620248 (36.8%)
Benjamin Otte 466996 (27.7%)
Timm Bäder 187516 (11.1%)
Emmanuele Bassi 165354 (9.8%)
Alexander Larsson 53065 (3.1%)
Carlos Garnacho 27227 (1.6%)
Christian Hergert 26964 (1.6%)
Руслан Ижбулатов 21760 (1.3%)
Jakub Steiner 18388 (1.1%)
Jonas Ådahl 12824 (0.8%)
Chun-wei Fan 12518 (0.7%)
Daniel Boles 12371 (0.7%)
Lapo Calamandrei 9995 (0.6%)
Christoph Reiter 8391 (0.5%)
Alexander Mikhaylenko 4936 (0.3%)
Tim-Philipp Müller 3932 (0.2%)
Rico Tzschichholz 3108 (0.2%)
William Hua 2900 (0.2%)
Jason Francis 1908 (0.1%)
Peter Bloomfield 1727 (0.1%)

As usual, Matthias towers over every other contributor, both in terms of sheer number of commits and in terms of code changes.

Employers

By commit
Red Hat 13706 (81.3%)
(Unknown) 1185 (7.0%)
GNOME Foundation 1095 (6.5%)
GNOME 571 (3.4%)
Purism 93 (0.6%)
Canonical 84 (0.5%)
Centricular 75 (0.4%)
Endless 20 (0.1%)
Collabora 14 (0.1%)
Intel 6 (0.0%)
Novell 3 (0.0%)
By changes
Red Hat 1415771 (84.0%)
GNOME Foundation 165355 (9.8%)
(Unknown) 58220 (3.5%)
GNOME 33442 (2.0%)
Purism 4936 (0.3%)
Centricular 4205 (0.2%)
Canonical 3347 (0.2%)
Novell 336 (0.0%)
Intel 222 (0.0%)
Collabora 208 (0.0%)
Endless 121 (0.0%)
By contributor
(Unknown) 199 (72.4%)
GNOME 32 (11.6%)
Red Hat 22 (8.0%)
Endless 6 (2.2%)
Collabora 4 (1.5%)
Centricular 3 (1.1%)
Novell 3 (1.1%)
GNOME Foundation 2 (0.7%)
Canonical 2 (0.7%)
Intel 1 (0.4%)
Purism 1 (0.4%)

While Red Hat employees affect the most changes, we still have a very large number of contributors from the community—both using their GNOME email address and using their work address even when contributing on a personal level. We also have multiple contributors from various companies in the GNOME and free software at large ecosystems, signalling a healthy community around the project.

Comparing numbers with GTK3 is a bit more tricky:

  • the GTK 2 → 3 development phase only took about a year and change, instead of four years
  • we were still using the old GNOME infrastructure, which meant fewer, larger patches, and a higher barrier to contribution in the form of Bugzilla

Nevertheless, the amount of contributors more than doubled compared to 2011, with almost three times the amount of unaffiliated contributors.

¹ – Paid staff of the GNOME Foundation.

² – Contributors using a gnome.org email address with no clear employment status.