Builder GTK 4 Porting, Part V

Previously Part IV, Part III, Part II, and Part I.

Still working through medicine changes which have wreaked havoc on my sleep, but starting to settle in a bit more.


Small changes here and there for template-glib to cover more cases for us in our keybindings effort. Improved type comparisons, fixed some embarrassing bugs, improved both GObject Introspection and GType method resolution.

Had some interesting talks with Benjamin about expression language needs within GTK and what things I’ve learned from Template-GLib that could be extracted/rewritten with a particular focus on continuously-evaluating-expressions.

Text Editor

I include gnome-text-editor in these updates because I tend to share code between Builder and g-t-e frequently.

  • Improved session resiliency
  • The Save-As dialog will now suggest filenames based on your current language syntax
  • Tracked down some property orderings which ended up being a GTK bug, so fixed that too
  • Persisted maximized window state to the session object on disk
  • Support to inhibit logout while documents are modified
  • Allow starting a single instance of the app with -s|--standalone like we do with Builder


  • More API strawmen for things we need in Builder
  • Fix some checkbutton annoyances
  • Removed assertions from debug builds during failure cases, converted to g_criticals()


  • Updated CI to use a newer Fedora release for more recent wayland protocols and what not
  • More work on source assistants and how measure/present are applied to popovers
  • Improved when and how we show informative tooltips with snippets
  • Add a bunch of “suggested-name” and “suggested-suffix” metadata properties to language specifications so that applications may suggest filenames for Save-As
  • Made Vim emulation of registers global to the application rather than per-view which makes things actually useful and expected behavior to share content between documents
  • Squash some testsuite issues


Merged a bunch of cleanup commits from the community which is very helpful and appreciated!

I also decided that we’re going to remove all PyGObject plugins from Builder itself. We’ll still have it enabled for third-party plugins, at least for now. Maybe someday we’ll get a GJS back-end for libpeas and we could go that route instead. I’ve spent too much time tracking down bindings issues which made me feel very much like I was still working on MonoDevelop circa 2004. That experience was the whole reason I wrote Builder in C to begin with.

None of our PyGObject plugins are all that complicated so I’ve rewritten most of them in C and had help for a few others. So far that covers: blueprint, clangd, go-langserv (now gpls), intelephense, jedi-language-server, ts-language-server, vala-language-server, buildstream, cargo, copyright, eslint, find-other-file, jhbuild, make, mono, phpize, rstcheck, rubocop, stylelint, and waf.

A few got removed instead for various reasons. That includes gvls (replaced by vala-language-server), rls (replaced by rust-analyzer), and gjs-symbols (to be replaced by ts-language-server eventually).

I added support for two new language servers: bash-language-server and jdtls (Java) although we don’t have any bundling capabilities for them yet with regards to Flatpak.

I’ve landed a new “Create New Project” design which required a bunch of plumbing cleanup and simplification of how templates work. That will help me in porting the meson-templates and make-templates plugins to C too.

A screenshot of the "Create New Project" design

I’ve added quick access to Errors and Warnings in the statusbar so that we can remove it from the (largely hidden) pane within the left sidebar. Particularly I’d like to see someone contribute an addition to limit the list to the current file.

A screenshot of the errors/warnings popover

I updated the support for Sysprof so that it can integrate with Builder’s application runners and new workspace designs. You can how have Sysprof data in pages which provides a lot more flexibility. Long term I’d like to see us add API hooks in Sysprof so that we can jump from symbol names in the callgraphs to source code.

A screenshot of Sysprof embedded within Builder

We cleaned up how symbolic icons are rendered in the greeter as well as how we show scroll state with a GtkScrolledWindow when you have a AdwHeaderBar.flat.

A screenshot of the greeter window

Our Valgrind plugin got more tweakables from the Run menu to help you do leak detection.

A screenshot of the valgrind menu

Keybindings for “Build and Run” along with various tooling got simplified to be more predictable. Also a lot of work on the menuing structure to be a bit simpler to follow.

A screenshot of the updated Run menu

You can force various a11y settings now to help get developers testing things they might otherwise never test.

A screenshot of the a11y menu containing high-contrast and ltr/rtl controls

Same goes for testing various libadwaita and libhandy settings. Both this and the RTL/LTR settings have a few things that still need to propagate through the stack, but it will happen soon enough.

A screenshot showing the forced-appearance modes for libadwaita/libhandy

Using Sysprof will be a lot easier to tweak going forward now that there are menu entries for a lot of the instruments.

A screenshot of the sysprof menu

A lot of new infrastructure is starting to land, but not really visible at the moment. Of note is the ability to separate build artifacts and runnables. This will give users a lot more control over what gets built by default and what gets run by default.

For example, a lot of people have asked for run support with better environment variable control. This should be trivial going forward. It also allows for us to do the same when it comes to tooling like “run this particular testsuite under valgrind”.

As always, freshest content tends to be found here 🐦 before I manage to find a spare moment to blog.

Builder GTK 4 Porting, Part IV

This week was a little slower as I was struggling with an adjustment to my new medication. Things progress nonetheless.

Text Editor

