Building and testing GTK

… or: how GTK developers check their work on the toolkit.

Since GNOME’s collective move to GitLab, GTK has taken advantage of the features provided by that platform—especially when it comes to its continuous integration pipeline.

In days of old, the only way to check that our changes to the toolkit were correct was to wait until the Continuous build bot would notify us of any breakage on the main development branches. While this was better than nothing, it didn’t allow us to prevent breakage during the development phase of anything—from features to bug fixes, from documentation improvements to adding new tests.

These days, the CI pipeline available in GitLab is run on every branch and merge request, long before the changes reach the public development branches used by everybody else.

Topic branches and merge requests

When developing a topic branch against the GTK 4 main development one, we run a CI pipeline that starts with a simple coding style check for the changes applied in the branch. The style check uses clang-format, which is often good enough for the GTK coding style; the coding style has a few “special” caveats, and clang-format can raise false negatives and false positives. For that reason, the style check is allowed to fail, but contributors and reviewers are strongly encouraged to check the logs in case of failure.

Once the style check is passed, we run the build phase, which currently contains three separate jobs:

  • a Linux debug build, using a Fedora container
  • an MSYS2 build on Windows
  • a Linux release build

The Linux debug build is pretty standard fare.

The MSYS2 build catches any issue with a GNU toolchain on Windows.

The release build is necessary to ensure that we don’t rely on side effects of the debugging code we have in place during development.

All of these jobs run the GTK test suite.

We publish the tests reports both as a JUnit file, taking advantage of GitLab’s support; and as an HTML report, stored as a pipeline artifact. This makes it easier for us to check what failed and what succeeded.

Ideally, we want to add more environments:

  • Linux builds based on other mainstream distributions
  • a Windows build using the MSVC toolchain
  • a macOS build, once the GDK backend is fixed

After the build and testing jobs pass, we step into an analysis phase. We run the Clang static analysis tool on GTK’s code base and generate a report. In the near future we could also run sanitizer tools like UBSan and ASan; fuzzying tools for our parsers, like GtkBuilder and CSS; or tools that verify that our UI definitions contain the appropriate accessibility descriptors.

Just like the tests, we publish the analysis reports as GitLab artifacts for review.

Once the analysis phase is passed, we build the API references, and check the result so that newly added symbols are properly documented.

Finally, we have manual CI jobs to build Flatpak bundles for the GTK demo application; the widget factory; and the icon browser. This allows designers to immediately test changes in Adwaita, or newly added widgets, without necessarily building GTK from a scratch on their systems.

Mainline development branches

Once the CI pipeline for a topic branch/merge request passes, we can merge the changes into the main development branch with a certain level of confidence that the code is correct and does what we want.

The main development branch runs the same pipeline as previously described, except that the Flatpak jobs are not manual any more—thus is always possible to test locally the current bleeding edge of GTK. Additionally, the documentation is published online, so it’s always up to date.

The GTK CI pipeline

What about GTK 3?

In the GTK 3 branch we have a simpler pipeline that runs the following jobs:

  • a full Meson debug build on Linux and Windows/MSYS2, for both static and shared libraries artifacts, on the current stable versions of Fedora and Debian
  • a full Meson release build on Linux, which also generates the API reference
  • an Autotools build on Linux and Windows/MSYS2
  • an optional Autotools distcheck build on Linux

The Autotools jobs will be in place for as long as GTK 3 supports Autotools. Ideally, we want to add other jobs for macOS and Windows/MSVC, taking advantage of the Meson build.

The GTK3 CI pipeline

Once the GTK 4 CI pipeline reaches a certain level of features and stability, we’re going to backport it to GTK 3, so we can be even more confident that the current stable branch does not regress.


For more information, you can check the GTK repository:

GTK Hackfest 2020 — Roadmap and accessibility

Between January 28th and January 31st, the GTK team held what’s now the third hackfest in Brussels.

The main topics of the hackfest were:

  • the schedule for the next development snapshot of GTK4
  • the missing features blocking the release of GTK 4.0
  • the current state of the accessibility support in the toolkit

The first two items occupied the most of the first two days of the hackfest; you can read the GTK 3.98 release announcement for what we’ve been working on for the past 300 days since the 3.96 release. The missing features are:

  • Event controllers for keyboard shortcuts
  • Movable popovers on Wayland
  • Row-recycling list and grid views
  • Animation API

