Shells for graphical interfaces come in many forms, from digital signage and kiosks that just show a single full screen application; to desktop environments that manage multiple applications, multiple screens and multiple workspaces. Traditionally, shells are built from a number of closely coupled components: display servers, compositors, window managers and panels.
Mir is a library for developing shells that makes it easier to share common functionality between them while preserving the freedom to be different where it matters. Mir provides window management defaults, but does not impose a particular window management style. It provides some default graphics hardware/driver stacks, but others can be (and are) used. It is possible to customize the compositing, etc.
Wayland is a protocol for communication between applications and shells and there are de-facto APIs, libraries and other tools for working with this protocol. There is a very narrow core to this protocol (basically just IPC and a mechanism for adding extensions) and to do anything “real” needs Wayland extension protocols. Mir provides the core and the standard extensions by default, and provides ways to enable and/or implement additional Wayland extension protocols.
If you create a shell with Mir you do not need to develop anything it has in common with other shells: window management, support for various hardware, compositing, Wayland. You can concentrate on the features that make it unique.
How is Mir used?
Like any other library, Mir is used by linking it into an application. There are existing applications using Mir…
Customizing Mir based shells
There are two basic ways to customize Mir: you can supply configuration options when the program is run, or you can write code that works with the Mir library.
Mir is structured so that the window management, compositing logic, graphics stacks and communications protocols can be configured independently. You can select a window management style (we provide floating, kiosk, and tiling window management examples) independently of other options such as the Wayland extension protocols supported.
In this article we’re going to focus on the options for configuring Wayland support.
Customizing Wayland extensions
The built in extensions
Mir comes with a number of Wayland extensions “built in”, the “recommended for every use” ones are enabled by default, others that are disabled by default and must be enabled by configuration or code.
The simplest way to configure these extensions is to take an existing Mir shell and specify the extensions you want:
Depending on the way you are deploying your shell, the extensions can be specified on the command line, as an environment variable, or in a configuration file.
When you write your own shell you can enable and/or disable extensions in the code. You can also write a “filter” so that you can control the extensions available to particular applications. (For example, you probably only want to offer zwlr_layer_shell_v1 to shell components.)
When writing shells it is common to have client “applications” that need access to features that are provided by the standard extensions. Unity8, for example, uses a richer set of window types so it can handle them well across both phones and desktops. This is where the ability to add Wayland extension protocols is useful: the client and server can exchange information not available by other means.
In addition to the built in extensions, shells can add extensions of their own. There are two reasons to do this when writing a shell:
your Wayland extension would be useful for many shells but is not yet ready to upstream to Mir; and,
your Wayland extension is specific to your shell and of no use elsewhere.
Once you have added your Wayland extension to your shell it can be controlled in the same ways as the built in extensions.
Implementing and testing Wayland extensions
When you implement a custom Wayland extension there are three steps to the process:
First, you generate “wrapper” classes that represent the protocol in Mir;
Then, you code and test the protocol logic for these classes;
Finally, you register and configure the protocol in your shell.
Use the development tools the Mir team provides to help with this:
Use the headers and code generator for the wrappers from the “libmirwayland-dev” package;
Test the implementation of your Wayland protocols with the Wayland Conformance Test Suite “wlcs”; and,
Register and configure your protocol using the Mir library “libmiral-dev”.
For more details on this development process follow the “worked example” which covers implementing the “primary_selection” protocol in the example egmde shell.
You might have many reasons to start building a graphical shell environment: you might want to customize the mir-kiosk experience, you might need a more desktop-like experience where multiple applications run on an appliance or you might want to “scratch an itch” and build something better that everything that came before.
Wayland provides an extensible way for shell components to communicate with each other, if there is no existing protocol that meets your needs then writing one that is fit for your purpose is well supported.
Whatever the reason you have for developing a Wayland based shell, Mir provides both a great foundation and the tools to build on it.