Casilda 1.0 released!

Version 1.0!

I am pleased to announce the release of Casilda version 1.0, a simple Wayland compositor widget for GTK 4 which can be used to embed other processes windows in your application.

This version includes lots of rendering improvements and optimizations together with new features and a simple API.

Etymology

Following Wayland tradition, this library is named after my hometown in Santa Fe, Argentina.

Why?

When I started working on Cambalache (a new GUI designer for GTK) one of the main design goals was to create all the preview widgets in a separate process to be able to support GTK 3 and 4 projects and avoid any situation that could take down the whole application.This requires a way to embed another process windows in a GtkWindow, initially I decided to use Broadway backend and a WebView as a stopgap measure until Cambalache was mature enough to justify investing time in making a proper Wayland compositor widget.

wlroots

After a couple of years the WebView approach started to show its limitations, so it was time to give the original idea of creating a Wayland compositor widget a try.

Thankfully, the wlroots library makes it relatively easy, especially with the help of it’s community!

You can read more about the first release of the compositor widget in the following post.

New Cambalache development release 0.91.1!

In a nutshell, Casilda utilizes wlroots to handle most of the wayland protocol, including the creation of virtual input and output devices.

It creates a wayland keyboard and pointer devices which then events are feed from a few GtkEventController in the Compositor widget.

It also creates an output device the same size as the widget allocation, which means each time the compositor widget size changes, wayland clients get a output resolution change event.

Native Rendering

Originally Casilda relied on wlroots to render the whole scene, get a pixel buffer and upload it to a cairo surface to render it in GTK. This worked, but was not optimal, for a number of reasons:

    • Shared memory buffers – Clients had to render in software mode
    • Extra copy to upload wlroots buffer to GTK for rendering

Luckily @valpackett decided to step in and added support for dmabufs which allows clients to use OpenGL or Vulkan to render.

Based on this work, I decided that it would be nice to go one step further and create a GdkTexture from each client window dmabuf and use it directly in the GTK scene graph.

This cuts all the middle men and extra copies/uploads and makes client windows directly accessible to render them in GtkWidget::snapshot()Here you can see the graphics updates of the compositor and how thanks to damage regions we do not need to update the parts that did not change.

Rendering natively adds some complexity but also gives us more flexibility. For example, I was able to easily tint the parent for transient windows.This is the actual code that tints the parent window, a simple color matrix transformation that gets converted somewhere in the rendering pipeline into a simple pixel shader.

  if (has_transient)
    {
      graphene_matrix_t matrix;
      graphene_vec4_t offset;
 
      graphene_matrix_init_from_float (&matrix,
                                       (float[16]) {
                                                     0.8, 0, 0, 0,
                                                     0, 0.8, 0, 0,
                                                     0, 0, 0.8, 0,
                                                     0, 0, 0, 1
                                                   });
 
      graphene_vec4_init (&offset, 0, 0, 0, 0);
      gtk_snapshot_push_color_matrix (data->snapshot, &matrix, &offset);
    }

Scrollable interface

CasildaCompositor now implements GtkScrollable interface, by default it does not have any adjustments set, but if you pack it inside a GtkScrolledWindow it will extend the size of the virtual output depending on the size and position of every client window.Currently it only expands the virtual output when you move a window over the left or bottom edge.

API – How to use it?

Casilda uses gi-docgen to generate it’s API reference documentation and it is available online here.

To embed another process window in your GTK 4 application all you have to do is create a CasildaCompositor widget and add it in the hierarchy just like any other widget.

You can specify which UNIX socket the compositor will listen on for client connections or use casilda_compositor_get_client_socket_fd() to get an already connected socket to the compositor.

compositor = casilda_compositor_new ("/tmp/casilda-example.sock");
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (compositor));

Once the compositor is running you can connect to it by specifying the socket in the WAYLAND_DISPLAY environment variable.

export GDK_BACKEND=wayland
export WAYLAND_DISPLAY=/tmp/casilda-example.sock
gtk4-demo

If you do not want any client being able to connect to the compositor you can pass NULL as socket and spawn the client with casilda_compositor_spawn_async() or get an already connected socket with casilda_compositor_get_client_socket_fd() and pass it to the client with the WAYLAND_SOCKET environment variable.

