The Compositor Modules "COMO" To Build Wayland Compositors Have Arrived

Written by Roman Gilg in Software on 4 March 2024 at 11:15 AM EST. Page 1 of 1. 42 Comments.

Open-source developer Roman Gilg who is known for his work on KWinFT prior to its rebranding as Theseus' Ship has some more important news to share today by way of Phoronix. Here's his guest post announcing The Compositor Modules.

Last week Phoronix reported that KWinFT was rebranded as Theseus' Ship, but also that there would be "something bigger" to talk about soon.

The time has come now. I'm happy to announce exclusively on Phoronix the very first release of The Compositor Modules - or short COMO, the C++ library collection to easily write Wayland and X11 compositors.

COMO logo

The first release is now available on GitHub. Let me give you a tour of what you can expect of this library. A library that as I believe will fill a big gap in the Wayland ecosystem.

Write Your Wayland Compositor like An X11 One

Let's face it: building a Wayland compositor is hard! Especially if you just want to implement some custom windowing logic. You still need among other things:

  • render stack via some graphics API and DRM
  • input stack via libinput
  • display management via DRM
  • drag-and-drop mediating between clients
  • logic for elevated operations like screenshots
  • and most likely a whole X11 window manager internally for Xwayland.

Writing an X11 window manager in comparison was way easier! You didn't need to do any of that because the XServer was doing it for you already. But on the other side what we certainly don't want anymore now with Wayland is a monolithic monster like the XServer was. The obvious solution is building support libraries to link against and simplify the creation of compositors.

There exist already some options for that:

  • wlroots
  • libweston
  • Mir
  • Qt Wayland Compositor
  • Louvre (new)
I believe though The Compositor Modules are much better suited to easily develop a feature rich Wayland compositor than any of the already existing ones for two simple reasons. The first one is that to write your own Wayland compositor all you need are three lines of CMake code and this main function:

   int main(int argc, char* argv[])
    {
        using namespace como;

        base::wayland::app_singleton app(argc, argv);

        using base_t = base::wayland::platform<>;
        base_t base({.config = base::config(KConfig::OpenFlag::FullConfig, "kwinft-minimalrc")});

        base.mod.render = std::make_unique<base_t::render_t>(base);
        base.mod.input = std::make_unique<base_t::input_t>(base, input::config(KConfig::NoGlobals));
        base.mod.space = std::make_unique<base_t::space_t>(*base.mod.render, *base.mod.input);

        return base::wayland::exec(base, app);
    }

As demonstrated by our MVP Minico.

The second reason is that The Compositor Modules are meant to be in the same way useful in a feature rich desktop session as well as a minimal embedded use case. Let me expand on this some more.

From Big Desktop

While The Compositor Modules make use of wlroots on the backend, their Wayland protocol side is not based on wlroots but Wrapland. This is due to the fact that The Compositor Modules are supposed to support building a fully functional compositor for the KDE Plasma desktop, what Theseus' Ship demonstrates.

wlroots doesn't support all the protocols needed for that. And it also doesn't provide all the integration with KDE desktop services, its rules and scripting API, its configuration system and last but not least the extensive X11 window manager feature set expected by legacy apps when running inside a KDE desktop.

KDE Plasma 6 desktop, screenshot from KDE.org
KDE Plasma is leading the pack in terms of functionality.

Similar things must be said about the other contenders. While libweston, Mir and Qt Wayland Compositor have always been primarily developed for minimal embedded use cases and only on second thought some of them have been made somewhat usable in constrained desktop use cases, Louve as a more recent option doesn't seem to be limited by that bias. But it is a greenfield project and expanding the smallish functionality it now offers to something large like the KDE desktop environment with all its quirks and features, is practically impossible.

On the other side The Compositor Modules were split out from KWinFT, what has been a fork of KWin. By that ancestry they maintained the same extraordinary level of functionality and integration with the big KDE Plasma desktop like the current standard KDE compositor. If you are looking for a full out of the box desktop experience without compromise and tinkering I believe a Wayland library may not offer less.