and all of them are being worked on in topic branches. The keyboard shortcuts branch has recently been rebased, and it’s in the process of being documented and cleaned up; the movable popovers is also being reviewed after a few iterations. The last two remaining branches are fairly sizeable, and will require some more iterations to get them right—with the animations API currently being mostly a prototype.

The final topic of the hackfest was the largest, and was a discussion long overdue.

GTK’s accessibility support was added as part of the GTK 2.0 release by the Sun Accessibility Team; it depends on the abstract data types provided by ATK (the Accessibility Tool Kit), which are then implemented concretely in GTK classes like GtkWidgetAccessible, or GtkEntryAccessible. Each widget has an “accessible” object associated to it, which is either automatically created by GTK, or can be provided by application code when subclassing a GTK widget. Non-widget types can also have accessible objects associated to them—the most notable case is the set of cell renderers for tree views and combo boxes. Underneath it all, sits AT-SPI, a protocol that is used by AT—Accessible Technologies, like a screen reader—to consume the data provided by applications. Typically, ATs will use a library like libatspi to deal with the protocol itself.

The main issues with the existing stack are:

  • there’s a lot of indirection caused by the existence of ATK; any new feature or bug fix needs to be defined inside ATK and then implemented into GTK and libatspi
  • ATK was written in a very different environment, and while it has seen a few deprecations, it shows its age in the assumptions it makes—like global coordinate spaces—and in its design
  • there’s a certain overlap between AT requirements and requirements for GUI testing that end up creating friction in the API design
  • the stack has fell in disrepair since the Sun accessibility team was disbanded; most of the ongoing work is still pretty much happening in the AT space (like Orca) and in web browsers
  • the entire stack was written when CORBA was a thing, and then ported to DBus in time for GNOME3; the protocol, though, is not really efficient and requires lots of roundtrips to move around small amounts of data, instead of having bulk operations and notifications

The last point is also the reason why we need a separate accessibility bus in order to avoid spamming the session bus, and making everything slower as soon as the accessibility support is enabled. A separate bus means that we need to poke an additional hole in any sandbox, and still lets everything that connects to the accessibility bus potentially snoop into what happens in every application.

Finally, GTK only supports accessibility on Linux; there is no support for macOS or Windows, which means applications written in GTK and ported to other platforms are not accessible to ATs there. As we expose ATK in our API, adding support for accessibility features on other platforms would require bridging ATK, creating further complexity.

As we want to redesign and update the accessibility features in GTK4, we need to understand what are the requirements for existing consumers of the accessibility stack, and what kind of use cases we need to target. For that, we asked Hypra, a company dedicated to the development of accessible solutions based on free and open source software, to help us.

Hypra developers are familiar with GNOME, and have been working on the Linux accessibility stack. Their clients cover a wide gamut of accessibility users, so they are in the best position to describe what kind of ATs are in actual use on a day to day basis.

There are a wide range of tools and functionality that have to be provided by different layers of the stack, from the toolkit to the compositor; application developers must also have access to the tools necessary to provide proper support to ATs, as they have a much better idea of what their applications should look and behave than the toolkit.

Over the course of two days we have identified a plan for moving forward:

  • drop ATK from the stack, and have GTK talk the AT-SPI protocol directly; this is similar to what Qt does from the toolkit side, and it makes it easier to both expand and verify eventual protocol changes
  • clean up the AT-SPI protocol itself, updating it where needed when it comes to using DBus more efficiently
  • drop the global accessibility bus, and have ATs negotiate a peer-to-peer connection to each application
  • make ATs ask the compositor to gather global state, like key shortcuts, instead of talking to applications that would then have to ask the windowing system—if that’s possible—or return invalid data when it isn’t
  • decouple GUI testing from accessibility
  • write widget and application authoring guides for application developers, and provide validation tools that can be used as part of the build and CI process to check if UI elements have the correct accessible description and links

There are more information available on the wiki for the notes and the roadmap, and we have already scheduled an additional check point meeting for this summer.

There’s a lot of work to be done, but we have now a much clearer idea of the scope and deliverables for such a redesign. If you want to help making things happen faster, feel free to join the effort; you can also make a donation to the GNOME Foundation.

The GTK team would like to thank the GNOME Foundation for the sponsorship for the venue and the attendees, and the fine folks at Hypra for joining the hackfest and explaining use cases and the current state of the accessibility stack, as well as helping out on the development side.

Constraint layouts

What are constraints

At its most basic, a constraint is a relation between two values. The relation
can be described as a linear equation:

target.attribute = source.attribute × multiplier + constant