compositor = casilda_compositor_new (NULL);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (compositor));
gtk_window_present (GTK_WINDOW (window));
 
gchar *argv[] = { "/usr/bin/gtk4-demo", NULL };
casilda_compositor_spawn_async (
    compositor, NULL, argv, NULL,
    G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL
);

Language Bindings

Casilda uses GObject introspection to enable bindings for other languages.

This is a full example in Python

#!/usr/bin/python3
 
import gi
import sys
 
gi.require_version("Gtk", "4.0")
gi.require_version("Casilda", "1.0")
from gi.repository import GLib, Gtk, Casilda
 
 
class CasildaApplication(Gtk.Application):
    def __init__(self):
        super().__init__(application_id="ar.xjuan.casilda.PyGObject.Example")
 
    def do_activate(self):
        compositor = Casilda.Compositor()
 
        window = Gtk.ApplicationWindow(
            application=self,
            title="Casilda Compositor",
            default_width=800,
            default_height=600,
            child=compositor
        )
 
        compositor.spawn_async (
            None,
            ["/usr/bin/gtk4-demo"],
            None,
            GLib.SpawnFlags.DEFAULT
        )
 
        window.present()
 
 
if __name__ == "__main__":
    app = CasildaApplication()
    sys.exit(app.run(sys.argv))

and in JavaScript

#!/usr/bin/gjs -m
 
import System from 'system';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=4.0';
import Casilda from 'gi://Casilda?version=1.0';
 
 
let CasildaApplication = GObject.registerClass({},
    class CasildaApplication extends Gtk.Application {
    constructor() {
        super({
            application_id: 'ar.xjuan.casilda.Gjs.Example'
        });
    }
 
    vfunc_activate() {
        let compositor = new Casilda.Compositor();
 
        let window = new Gtk.ApplicationWindow({
            application: this,
            title: 'Casilda Compositor',
            default_width: 800,
            default_height: 600,
            child: compositor
        });
 
        window.connect('close-request', () => {
            this.quit();
        });
 
        compositor.spawn_async (
            null,
            ["/usr/bin/gtk4-demo"],
            null,
            GLib.SpawnFlags.DEFAULT,
            null
        );
 
        window.present();
    }
});
 
let app = new CasildaApplication();
app.run([System.programInvocationName].concat(ARGV));

This pretty much covers Cambalache use case and the old XEmbed protocol used by GtkSocket/GtkPlug widget classes.

All you need to do is put the widgets you want to embed in a full screen window and launch the process with spawn_async() .

The compositor will take care of the rest, including resizing the fullscreen window when the compositor size changes.

What’s next?

Besides bugfixes future releases will focus on upgrading to new wlroots releases and improving current features like keyboard layout support, touch devices, etc.

Where to get it?

Source code lives on GNOME gitlab here

git clone https://gitlab.gnome.org/jpu/casilda.git

Matrix channel

Have any question? come chat with us at #cambalache:gnome.org

Mastodon

Follow me in Mastodon @xjuan to get news related to Casilda and Cambalache development.

Happy coding!

An accessibility update

I recently saw somebody ask

Is Fedora accessible now ?

To which I want to say: yes! But this question does not really have a  simple yes-or-no answer. There is lots of nuance to it. A better question would be:

Is this system usable for *me* ?

Accessibility is about making our software usable (and, ideally, pleasant to use) for as many people as we can.

It has been a year since we last gave an update on accessibility (a11y) in and around GTK. Time to look at what has happened in this space since then. On the surface, it might seem that the answer is: not much. But lets look a bit closer.

A new backend

We merged the AccessKit a11y backend in GTK 4.18. This is pretty big news for GTK on platforms other than Linux. For the very first time, GTK applications can be accessible on Windows and macOS. This is also the first rust dependency in GTK.

If you want to try it out, build GTK with the -Daccesskit=enabled build option, and set

GTK_A11Y=accesskit

in the environment. The AccessKit backend works on Linux as well, but we are still defaulting to at-spi here. If you are ever uncertain which a11y backend GTK is using, you can find this information in the inspector.

The new backend was created by Matt Campbell as part the STF initiative.

Keyboard shortcuts in orca