I spent a little time this week triaging some incoming Text Editor issues and feature requests. I’d really like this application to get into maintenance mode soon because I have plenty of other projects to maintain.

  • Added support for gnome-text-editor - to open a file from standard input, even if you’re communicating to a single instance application from terminal.
  • Branch GNOME 42 so we can add new strings.
  • Fix a no-data-loss crash during shutdown.


  • Fix template evaluation on macOS.
  • Make boolean expression precedence more predictable.
  • Cleanup output of templates with regards to newlines.


  • Propagate modified page state to tabs
  • Some action tweaks to make things more keyboard shortcut friendly.


  • Merged support for configuration editing from Georges.
  • Add lots of keybindings using our new keybinding engine.
  • Track down and triage that shortcut controllers do not capture/bubble to popovers. Added workarounds for common popovers in Builder.
  • Teach Builder to load keybindings from plugins again and auto-manage them.
  • Lots of tweaks to the debugger UI and where widgetry is placed.
  • Added syntax highlighting for debugger disassembly.
  • Added menus and toggles for various logging and debugger hooks. You can get a breakpoint on g_warning() or g_critical() by checking a box.
  • Ability to select a build target as the default build target finally.
  • More menuing fixes all over the place, particularly with treeviews and sourceviews.
  • Fix keyboard navigation and activation for the new symbol-tree
  • Port the find-other-file plugin to the new workspace design which no longer requires using global search.
  • GTK 4 doesn’t appear to scroll to cells in textview as reliably as I’d like, so I dropped the animation code in Builder and we jump strait to the target before showing popovers.
  • Various work on per-language settings overrides by project.
  • Drop the Rust rls plugin as we can pretty much just rely on rust-analyzer now.
  • Lots of CSS tweaks to make things fit a bit better with upcoming GNOME styling.
  • Fix broken dialog which prevented SDK updates from occurring with other dependencies.

A screenshot of builder's find-other-file plugin

A screenshot of Builder's debugger

A screenshot showing the build target selection dialog

A screenshot of the run menu A screenshot of the logging menu

Builder GTK 4 Porting, Part III

Another week of porting Builder which ultimately sent me on a few fun tangents. I especially enjoyed the work on Template-GLib which brought me back to my days working on languages and runtimes.


  • Prototype and submit a merge request to add support for setting an action parent on a widget. This allows you to alter the normal GtkActionMuxer action resolution. Very handy for situations like Builder and other document-oriented applications.


  • GtkSourceView updates to make it possible to write an external “snippet editor” application (Günther is working on one already)
  • Improve Solarized style schemes a bit for better IDE integration by specifying colors for diff as they can be used by git-based gutter renderers.
  • A little more performance work on gutter renderers as they have always been a major source of runtime costs.
  • Allow gutter renderers to overdraw atop the textview so they can do some more fancy things.


  • Figured out why I was getting spinning CPU with the VTE port for GTK 4. Submitted a diagnosis/fix upstream.


  • Prototyped and landed a new shortcut manager with uses a keybindings.json-like file similar to VS Code (albeit with slightly different syntax which makes more sense for GTK applications). Plugins will be able to override and extend these, as will the user.
  • Prototyped and landed support for showing “selection area” within the gutter renderer.
  • Compress information in a bit tighter space for gutter, as we have a lot of information to display there. Still more we can do should anyone have free time to work on this.
  • Improve breakpoints drawing now that we have some overlapping selections to worry about.
  • Lots of menu cleanup across plugins.
  • More porting from our old IdeSourceView into a new implementation.
  • Lots of object-lifecycle fixes now that Builder more aggressively shuts down components.

Keybindings look something like this.

I would like to specify how wonderful the new shortcut components are in GTK 4, particularly if you’re writing complex applications that have to manage layered shortcuts, user overrides, and such. I’m thinking applications in the class of Inkscape, GIMP, Builder, Darktable, and such will really benefit from this someday.

A screenshot of Builders updated line selections


One of the things that Builder needed was the ability to express when a shortcut is active. In VS Code, they have a "when" element which works well enough for this. However, it has some basic expressions that need to be evaluated at runtime.

Builder already has an expression engine which is used for project templates and what not and it even supports GObject Introspection. It was in sore need of some updates but is very capable for the problem here. I have the tendency to only implement enough to solve problems so this was a nice return to finishing some of that up.

One of the nice things here, when the use case is so focused, is that there is no need for a runtime, JIT, etc. It’s just an AST that has a tmpl_expr_eval() API where you pass in scope and all the objects continue to live in C land, nothing special to deal with.

  • Add anonymous functions (no lambdas though).
  • Allow assigning functions to a symbol.
  • Improve function calling under various situations (named, anonymous, and GObject Introspection functions).
  • Make constructors work.
  • Add a bunch of builtins for things like asserts, casts, math.
  • Fix typeof() builtin for a number of GObject Introspection cases.
  • Add unit tests!
  • Add null keyword.
  • You can now do things like typeof(widget).is_a(typeof(Ide.Page))
  • The require Gtk version "4.0" style imports made it so you couldn’t call .require() due to the Bison parser. That is fixed and you can use @keyword for reserved keywords.
  • A nop has been added with the keyword pass.
  • Fix a bunch of valgrind discovered things.
  • Add linewise comments using the # python style.

I don’t know how much time I’ll spend on this in the future, or if it will go another few years without much work. But with a maintainer who had time, it could be a nice little glue language without all the “muchness” that more well known languages tend to bring in.