For instance, this:

Can be described as:

blue.start = red.end × 1.0 + 8.0

Or:

  • the attribute, “start”, of the target, “blue”, which is going to be set by the constraint; this is the left hand side of the equation
  • the relation between the left and right hand sides of the equation, in this case equality; relations can also be greater than or equal to,
    and less than or equal to
  • the attribute, “end”, of the source, “red”, which is going to be read by the constraint; this is the right hand side of the equation
  • the multiplier, “1.0”, applied to the attribute of the source
  • the constant, “8.0”, an offset added to the attribute

A constraint layout is a series of equations like the one above, describing all the relationships between the various parts of your UI.

It’s important to note that the relation is not an assignment, but an equality (or an inequality): both sides of the equation will be solved in a way that satisfies the constraint; this means that the list of constraints can be rearranged; for instance, the example above can be rewritten as:

red.end = blue.start × 1.0 - 8.0

In general, for the sake of convenience and readability, you should arrange your constraints in reading order, from leading to trailing edge, from top to bottom. You should also favour whole numbers for multipliers, and positive numbers for constants.

Solving the layout

Systems of linear equations can have one solution, multiple solutions, or even no solution at all. Additionally, for performance reasons, you don’t really want to recompute all the solutions every time.

Back in 1998, the Cassowary algorithm for solving linear arithmetic constraints was published by Greg J. Badros and Alan Borning, alongside its implementation in C++, Smalltalk, and Java. The Cassowary algorithm tries to solve a system of linear equations by finding its optimal solution; additionally, it does so incrementally, which makes it very useful for user interfaces.

Over the past decade various platforms and toolkits started providing layout managers based on constraints, and most of them used the Cassowary algorithm. The first one was Apple’s AutoLayout, in 2011; in 2016, Google added a ConstraintLayout to the Android SDK.

In 2016, Endless implemented a constraint layout for GTK 3 in a library called Emeus. Starting from that work, GTK 4 now has a GtkConstraintLayout layout manager available for application and widget developers.

The machinery that implements the constraint solver is private to GTK, but the public API provides a layout manager that you can assign to your GtkWidget class, and an immutable GtkConstraint object that describes each constraint you wish to add to the layout, binding two widgets together.

Guiding the constraints

Constraints use widgets as sources and targets, but there are cases when you want to bind a widget attribute to a rectangular region that does not really draw anything on screen. You could add a dummy widget to the layout, and then set its opacity to 0 to avoid it being rendered, but that would add unnecessary overhead to the scene. Instead, GTK provides GtkConstraintGuide, and object whose only job is to contribute to the layout:

An example of the guide UI element

In the example above, only the widgets marked as “Child 1” and “Child 2” are going to be visible, while the guide is going to be an empty space.

Guides have a minimum, natural (or preferred), and maximum size. All of them are constraints, which means you can use guides not just as helpers for alignment, but also as flexible spaces in a layout that can grow and shrink.

Describing constraints in a layout

Constraints can be added programmatically, but like many things in GTK, they can also be described inside GtkBuilder UI files, for convenience. If you add a GtkConstraintLayout to your UI file, you can list the constraints and guides inside the special “<constraints>” element:

  <object class="GtkConstraintLayout">
    <constraints>
      <constraint target="button1" target-attribute="width"
                     relation="eq"
                     source="button2" source-attribute="width" />
      <constraint target="button2" target-attribute="start"
                     relation="eq"
                     source="button1" source-attribute="end"
                     constant="12" />
      <constraint target="button1" target-attribute="start"
                     relation="eq"
                     source="super" source-attribute="start"
                     constant="12" />
      <constraint target="button2" target-attribute="end"
                     relation="eq"
                     source="super" source-attribute="end"
                     constant="-12"/>
    </constraints>
  </object>

You can also describe a guide, using the “<guide>” custom element:

  <constraints>
    <guide min-width="100" max-width="500" />
  </constraints>

Visual Format Language

Aside from XML, constraints can also be described using a compact syntax called “Visual Format Language”. VFL descriptions are row and column oriented: you describe each row and column in the layout using a line that visually resembles the layout you’re implementing, for instance:

|-[findButton]-[findEntry(<=250)]-[findNext][findPrev]-|

Describes an horizontal layout where the findButton widget is separated from the leading edge of the layout manager by some default space, and followed by the same default amount of space; then by the findEntry widget, which is meant to be at most 250 pixels wide. After the findEntry widget we have some default space again, followed by two widgets, findNext and findPrev, flush one against the other; finally, these two widgets are separated from the trailing edge of the layout manager by the default amount of space.

