I haven’t talked about ‘regular’ software development in a very long time, but it is something I do on a regular basis. In addition to my work at Ubisoft, I also have a few open-source applications for Linux that I’ve written over the years. When GTK4 released a couple months ago, I was quite interested in trying it out.
I’ve just gone through a full GTK4 port, so now it’s time to share my thoughts on the new release!
GTK in a Nutshell
Before we dive into the new update, I think it’s wise to explain what GTK is for those who may not know.
GTK is an open-source framework for building GUIs in desktop applications. It’s one of two main frameworks powering most graphical Linux apps (QT is the other), and sits under the same umbrella as the GNOME desktop project. So, as you can imagine—the 4th major release of this framework is a pretty big deal for Linux desktop application development.
I don’t want this post to just be a list of changes, since you can find better writeups of that elsewhere. Instead, the focus will be on the port process of one program and how the changes in GTK4 affected it.
The application we’ll be looking at today is Rida, a small comic and manga reading program written in Vala. It’s intended as a simpler and more modern alternative to MComix, with plans to add plugin-based support for reading comics through various web services. I don’t consider it polished enough for release, but it works well enough for personal use. What matters here is that it’s a very good candidate for testing out GTK4—images (and rendering as a whole) evolved quite a bit in this update, and as you can imagine comic readers are all about drawing pictures onscreen!
On the code side, Rida is a bit of an experiment. Fueled by my profesional work with WPF, I wanted to try a pattern like Presentation-Model in GTK and see how viable it could be. This runs a little bit counter to how GTK operates in some ways, so there are aspects that I fully expected to break during the upgrade process. On the upside, it also means that much of the application logic is well separated from the UI code. In theory, a big UI update shouldn’t change the operation of the program much. Let’s see how those assumptions held up in practice!
The Porting Process
Following the port guide helpfully released by the GTK devteam, the first big hurdle that I had to cross was input handling. For years, GTK widgets exposed simple events like
key-press-event. GTK4 removes these in favor of ‘Event Controllers’, which let you attach event-handling to parts of your UI and more precisely control how input events get propagated across it. I think this is a good idea on its face, but the event controllers seem to be a lot less reliable than the old events… I’ve had a few instances where inputs seemingly get dropped, and it’s difficult to debug where they’re going. I’m sure the devteam will keep iterating on the process of debugging these, but in the meantime they’re one of my bigger pain points with GTK4.
Actions were another problem that I ran into, in part due to my peculiar setup. In order to contain backend code outside of the UI, I attached certain comic-related actions to the presentationmodel model object bridging comics to the reader view… unfortunately, it seems that unmapping and remapping actions to the UI doesn’t work like it did in GTK3. After a few hours of debugging, I gave up and restructured my code to make the actions static. Thankfully, this isn’t a very common case and it’s easy to work around.
Beyond these two issues, the presentation/model layers were barely affected by the port. The only other change that affected these sections of the code was the big rendering change. This actually just amounted to replacing
GdkPaintable, and stripping out much of my image scaling code in favor for the stuff now built into GTK proper. Personally, I’d call that a big win! I was expecting a lot of pain from such a huge change, but it really just let me cut code out of the application altogether.
Beyond the 3 big changes above, GTK4 also had a bunch of changes to visibility, widget hierarchies, and other stuff related to the overall structure of the UI. I haven’t really dug into these much, but they let me cut a lot of lines out of my UI defnition files. As always, any feature that lets me write less code for the same result is welcome!
In the end, just porting to GTK4 shrank my codebase by roughly 10%. The rendering changes also seem to have made many parts of the UI smoother and more responsive. I’m rather impressed by the end result and I’m excited to update my other applications.
GTK4 still has some sticking points, but these mostly seem like bugs or areas that haven’t been as thoroughly polished yet. Overall this new update feels like a big step in the right direction, with a lot of much-needed streamlining and optimization. I’ll keep gradually porting over my projects, and write about those ports if I see anything new while doing so.