To Small Embedded

"Big desktop" is the one extreme, but The Compositor Modules are built to cover the whole range of applications for a Wayland compositor from big desktops like KDE over smaller desktops like LXQt to embedded applications.

Embedded use cases are an important field for Wayland as a technology. In terms of commercial potential this is probably the most important differentiating factor from the old X Window System, and clearly some of Wayland's design decisions have been influenced by it.

Examples of embedded applications
Embedded is a wide field, but the display requirements are in general less complex than on desktop.

So it is also no wonder that from the five library contenders listed above all three commercially backed ones are heavily focused on embedded applications.

Of course what they offer in this particular area is valid, but I still believe The Compositor Modules will be a better solution, due to them being based on wlroots and sharing their core with compositors for desktops. The second point means you can stress test this core on the desktop and transfer your experience and developer setup directly to embedded.

That this is not an empty requirement is shown by experiments like the one done by the MBition company, a subsidiary to Mercedes-Benz Group, who try to use KWin in new Mercedes.

It's a nice experiment and it shows that there is an incentive to use a bigger compositor in such cases, but ulimitively achieving this with the standard KDE compositor will be difficult as KWin was never built for this kind of use case and its monolithic nature imposes the desktop use case.

I put a lot of work into making sure that The Compositor Modules are the opposite: modular and open to any use case from big to small.

Let's look at some technical design decisions that are making this possible.

Modular Through C++ Templates

If you show a C++ programmer a random file of source code from KWin and one from The Compositor Modules the most glaring difference he will make out after few seconds is probably the heavy usage of generic programming in The Compositor Modules.

In fact I moved as much logic as possible to compile time, not only because it makes the runtime faster and the code safer, but also because it allows us to completely modularize the library structure in terms of dependencies and options for consumer customization.

Pattern of C++, Wayland and X11 logos
Advanced C++ techniques allow seamless integration between Wayland and X11 code.

Let's look at the first aspect. You can build a Wayland compositor without any X11 dependencies simply by *not* linking against the separate como::xwayland library. Internally this is made possible by several class templates, for example the space of all windows being templated over an `std::variant` of window types.

And if you don't need Xwayland, then you can just use a space without the X11 window type variant. This is all done at compile time, leveraging all the safety guarantees of the C++ type system and without the usage of macros.

For comparison last week support for builds without libxcb dependencies has also been merged into KWin. But due to KWin's monolithic architecture, this requires a lot of macro usage.

Let's look at the second aspect, customization options. When you build a Wayland compositor with The Compositor Modules, you have limitless options to customize your compositor by either subtyping through virtual inheritance or by even replacing types completely with your own custom ones.

As said everything is templated, so you may just introduce your own space to have a different logic for positioning windows, or you provide a different free function only to change a single aspect of it.

The Compositor Module's code has been refactored a lot to separate logic from data. This allows such type-specific overrides of helper functions.

Or you start a bit smaller with your customization, by limiting the things you compile. For example the above code of Minico omits adding a script field to the base.mod struct. This is something Theseus' Ship on the other side does. Omitting to add this field means omitting to compile the whole scripting module. This way in a simple declarative fashion we describe what functionality our compositor will offer and what it won't.

Modular Through Modern CMake

Modularity through templates is one thing. But as we provide a library collection, the goal of modularity needs to be supported through usage of modern CMake techniques.

A lot of work in the last year went into modularizing not only the code but also the library structure behind it. I achieved this through the consistent use of modern CMake techniques and meticulous unfolding of internal and external dependencies. In the end for Wayland compositors the following hierarchy of relations emerged:

COMO libraries.

Following this graph one can easily see what library modules are dependent on each other. The CMake code directly documents and ensures that.