Using the VFL notation, GtkConstraintLayout will create all the required constraints without necessarily having to describe them all manually.

It’s important to note that VFL cannot describe all possible constraints; in some cases you will need to create them using GtkConstraint’s API.

Limits of a constraint layout

Constraint layouts are immensely flexible because they can implement any layout policy. This flexibility comes at a cost:

  • your layout may have too many solutions, which makes it ambiguous and unstable; this can be problematic, especially if your layout is very complex
  • your layout may not have any solution. This is usually the case when you’re not using enough constraints; a rule of thumb is to use at least two constraints per target per dimension, since all widgets should have a defined position and size
  • the same layout can be described by different series of constraints; in some cases it’s virtually impossible to say which approach is better, which means you will have to experiment, especially when it comes to layouts that dynamically add or remove UI elements, or that allow user interactions like dragging UI elements around

Additionally, at larger scales, a local, ad hoc layout manager may very well be more performant than a constraint based one; if you have a list box that can grow to an unknown amount of rows you should not replace it with a constraint layout unless you measure the performance impact upfront.

Demos

Of course, since we added this new API, we also added a few demos to the GTK Demo application:

A constraints demo
The constraints demo window, as part of the GTK demo application.

As well as a full constraints editor demo:

The GTK constraints editor demo
A screenshot of the GTK constraints editor demo application, showing the list of UI elements, guides, and constraints in a side bar on the left, and the result on the right side of the window

More information

Layout managers in GTK 4

Containers and layout policies have been a staple of GTK’s design since the very beginning. If you wanted your widget to lay out its children according to a specific policy, you had to implement GtkContainer for handling the addition, removal, and iteration of the child widgets, and then you had to implement the size negotiation virtual functions from GtkWidget to measure, position, and size each child.

One of the major themes of the GTK 4 development cycle is to delegate more functionality to ancillary objects instead of encoding it into the base classes provided by GTK. For instance, we moved the event handling from signal handlers described by GtkWidget into event controllers, and rendering is delegated to GtkSnapshot objects. Another step in that direction is decoupling the layout mechanism from GtkWidget itself to an ancillary type, GtkLayoutManager.

Layout Managers

A layout manager is the object responsible for measuring and sizing a widget and its children. Each GtkWidget owns a GtkLayoutManager, and uses it in place of the measure() and allocate() virtual functions—which are going away. The gist of the change: instead of subclassing a GtkWidget to implement its layout policy, you subclass GtkLayoutManager, and then assign the layout manager to a widget.

Just like in the old GtkWidget code, you will need to override a virtual function to measure the layout, called measure(), which replaces the get_preferred_* family of virtual functions of GTK 3:

static void
layout_measure (GtkLayoutManager *layout_manager,
                GtkWidget        *widget,
                GtkOrientation    orientation,
                int               for_size,
                int              *minimum,
                int              *natural,
                int              *minimum_baseline,
                int              *natural_baseline)

After measuring, you need to assign the size to the layout; this happens in the allocate() virtual function, which replaces the venerable size_allocate() virtual function of previous GTK major versions:

static void
layout_allocate (GtkLayoutManager *layout_manager,
                 GtkWidget        *widget,
                 int               width,
                 int               height,
                 int               baseline)

On the more esoteric side, you can also override the get_request_mode() virtual function, which allows you to declare whether the layout manager requests a constant size, or if one of its sizes depend on the opposite one, like height-for-width or width-for-height:

static GtkSizeRequestMode
layout_get_request_mode (GtkLayoutManager *layout_manager,
                         GtkWidget        *widget)

As you may notice, each virtual function gets passed the layout manager instance, as well as the widget that is using the layout manager.

Of course, this has bigger implications on various aspects of how GTK widgets work, the most obvious being that all the complexity for the layout code can now stay confined into its own object, typically not derivable, whereas the widgets can stay derivable and become simpler.

Another feature of this work is that you can change layout managers at run time, if you want to change the layout policy of a container; you can also have a per-widget layout policy, without adding more complexity to the widget code.

Finally, layout managers allow us to get rid of one of the special cases of GTK, namely: container child properties.

Child properties

Deep in the guts of GtkContainer sits what’s essentially a copy of the GObject property-related code, and whose only job is to implement “child” properties for types deriving from GtkContainer. These container/child properties exist only as long as a child is parented to a specific class of container, and are used for a variety of reasons—but, generally, to control layout options, like the packing direction in boxes and box-like containers; the fixed positioning inside GtkFixed; or the expand/fill rules for notebook tab widgets.