One of the remaining gaps in the Wayland a11y support was the lack of support for the special keyboard shortcuts that are traditionally provided by the orca screen reader.

Another result of the STF initiative was a prototype for a new a11y protocol, including support for these shortcuts, but it was not complete and unmerged.

Thankfully, Lukáš Tyrychtr and Carlos Garnacho cooperated on extracting the relevant parts and completed the shortcuts support. This closes one of the biggest remaining “Wayland accessibility” gaps in  GNOME 48.

An accessible web browser

Georges Basile Stavracas Neto put a lot of effort into making webkitgtk accessible, in particular when it is used in a flatpak sandbox. You can watch his GUADEC talk from last year to learn all about the complexities of this task. But he succeeded, so GNOME Web is now a fully accessible, fully sandboxed web browser.

This was work was also supported by the STF initiative.

A new accessibility tool

Elevado is a new tool to let you browse and explore what apps expose on the a11y bus. The existing tool for this, accerciser, has not been in active development for a long time, so it is good to have an alternative.

The new tool just got ported to rust, so its cool. And it just saw its first release. Try it out!

Elevado was started by Georges to help with his work on a11y in webkitgtk.

The long tail

Beyond these big headline features, there have been many smaller improvements to a11y in GTK and related libraries:

  • A number of missing accessible labels, tooltips and key bindings have been added in the file chooser
  • List boxes now provide information to make orca say the right thing
  • The a11y overlay in the GTK inspector will now show you when your buttons are too small as click targets
  • ATs can receive notification about platform state (such as focus) changes, and custom accessible implementations can emit such notifications
  • We now provide information about shortcuts and mnemonics for actions in the form that orca expects
  • Reporting of text attributes has been improved (a contribution from the LibreOffice team)
  • libadwaita toast notifications are now announced to AT
  • The accessible representation of many libadwaita action row widgets has been improved

Summary

Accessibility in GNOME is continuously improving, thanks to the contributions of many people. Thanks to everybody who helps! ❤️

What’s new in GTK, winter 2025 edition

We just had a GTK hackfest at FOSDEM. A good time for an update on whats new and exciting in GTK, with an eye towards 4.18.

GTK hackfest 2025Requirements

You can no longer call gdk_display_get_default() or gdk_display_open() before gtk_init(). This was causing problems due to incomplete initialization, so we made it fail with a (hopefully clear) error message. If you are affected by this, the usual fix is to just call gtk_init() as early as possible.

On Windows, we have a hard requirement on Windows 10 now. All older versions are long unsupported, and having to deal with a maze of ifdefs and unavailable APIs makes development harder than it should be. Dropping support for very old versions also simplifies the code down the stack, in Pango and GLib.

The same idea applies to macOS, where we now require macOS 10.15.

Spring cleaning

The old GL renderer has been removed. This may be unwelcome news for people stuck on very old drivers and hardware. But we will continue to make the new renderers work as well as possible on the hardware that they can support.

The X11 and Broadway backends have been deprecated, as a clear signal that we intend to remove them in the GTK 5. In the meantime, they continue to be available. We have also deprecated GtkShortcutsWindow, since it needs a new design. The replacement will appear in libadwaita, hopefully next cycle.

It is worth reminding everybody that there is no need to act on deprecations until you are actively porting your app to the next major version of GTK, which is not on the horizon yet.

Incremental improvements

Widget layout and size allocation has received quite a bit of attention this cycle, with the goal of improving performance (by avoiding binary search as much as possible) and correctness. Nevertheless, these changes have some potential for breakage, so if you see wrong or suboptimal layouts in applications, please let us know.

GTK has had difficulties for a while getting its pointer sizes right with fractional scaling on Wayland, but this should all be solved in GTK 4.18. No more huge pointers. Fixing this also required changes on the mutter side.

New beginnings

Accessibility in GTK 4.18 is taking a major step forward, with the new AccessKit backend, which gives us accessibility on  Windows and macOS, for the very first time. The at-spi backend is still the default on Linux, and has seen a number of improvements as well.

And, maybe the biggest news: We have an Android backend now. It is still experimental, so you should expect some rough edges and loose ends. For example, there is no GL renderer support yet. But it is exciting that you can just try gtk4-demo on your phone now, and have it mostly work.

Enjoy!