Builder GTK 4 Porting, Part II

Another week of work towards porting Builder to GTK 4. Since I can’t add to TWIG from IRC, I’ll try harder to drop some occasional updates here.

GtkSourceView

  • Merged fixes for highlighting unicode literals for C
  • Improved parsing of language values in snippet bundles
  • GtkSourceGutter will not correctly mark prelit and selection quarks within GtkSourceGutterLines.
  • Fixed a bunch of little mouse pointer annoyances when using GtkSourceHover interactive tooltips.
  • GtkSourceGutterRenderers can now opt-out of signal emission for GtkSourceGutterRenderer::query_data(). Signal emission with GObject is rather slow, so avoiding it on every line can be helpful. Just set the virtual method pointer to NULL. The signal was only ever added to make porting easier anyway.

libpanel

  • Merged fixes to be used as a subproject with static libraries only
  • CSS styling matches recent changes in libadwaita, particularly around making navigation tabs and panel frame headers more unified.
  • PanelWidget no longer uses a GtkBinLayout so that it’s easier for subclasses to integrate with popovers from size_allocate() to call gtk_popover_present().

Builder

  • Georges did a live coding stream where they ported a bunch of the “buildui” plugin. That is merged to the GTK 4 port now. It brings a number of features back to the UI including the build terminal, run terminal, build panel (with pipeline stages, warnings, and errors), and project information in the omnibar popover.
  • Günther did a bunch of work porting our old snippet files to the new XML-based snippet bundle format upstream in GtkSourceView. Along with that came porting of the snippets plugin for Builder’s new GTK 4-based editor.
  • Workspace windows have a bit better predictability when restoring sizes.
  • The project creation workflow was ported, albeit needs to have the redesign implemented still.
  • Lots of resiliency fixes for clang and symbol-tree plugins to improve life-cycle management.
  • The Valgrind plugin was ported to C. This was also back-ported to main because it fixed a number of oddities (crashes) occurring in PyGObject.
  • Builder’s “omni-gutter” GtkSourceGutterRenderer was ported to GTK 4 and got a lot of cleanups along the way. I believe there is still some outstanding things to fix such as handling rendering for symbolic icons as I’m pretty sure that’s not correct yet.
  • The “debuggerui” plugin has been ported to GTK 4 and appears to be working well now. This plugin is responsible for bridging the internal IdeDebugger interfaces to the UI interface.
  • Style schemes were updated for GtkSourceView 5
  • Tabs are now the default navigation interface for pages. There is likely still a lot to do around how we want empty frames to look and behave though.
  • The project-tree is now most ported, and with some workarounds to allow making GtkPopover work you can actually display popovers and activate menu items.
  • A long-standing plugin ordering issue has been fixed so that gtk/menus.ui embedded in plugin resources have menu-merging in the proper order.
  • Some incremental work landed to support per-project configuration of languages.
  • The “ls” plugin (directory views) supports “humanized” timestamps again and columns are resizable once more.
  • You can place panels in the right-side-bar now.

Upcoming

There are a bunch of foundational things to still get landed before I feel I can get Builder flipped over to our Nightly builds. In particular we need to land support for things like:

  • Keyboard shortcuts using GtkShortcutController. This was all done with libdazzle previously.
  • Allow plugins to define custom keyboard shortcuts and merge them into the controller.
  • Port “shellcmd” plugin and integrate keyboard shortcuts to apply those commands.
  • Finish rewrite of the search popover. I’m trying to delay this until GtkListView with sections is supported, as it would provide us a much greater path for performance.
  • A lot of our problems would be simpler if we could make GtkActionMuxer use an alternate action muxer parent from another (non-descendant) widget.
  • Configuration editing in the project configuration window. This is a new design so the port is not 1:1.

A screenshot of Builder with the project-tree context menu and debugger on display

A screenshot of Builder with various panels moved around to non-standard locations

Builder GTK 4 Porting, Part I

Now that GNOME 42 was released in March I’ve had spare cycles to focus on porting Builder to GTK 4 in April. I’ve made a lot of progress thus far, but there is still plenty to go.

Builder is certainly one of the larger GTK applications out there and so it can be a bit daunting unless you embrace your inner hubris and just forget where the end of the tunnel is.