Child properties are hard to use, as they require ad hoc API instead of the usual GObject one, and thus require special casing in GtkBuilder, gtk-doc, and language bindings. Child properties are also attached to the actual direct child of the container, so if a widget interposes a child—like, say, GtkScrolledWindow or GtkListBox do—then you need to keep a reference to that child around in order to change the layout that applies to your own widget.

In GTK’s master branch we got rid of most of them—either by simply removing them when there’s actual widget API that implements the same functionality, or by creating ancillary GObject types and moving child properties to those types. The end goal is to remove all of them, and the relative API from GtkContainer, by the time GTK 4 rolls out. For layout-related properties, GtkLayoutManager provides its own API so that objects are created and destroyed automatically once a child is added to, or removed from, a widget using a layout manager, respectively. The object created is introspectable, and does not require special casing when it comes to documentation or bindings.

You start from deriving your own type from the GtkLayoutChild class, and adding properties just like you would for any other GObject type. Then, you override GtkLayoutManager‘s create_layout_child() virtual function:

static GtkLayoutChild *
create_layout_child (GtkLayoutManager *manager,
                     GtkWidget *container,
                     GtkWidget *child)
{
  // The simplest implementation
  return g_object_new (your_layout_child_get_type (),
                       "layout-manager", manager,
                       "child-widget", child,
                       "some-property", some_property_initial_state,
                       NULL);
}

After that, you can access your layout child object as long as a widget is still a child of the container using the layout manager; if the child is removed from its parent, or the container changes the layout manager, the layout child is automatically collected.

New layout managers

Of course, just having the GtkLayoutManager class in GTK would not do us any good. GTK 4 introduces various layout managers for application and widget developers:

  • GtkBinLayout implements the layout policy of GtkBin, with the added twist that it supports multiple children stacked on top of each other, similarly to how GtkOverlay works. You can use each widget’s alignment and expansion properties to control their location within the allocated area, and the GtkBinLayout will always ask for as much space as it’s needed to allocate its largest child.
  • GtkBoxLayout is a straight port of the layout policy implemented by GtkBox; GtkBox itself has been ported to use GtkBoxLayout internally.
  • GtkFixedLayout is a port of the fixed layout positioning policy of GtkFixed and GtkLayout, with the added functionality of letting you define a generic transformation, instead of a pure 2D translation for each child; GtkFixed has been modified to use GtkFixedLayout and use a 2D translation—and GtkLayout has been merged into GtkFixed, as its only distinguishing feature was the implementation of the GtkScrollable interface.
  • GtkCustomLayout is a convenience layout manager that takes functions that used to be GtkWidget virtual function overrides, and it’s mostly meant to be a bridge while porting existing widgets towards the layout manager future.

We are still in the process of implementing GtkGridLayout and make GtkGrid use it internally, following the same pattern as GtkBoxLayout and GtkBox. Other widgets inside GTK will get their own layout managers along the way, but in the meantime they can use GtkCustomLayout.

The final step is to implement a constraint-based layout manager, which would let us create complex, responsive user interfaces without resorting to packing widgets into nested hierarchies. Constraint-based layouts deserve their own blog post, so stay tuned!

Testing Discourse for GTK

For the past 20 years or so, GTK used IRC and mailing lists for discussions related to the project. Over the years, use of email for communication has declined, and the overhead of maintaining the infrastructure has increased; sending email to hundreds or thousands of people has become increasingly indistinguishable from spam, in the eyes of service providers, and GNOME had to try and ask for exceptions—which are not easy to get, and are quite easy to be revoked. On top of that, the infrastructure in use for managing mailing lists is quite old and crumbly, and it’s unnecessarily split into various sub-categories that make following discussions harder than necessary.

After discussions among the GTK team, with the GNOME infrastructure maintainers, and with the GTK community at large, we decided to start a trial run of Discourse as a replacement for mailing lists, first and foremost, and as a way to provide an official location for the GTK community to discuss the development of, and with, GTK—as well as the rest of the core GNOME platform: GLib, Pango, GdkPixbuf, etc.

You can find the Discourse instance on discourse.gnome.org. On it, you can use the Platform and Core categories for discussions about the core GNOME platform; you can use the appropriate tags for your topics, and subscribe to the ones you’re interested in.

