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!

GTK+ 3.0 Released

GTK+ 3.0 is a major new version of GTK+, containing far too many changes to list them all here.

The major highlights include:

  • Cairo drawing throughout. GDK no longer wraps the antiquated X11 drawing API; we’ve made a clean break and exclusively rely on cairo for all our drawing needs now. This has also enabled us to remove several other X11-centric concepts such as GCs, colormaps and pixmaps.
  • Modern input device handling. The input device handling in GDK has long been a sadly neglected area. This has changed; with 3.0, GTK+ steps into the modern world of XI2 with full support for multiple pointers, keyboards and other gizmos.
  • A new theming API which sports a familiar CSS syntax for theme configuration and other improvements such as animated state transitions.
  • More flexible geometry management, with support for height-for-width, for both widgets and cell renderers.
  • Multiple backend support for GDK. With GTK+ 2.x, you had to recompile your application to have it work with a different GDK backend. In GTK+ 3, multiple GDK backends can be built into a single library and selected at runtime.
  • Easy application support. With the integration of D-Bus support in GIO, we could finally add a GtkApplication class that handles a lot of the platform integration aspects of writing an application, such as keeping track of open Windows, ensuring uniqueness, exporting actions, etc.
  • Of course, there’s some new widgets as well, such as a switch and an application chooser.

GTK+ is the work of hundreds of contributors, far too many to list them all here. But I want to take the time to thank some people who contributed in a major way:

  • Carlos Garnacho (Lanedo), for his work on XI2 support and the new theme system
  • Benjamin Otte (Red Hat), for his work on GDK and cairo drawing
  • Tristan Van Berkom (Openismus), for his work on geometry management
  • Colin Walters (Red Hat), for his work on GtkApplication
  • Ryan Lortie (Codethink), for his work on dconf, GSettings and GtkApplication
  • Javier Jardón, for tireless code, build and documentation cleanup

GTK+ 2.18 stable release

GTK+ 2.18 adds new functionality while maintaining source and binary compatibility with GTK+ 2.16. Highlights of new features and improvements in GTK+ 2.18 are:

GtkInfoBar
A new widget to show a transient ‘message area’ inside a content pane. The API is similar to GtkDialog and supports theming for different message types (warnings, errors, etc)

GtkBuilder

  • Scale marks can be specified in builder markup
  • GtkAssistant action widgets can be added in builder markup

GtkLabel
GtkLabel can show embedded URLs, much like SexyUrlLabe

GtkEntry
GtkEntry has been refactored to follow the model-view pattern, with GtkEntryBuffer as model. One intended use case for this is to support ‘secure memory’ for password entries

File chooser

  • Backup files are hidden by default
  • GTK+ remembers the sorting state of the file list
  • File sizes are shown by default
  • The ‘Create Folder’ button can be disabled with the the ::create-folders property

Printing support

  • GTK+ supports authentication against CUPS servers
  • A backend for the PAPI printing system has been added
  • The file and lpr backends can print multiple pages per sheet
  • The file backend can produce svg files
  • GTK+ supports printing an application-defined ‘selection’ in addition to the usual page ranges
  • The print dialog can optinally include the page setup controls, avoiding the need for a separate page setup dialog in many situations

Theming support

  • The bullet character used in invisible entries can be set by themes with the ::invisible-char style property
  • The file chooser can show different icons for xdg user dirs. The icon names are folder-documents, folder-download, folder-music, folder-pictures, folder-publicshare, folder-templates and folder-video
  • The GtkInfoBar uses symbolic colors for theming its background color depending on the message type. The color names are info_fg_color, info_bg_color, warning_fg_color”, warning_bg_color, etc.

GDK changes
GDK has been rewritten to use ‘client-side windows’. This means that GDK maintains its own window hierarchy and only uses X windows where it is necessary or explicitly requested. Some of the benefits of this change are

  • Reduced flicker
  • The ability to do transformed and animated rendering of widgets
  • Easier embedding of GTK+ widgets, e.g. into Clutter scene graphs
  • See gdk-demo for some simple examples of client-side windows in action. See the documentation for information about possible problems when moving to client-side windows.

For more details and lists of fixed bugs, see the
announcements for the 2.17.x development releases: 2.17.0, 2.17.1, 2.17.2, 2.17.3, 2.17.4, 2.17.5, 2.17.6, 2.17.8, 2.17.9, 2.17.10, 2.17.11

GLib 2.22 Stable Release

GLib 2.22 is a stable release adding an incremental improvement in functionality over GLib 2.20 while maintaining binary and source compatibility.

Major new features include:

  • GArray, GPtrArray, GByteArray, GTree and GMappedFile can be reference counted.
  • GLib can be forced to reload the XDG user directory mapping.
  • The GLib mainloop supports per-thread default contexts.
  • GIO now provides types and methods for IP addresses and UNIX domain socket addresses.
  • GResolver provides asynchronous and cancellable APIs for resolving hostnames, reverse lookup of IP addresses and resolving SRV records.
  • Support for network IO has been added to GIO, including low-level socket API and high-level API for network connections and services.
  • GIOStream and its subclasses have gained support for read-write access.
  • GIO supports starting and stopping of drives, which can be used in connection with external hard disk enclosures, disk arrays, iSCSI devices, etc.
  • GIO supports user interaction during unmount and eject operations.
  • GIO can store and retrieve per-file metadata.

For more details and lists of fixed bugs, see the announcements of the 2.21.x development releases: 2.21.0, 2.21.1, 2.21.2, 2.21.3, 2.21.4, 2.21.5 and 2.21.6

GTK+ 2.16.0 stable release

GTK+ 2.16 adds new functionality while maintaining source and binary compatibility with GTK+ 2.14. Highlights of new features and improvements in GTK+ 2.16 are:

Noteworthy new APIs

  • GtkOrientable is a new interface implemented by all widgets that have horizontal and vertical variants
  • GtkActivatable is a new interface that must be implemented by widgets that are used as action proxies

Changes in GtkEntry

  • GtkEntry can show icons at either side of the entry, which can be made clickable, drag sources, etc.
  • GtkEntry can show progress information behind the text.
  • GTK+ picks the best available placeholder character for password entries unless one is explicitly set.
  • GTK+ displays a Caps Lock warning in password entries.
  • Input methods can now be selected per-widget with the “im-module” property.

Changes in GtkScale

  • GtkScale can now display annotated marks for certain values.

Changes in GtkStatusIcon

  • GTK+ uses an extension of the tray icon specification to negotiate RGBA support. This is also supported by the GNOME panel.
  • GtkStatusIcon now supports scroll events, middle clicks and rich tooltips if the platform allows it.

Changes in file chooser

  • The file chooser can optionally show file sizes.
  • Volumes are mounted when necessary.
  • GTK+ remembers the file chooser’s window size across invocations.
  • Non-local uris can be entered in the location entry.

Changes in printing support

  • Page rendering can be deferred to a thread.

Internationalization support

  • Keyboard shortcut handling has been changed, to help with a longstanding complaint about the way in which GTK+ handles multiple keyboard layouts. GTK+ now only uses keys from groups other than the current group if they are not present in the current group.

GDK changes

  • GdkKeymap emits a state-changed signal when the Caps Lock state changes.
  • There is a predefined type for blank cursors, GDK_BLANK_CURSOR.

For more details and lists of fixed bugs, see the
announcements for the 2.15.x development releases:

See the original announcement for more info and downloads.