A Markup Language for GTK

22 October 2021

GTK has an XML-based format for declaratively constructing user interface components. It looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <template class="TestWindow" parent="GtkApplicationWindow">
    <property name="default-width">600</property>
    <property name="default-height">300</property>
    <child type="titlebar">
      <object class="GtkHeaderBar" id="header_bar">
        <child type="end">
          <object class="GtkMenuButton">
            <property name="icon-name">open-menu-symbolic</property>
          </object>
        </child>
      </object>
    </child>
    <child>
      <object class="GtkLabel" id="label">
        <property name="label" translatable="yes">Hello, World!</property>
      </object>
    </child>
  </template>
</interface>
A window with the text "Hello, world" in the middle

I’ve never particularly liked this format. It’s great to have a declarative format instead of building everything in code, but this XML is verbose and hard to understand. It’s too much effort to write, and when I’m reviewing my merge requests, I usually skip the UI files because it’s so hard to read the diffs.

In my ideal world, I’d be able to build the same UI with some code like this:

@gtk "4.0";

@template TestWindow : Gtk.ApplicationWindow {
  default-width: 600;
  default-height: 300;

  [titlebar]
  Gtk.HeaderBar header_bar {
    [end]
    Gtk.MenuButton {
      icon-name: "open-menu-symbolic";
    }
  }

  Gtk.Label label {
    label: _("Hello, world!");
  }
}

So I’ve been working on exactly that: a dedicated markup language that compiles to GtkBuilder XML. The example isn’t much shorter than the XML, but in my opinion, it’s vastly easier to read. It’s less cluttered and much easier to visually scan.

Of course, the downside is that you have to learn a new markup language, with all its syntax and quirks. But I think with good enough developer tooling, it won’t be an issue. On that front, I’ve also begun writing a language server with diagnostics, documentation on hover, and completion.

How It Works

The program, currently called gtk-blueprint-tool, takes the above syntax and compiles it to GtkBuilder XML. So it’s not a replacement for GtkBuilder, but a higher-level language built on top of it. There aren’t any new features that the XML doesn’t have, just an easier way to use them.

It’s not ready to use yet; the syntax isn’t finalized, and there’s a lot of important features missing (menus, CSS classes, syntax highlighting, an easy way to use it in a project…) but if you want to try it out, I’d love to get some early feedback.

Other Approaches

This isn’t a new or original idea, and plenty of different ways of simplifying GtkBuilder have been proposed (see this discussion from March 2020). One idea was to keep using XML but simplify it to something more like HTML, where each XML element is an object and the tag names match the GObject class names. In fact, that’s how the original libglade worked. But that idea was rejected as not being well scalable to other libraries. Other ideas have been tried, like reusing GTK’s CSS parser, but that never went anywhere.

Ultimately, I decided on a completely custom language that compiles to the existing XML because I felt it would provide the most flexibility. And it turns out writing a simple parser from scratch isn’t all that hard–I wrote both the tokenizer and the parser in Python and it only took a couple days.

Future Plans

GTK 4 has a cool feature called GtkExpression that lets you bind any property to a powerful, reactive expression system. It’s very clunky in XML, but with a lot more work, I can imagine a very nice syntax in my new language:


@gtk "4.0";

@template MyWindow : ApplicationWindow {
  int file-size: 0;

  Gtk.Label {
    label: bind _("File size: %s", format_size (this.file-size));
  }
}

But before I implement advanced features like that, I need to finish all the other features, create syntax highlighting profiles, write documentation, finish the language server, and, of course, test it all. It’s a lot of work, but this is something I’ve wanted to do for a long time and I think it’ll be a really useful addition to the ecosystem when I’m done.


Next

Platforms, Compatibility, and the Future of the Free Desktop

If you’ve followed Linux (and particularly GNOME) development, you’ve probably heard the recent kind, well-meaning, respectful discussions about theming, extensions, customization, and the general direction of the Linux platform. Here’s my two cents as a GNOME developer.

Previous

Tutorial: Mobile App Development with GNOME Builder

In my previous post, I described Builder’s new support for mobile device development. Here I’ll explain how to set it up on your favorite mobile Linux device.