We’re planning to move some of the pages on the wiki to Discourse as well, especially the ones where we expect feedback from the community.

We’re still working on how to migrate users of the various mailing lists related to GTK, in order to close the lists and have a single venue instead of splitting the community; in the meantime, if you’re subscribed to one or more of these lists:

  • gtk-devel-list
  • gtk-app-devel-list
  • gtk-list
  • gtk-i18n-list

then you may want to have a look at Discourse, and join the discussions there.

Report from the GTK hackfest in Brussels

Thanks to the GNOME Foundation, various GTK developers were able to meet in Brussels right after FOSDEM, for one of our yearly hackfests.

The main topics of the hackfest were:

  • recap the work that landed into the master branch in the past 6-12 months, in order to have everyone on the same page
  • discuss the features still in flight in separate branches, assess their state of completion, and identify blockers
  • figure out what are the blockers for the first release of GTK 4.0

Hackfests allow us to have this kind of discussions with a large bandwidth at our disposal, compared to online communication channels, so they are very important for the project.

You can see the full agenda on the wiki, and we’ll make sure to write articles on the biggest items on it.

The largest items of the discussion were the introduction of new list models and list/grid view widgets; a unified key handling API; the decoupling of layout management policies from containers, and the introduction of constraint layout management; the possibility of merging widgets from libhandy, to allow for writing applications responsive to form factor changes; the switch to a purely declarative menu description API, and the removal of public menu widgets; adding 2D and 3D transformations to GtkWidget; implementing an animation API that applications can consume.

  • list models and list/grid widgets — we’d really like to retire GtkTreeView and GtkIconView, but the existing replacements, GtkListBox and GtkFlowBox, are not performant enough when scaling to very large and dynamic data sets. We need better data storage types, that can be composed to perform operations such as mapping, filtering, and sorting, but can also avoid iterating over all the elements when sizing and drawing widgets. Benjamin Otte already added various models to GTK, and is working on a list and a grid view widgets that can efficiently display their contents. Benjamin and other GNOME application developers are in the process of identifying various stakeholders for  a separate hackfest specifically for gathering more requirements and getting feedback on the new API.
  • unified key handling API — now that we moved all our pointer and touch input handling away from events and towards gestures, we want to do the same for key handling, like key bindings, mnemonics, and accelerators. The overall design is based on triggering actions, and allow introspection of all the “shortcuts” currently available to the GTK inspector, for ease of debugging. There is a development branch already available.
  • layout managers — in GTK 3, layout is imposed by containers on their children; we want to be able to decouple that from widgets and move it into a separate delegate objects hierarchy. Layout managers allow us to reduce the complexity of writing new widgets; they keep the layout code in a separate, non-derivable type; and they allow us to simplify the toolkit internals to the point that we might even make GtkWidget and instantiable type in the future. Layout managers are the first step towards adding constraint-based layout management to GTK, which do away with nesting boxes to create complex UIs. There is a development branch already available. For more information on constraint layouts, you can see the Emeus experimental library for GTK 3.
  • merging widgets from libhandy — Adrien Plazas gave an overview of what’s currently provided by libhandy, and what would be useful to have straight from GTK4 in the future. We discussed reactive layouts, and the ability express sizing with percentages, as well as possibly using constraints to get similar results.
  • declarative menus — GTK has iterated over different menus API over the years; from building menus out of widgets, to GtkUIManager, to GtkBuilder, to GMenu; we also moved to declaring the behaviour of pop up menus, in order to have the windowing system display them more accurately without exposing global coordinates. There’s a lot of overlap, but no clear winner, mostly because we still allow using widgets to build application menus and context menus. Fully switching to declarative style menus, adding new API to make them more expressive, and making GtkMenu and friends private implementations for the toolkit, would allow us to get things like being able to inspect all menus, even out of process; menus manipulable by plugin systems without necessarily creating widgets and keeping track of them; avoiding positioning bugs. There is a full strawman proposal available on the wiki, and Matthias Clasen is working on switching context menus to GMenu in a development branch.
  • widget transformations — Sadly, Timm Bädert couldn’t make it to the hackfest, but we’ve been reviewing his development branch that adds 2D and 3D transformations to GTK widgets, and we’re very excited about it.
  • animations — one last thing we’d like to land for GTK4 is an animation framework for GTK widgets to replace the current generic “frame tick callback”. The model for it is the Clutter explicit animation API, which in turn was based on Core Animation and CSS3 transitions. This work is still in the design phase, but you can expect development branches for it to land soon.