During this porting effort I’ve also been taking time to redo a number of things that just weren’t working well for us. Additionally I’ve spent significant time on what would appear to be tangents, with the goals of easing the porting effort. For example, before I set off on the port I spent time doing things like

  • Work with Matthias Clasen to make GtkTextView support GPU rendering, then make it fast. More recently we’ve even experimented with drawing font shapes at any scale on the GPU thanks to work by Behdad on GLyphy.
  • Write a new macOS back-end for GTK 4 to improve our cross-platform portability and performance story
  • Modernize GTK 4’s GL renderer to help reduce overhead. And then modernize that a bit more to work around Apple’s lack of something like eglSwapBuffersWithDamage().
  • Port Sysprof to GTK 4 and continue helping integrate it into layers of the stack like GLib, GJS, GTK, Pango, GtkSourceView, GNOME Shell, and more.
  • Port D-Spy to GTK 4 and abstract a library for Builder usage
  • Port GtkSourceView to GTK 4
    • Improve GPU rendering by premultiplying alpha, altering when/where some nodes are snapshotted, and how we draw certain textures.
    • JIT’d regexes for syntax highlighting sub-system using PCRE2 instead of the old GRegex APIs
    • JIT’d regexes for text search sub-system also with PCRE2
    • Port Builder’s completion engine upstream to reduce time-to-display and memory overhead
    • Port Builder’s snippet engine and syntax upstream
    • Port Builder’s interactive tool-tips (Hover Providers) upstream
    • Port Builder’s auto-indentation engine upstream
    • Write a new Vim emulation engine upstream in GtkSourceView so we can drop Builder’s
  • Work with Alexander to implement application-wide recoloring support for libadwaita-based applications using GtkSourceView style-schemes
  • Write GNOME Text Editor to prove all the components are working
  • Write a new spell-check engine for GTK 4 (also used by Text Editor) including the creation of a new hybrid data-structure combining a piecetable and a B+Tree
  • Write a new docking/panel engine for GTK 4
  • Write a GTK 4 based designer (Drafting) in coordination with my upstream GTK 4 work so that we can support separation of designer and build/dev containers where code may run. More on that later though when it lands in Builder.

We’ve also been eagerly awaiting GTK 4 ports of both WebKit and VTE, neither of which are trivial efforts to do well. And by well I mean passing GL composited GL textures for a browser or taking advantage of GTK’s fast text rendering/caching/layout. The good news is that these are starting to come together.

People that follow my Twitter have already seen these of course. My goal is to land the GTK 4 port in Builder’s Nightly in May some time so that we get plenty of testing before GNOME 43. It’s a large application, so it will need all the testing it can get.

A screenshot of Builder's GTK 4 port

Preferences

Preferences is getting a major revamp in our GTK 4 port to make things a bit nicer to look at and also easier to locate features and tweaks. The tricky part with things like this is making it easy for plugins to extend it without “reeking of plug-in based design”.

A screenshot of Builder's new preferences window

Another thing we’ve always wanted in Builder but couldn’t really do at the time was to allow per-project overrides. I’m happy to say that we will likely have this landed in our GTK 4 port. A number of things like per-language settings can be overriden on a per-project basis. I also hope to see build systems and tooling extend the project settings much more than we did in the past. For example, the Meson plugin could use meson_options.txt to add appropriate toggles.

Menus

Builder has always had a minimalist design to keep “machinery” out of the way and in most cases just do the right thing for you. We still want that design but we also want to expand on the things you can do. So you’ll find some new menuing in Builder’s GTK 4 port which will get wired up soon to do just that.

Things that have to do with Building can be found near the Build button.

A screenshot of Builder's build menu in the center top of the window

Things that have to do with Running can be found near the Run button.

A screenshot of the run menu in the center top of the window.

We’ve also dropped the “surface” abstraction in the GTK 4 port as it really only added confusion without much benefit. Our new paneling engine will make our reasoning for having that abstraction a non-issue.

Statusbar

You’ll notice that the GTK 4 port of Builder has a statusbar which can be extended by plugins. I tried for years to avoid it, but honestly, it just makes designing things easier and everyone is already using them in similar products. No need to begrudgingly hold out from a design standpoint.

Text Editor with More

Some people really don’t like IDEs, and I totally get that.

However, if you like the new Text Editor I wrote for inclusion in GNOME 42 but find it’s not quite powerful enough for the type of programming you do, Builder might still be able to help you out. It has an editor mode which is a much more powerful version of Text Editor with a robust and mature plugin architecture.

A screenshot of Builder's simple editor mode.

Additionally, users of Builder’s IDE functionality can add one of these supplemental editor windows to additional monitors. The window will be linked to your project’s primary workspace meaning all the same functionality is there, simply on an additional monitor.

Portability

It even runs on macOS! If you’d like to see this work better there, I imagine there are opportunities to improve transparent podman support so that people who use macOS can still take advantage of Linux containers. Even though I wrote the new macOS back-end for GTK, I don’t actually use it in my daily life, so my effort there is going to be limited.

A screenshot of Builder's GTK 4 port running on macOS

Additionally, if you’d like to help on things, the scope of Builder can grow considerably now that we have a toolkit that will enable us to do that. If you’d like to help do things like simulators, cross-device integration, debuggers, language server integration, or other fancy new features, we’d love your contributions!