Through usage of modern target-based CMake code even one single wrong header include will directly reveal itself. For example any *render* type usage from within the *input* module is impossible, since the input module only links against the *win* module.

For the future development of The Compositor Modules these dependency relations make it easier to trace bugs and scope features. For consumers of The Compositor Modules the dependencies provide a sane structure to base their assumptions about library functionality and their customizations on.

High Code Quality And Automation

When providing a library like The Compositor Modules, it is important to fulfill modern standards in terms of code safety and correctness.

This has been a goal from the very beginning and nowadays every code change is compiled in CI with all compiler warnings enabled as errors. We do this in parallel with GCC and Clang.

Also on pull request a test suite of currently over 100 active tests has to pass. This way it is ensured the master branch is always "green", an important criteria for regression-free code.

GitHub Actions result
GitHub Actions executed on a pull request for The Compositor Modules.

Of course this doesn't make bugs impossible, but long-term it is an important mechanism to increase stability. That there were such large and fundamental changes in the code base over the years, while at the same time it was possible to maintain the overall functionality and to stay largely on top of changes in KWin as well as other KDE components for the Plasma 6 transition, stands testament to that.

Next: More Features

With the release of The Compositor Modules the hard part is done now. The underlying overall library structure with the necessary abstractions has been established.

The focus can now be shifted to stabilization and more feature work. While The Compositor Modules already provide a large feature set there are still some important features missing as documented in the Wayland feature table.

Some of these features can likely be ported directly or at least partially from KWin, that received a lot of external funding in the last years for adding features. The good news is that implementing new features is relatively straightforward, when there is already a reference implementation available.

Other features will require more integration with wlroots, something I'm looking forward to as wlroots is a great project and depending more heavily on it pushes for greater unification and code reuse in the Wayland ecosystem.

Next: More Consumers

The first release of The Compositor Modules is of course still an unstable one. Stabilization will take time. But I still believe, since after all the large refactors are done now and the general structure has been established, it is a good point in time to base experimental compositor projects on The Compositor Modules.

The Compositor Modules should be a great fit for desktops like LXQt, XFCE or Cinnamon, that require a tailor-made compositing solution on Wayland. A solution which is on the one side open enough to adapt to their needs and on the other side provides enough features out of the box to not stretch their contributor resources too thin.

At the moment I'm looking into building such a solution with The Compositor Modules for LXQt. LXQt is an interesting project for me since it is a full desktop solution like KDE Plasma, but with a less extensive feature set. So a compositor for LXQt would showcase how one can purposefully and selectively scale down functionality when using The Compositor Modules.

Next: More Funding

Let's be real: a big project like The Compositor Modules can't be maintained long term in a sustained manner without some corporate financial backing.

In the last two years I worked on the project in my free time, in parallel to my work as a freelancer. I was able to sustain that work load, but you can't do that forever and you can't expect that from every contributor, who wants to provide more than a few lines of code to the project. That does hold for The Compositor Modules as it does for other big projects like KWin.

But The Compositor Modules now provide a great basis to build Wayland compositors for all kind of applications, from different flavours of the Linux desktop to embedded products.

My hope is that there are companies, who are willing to financially support the creation of a Wayland library like The Compositor Modules. A library which is not only meant to solve the company's own specific current use case, be it with a minimal solution like Minico, one with custom types or one with a maximal feature set like Theseus' Ship. But a library, which will raise the tide for all boats.

About The Author: Roman Gilg is a software architect with notable contributions to many open-source projects. He also has done industry work on complex systems, most often leveraging C++. Besides that he is as well an experienced platform engineer and project manager. At the moment he spearheads the WinFT projects with the declared goal of providing common display solutions for Linux desktop and embedded. He can be followed via Twitter or LinkedIn.

If you enjoyed this article consider joining Phoronix Premium to view this site ad-free, multi-page articles on a single page, and other benefits. PayPal or Stripe tips are also graciously accepted. Thanks for your support.


Related Articles