Aside from the big topics, we also discussed various smaller ones:

  • improving performance and memory use; we want to expose the SysProf counters during the frame clock phases, so we can easily identify problems.
  • improving the test suite, especially when it comes to reporting failures; right now, we have to go through the CI failure log, but we’d like to publish proper reports using the GitLab CI infrastructure
  • replacing child properties with real GObject properties on ancillary objects, especially for layout managers; would make documentation, introspection, and usage clearer.
  • finishing the drag and drop rework, to get a more modern API.
  • adding a top-level interface for “window-like” objects—such as windows, dialogs, popovers, menus/popups—useful for establishing common behaviour, and removing hacks and complexity in GtkWindow.

And, finally, yes: we did remove the “plus” from GTK. ;-)

News from GLib 2.58

Next September, GLib will hit version 2.58. There have been a few changes during the past two development cycles, most notably the improvement of the Meson build, which in turn led to an improved portability of GLib to platforms such as Windows, macOS, and Android. It is time to take stock of the current status of GLib, and to highlight some of the changes that will impact GLib-based code.

  • Meson – Thanks to the ongoing work of Nirbheek Chauhan and Xavier Claessens, the Meson build has been constantly improving, to the point that we can start switching to it as the default build system. The plan—as outlined on the mailing list—is to release GLib 2.58 using Meson, while keeping the Autotools build in tree and available in the release archive; then, we’ll drop the Autotools build during the following development cycle, and release GLib 2.60 without Autotools support. Linux distributors are very much welcome to start testing the Meson build in their builders; we’ve been running the Meson build as part of our CI process for a while, now, but more exposure will bring out eventual regressions that we missed; additionally, it would be stellar if people with different toolchains than GCC/Clang/MSVC would start trying the Meson build and report bugs. In the meantime, if you’re using GLib on macOS and Windows, we already recommend you switch to Meson to build GLib, as it’s easier and better integrated with those platforms than Autotools
  • Reliability and portability – GLib switched to GitLab alongside the rest of GNOME, which meant being able to run continuous integration outside of the GNOME Continuous builds. Now we run CI on multiple toolchains, multiple build systems, and multiple platforms for every commit and merge request, which significantly reduces the chances of a broken build. We’ve also improved the code coverage in the test suite. Of course, we could always do better; for instance, we don’t have a CI runner for macOS and the Solaris family of OSes, and more runners for the *BSD family would be greatly appreciated. We’ve issued a call for help, if you have a spare machine and some bandwidth that you can donate
  • File monitoring on *BSD – Apropos the *BSD family, the kqueue backend for file monitoring in GIO has been completely overhauled by Martin Pieuchot and Ting-Wei Lan; the new code is simpler, more robust, and passes all the tests
  • Use posix_spawn() for efficient process launching — Thanks to Daniel Drake, GLib now can use posix_spawn() under specific circumstances, if the platform’s C library supports it; this allows hitting fast paths in the kernel, compared to manually calling fork() + exec(); those fast paths are especially beneficial when running on memory constrained platforms
  • Reference counting types and allocations — GLib uses reference counting as a memory management and garbage collection mechanism in many of its types, but lacks the public API to allow other people to implement the same semantics in their own data structures; this leads to much copy-pasting and re-implementations, and typically to things like undefined behavior when it comes to saturation and thread safety. GLib 2.58 has a grefcount and a gatomicrefcount types, alongside their API, to reduce this duplication. Additionally, taking a cue from other languages like Rust, GLib provides a way to add reference counting semantics on memory allocations, by adding a low level API that allows you to allocate structures that do not have a reference count field, and automatically add reference counting semantics to them
  • Deprecations – A few soft deprecations have become real deprecations in this last development cycle:
      • g_type_class_add_private() has finally been deprecated, five years after we introduced the instance private data macros; if you’re still using that function in your class initialization, please switch to G_DEFINE_TYPE_WITH_PRIVATE or G_ADD_PRIVATE
      • g_main_context_wait() is officially deprecated, but you should have already seen run time warnings about its use
      • gtester, the GTest harness provided by GLib, is deprecated; if you’re using Autotools, you should use the TAP harness that comes with Automake

There have been lots of contributions in GLib, in this past cycle, thanks to the tireless efforts of Philip Withnall; he’s been instrumental in reviewing patches, triaging bugs, and implementing changes in the development process of the project. The switch over to GitLab has also improved the contribution process, with many more developers opening merge requests:

  • 2.54.0..c182cd68: 968 changesets from 143 developers, up from 412 changesets and 68 developers during the 2.53 development cycle
  • A total of 31851 lines added, 27976 removed (delta: +3875)
Developers with the most changesets
Philip Withnall 303 31.3%
Xavier Claessens 79 8.2%
Emmanuele Bassi 69 7.1%
Christoph Reiter 42 4.3%
Ting-Wei Lan 21 2.2%
Chun-wei Fan 21 2.2%
Nirbheek Chauhan 21 2.2%
Ondrej Holy 20 2.1%
Руслан Ижбулатов 20 2.1%
Mikhail Zabaluev 20 2.1%
Simon McVittie 15 1.5%
Matthias Clasen 14 1.4%
Christian Hergert 13 1.3%
Iñigo Martínez 12 1.2%
Bastien Nocera 10 1.0%
Rafal Luzynski 9 0.9%
Michael Catanzaro 9 0.9%
Will Thompson 8 0.8%
Allison Lortie 8 0.8%
Daniel Boles 8 0.8%

Make sure to test your code with GLib 2.57.2, the next development snapshot towards the 2.58.0 stable release.

This week in GTK+ – 36

In this last week, the master branch of GTK+ has seen 22 commits, with 1165 lines added and 904 lines removed.

Planning and status
Notable changes

On the master branch:

  • Robert Ancell updated the icon browser utility to improve the error messages when loading an icon failed
  • Matthias Clasen improve the newly added GtkCenterBox widget; you can follow along his work in the “Container Secrets” series of articles
Bugs fixed
  • 783552 – Translation interpretation
  • 759308 – Instant apply in printing dialog (number of copies)
  • 783445 – Incomplete documentation of gtk_widget_insert_after/before()
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 35

In this last week, the master branch of GTK+ has seen 33 commits, with 5011 lines added and 8140 lines removed.

Planning and status
  • The GTK+ road map is available on the wiki
  • Patrick Griffis is experimenting with a feature branch to deprecate and remove gtk_dialog_run(); see this comment on the pitfalls of nested main loops with regards to UI threads, IPC threads, and I/O threads
  • Matthias Clasen is experimenting with re-using the fuzzy search in libdazzle in the icon browser
Notable changes

On the master branch:

  • Matthias Clasen added the ability to copy the icon name to the clipboard to the icon browser utility
  • Matthias also made the GtkCenterBox widget public; this widget replaces the equivalent functionality of GtkBox to have a centered widget
  • Olivier Fourdan fixed various bugs in the Wayland backend, and backported the fixes to the gtk-3-22 stable branch
  • Chun-wei Fan pushed various fixes to ensure that GTK+ keeps building with MSVC on Windows
  • Emmanuele Bassi modified the Meson build to ensure that all the SASS-based themes are regenerated when building GTK+, if sassc is installed; Lapo Calamandrei removed the Gem file for Ruby/Sass, and thus GTK+ switched to sassc as the preferred SASS compiler
Bugs fixed
  • 770513 – MainToolbar in full-screen mode has rounded corners, which show video pixel bleed-thru underneath it
  • 783347 – gtkfilechoosernativewin32: Fix support for non-ASCII paths
  • 781945 – SIGSEGV dragging window on Wayland when toplevel window set_transient_for is set to another toplevel
  • 782283 – Wayland: Crash when dismissing a menu when a tooltip is visible
  • 781285 – Key repeat cancel under Wayland should depend on which key is repeating
  • 783397 – Remove unused code in gtktextdisplay.c
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 34

After quite a long break around the GNOME 3.24 release, we’re finally back. Sorry for the wait!

In this last week, the master branch of GTK+ has seen 103 commits, with 2355 lines added and 5482 lines removed.

Planning and status
  • The GTK+ road map is available on the wiki.
  • Matthias Clasen released GTK+ 3.91.0, the first snapshot of the development cycle that will lead to the 3.92 release. This is still part of the development cycle towards the API stable 4.0.
  • Timm Bäder is working on his drawing branch which aims to replace all the internal uses of CSS gadgets with real widgets. See this article on this blog for more information.
Notable changes

On the master branch:

  • Carlos Garnacho merged his event-delivery branch, which moves the event handling from the GDK window hierarchy to the GTK widget one; this is the first step towards the removal of all GdkWindow instances outside of the top level one, and which will ultimately lead to improved input handling.
Bugs fixed
  • 745289 – wayland: do not use g_error() on connection errors
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.