The X-Windows system is all-pervasive but struggles with security and performance graphics. Alan Griffiths introduces Mir Abstraction Layer to deal with these issues.
What is Mir?
The project I’m working on is Mir. This is a replacement for the venerable X Windows (see ‘We need a new windowing system’). Mir is a set of libraries providing the facilities for the participants in window management: the ‘servers’ that manage organising the windows onscreen and the ‘clients’ (or applications) that provide the content of the windows. In addition there are facilities to load plugin modules for different ‘graphics platforms’, ‘input platforms’ and renderers. At the time of writing, the supported platforms are the Mesa and Android graphics stacks and running the ‘server’ either directly on these drivers or as a ‘guest’ of either Mir itself or of X11.
|We need a new windowing system|
The X-Windows system has been, and remains, immensely successful in providing a way to interact with computers. It underlies many desktop environments and graphical user interface toolkits and lets them work together. But it comes from an era when computers were very different from now, and there are real concerns that are hard to meet.
In 1980 computers were big things managed by specialists and connecting them to one another was ‘bleeding edge’. In that era, the cost of developing software was such that any benefit to be gained by ‘listening in’ on what was happening was negligible: there were few computers, they were isolated, and the work they did was not open to exploitation.
X-Windows developed in this environment and, through a series of extensions, has adapted to many changes. But it is inherently insecure: any application can find out what happening on the display (and affect it). You can write applications like Xeyes that tracks the cursor with its ‘eyes’ or ‘Tickeys’ that listens to the keyboard to generate typewriter noises.
X-Windows is poorly adapted to a world with millions of computers connected to the Internet, being used for credit card transactions and online banking, and managed by non-experts who willingly install programs from complete strangers.
There has been a growing realization that adapting X-Windows to the new requirements of security and graphics performance isn’t feasible. There are at least two projects aimed at providing a replacement: Mir and Wayland/Weston. While some see these as competing, there are a lot of areas where they have common interests: they both need to interact with other software that previously assumed X11, and much of the work needed to introduce support an alternatives benefits both projects.
There are multiple downstream projects using the ‘client’ side of Mir: there’s Mir support available in GTK, Qt and SDL2. In addition, there’s an X11 server that runs on Mir: Xmir, this allows X based applications to run on Mir servers.
On the server side, Mir hasn’t had a range of projects using it: it has been in use by the Unity8 window manager used on phones and tablets and recently made available as a ‘preview’ on the Ubuntu 16.10 desktop.
While having a downstream project that uses Mir on real devices that ship to real customers has been a big benefit, the close association of the two projects has had some downsides.
Because the ‘client’ side of Mir has multiple projects using it, the importance of a stable API and ABI has been both appreciated and acted upon . On the server side things haven’t been so disciplined. The API has evolved gradually and the ABI has broken on almost every release.
The slow evolution of the server API has been managed by maintaining a ‘compatibility branch’ of Unity8 and releasing that at the same time as every Mir release. (I’m keeping the explanation simple: there are actually additional projects involved in this dance, which makes it even more involved and expensive.)
Maintaining and releasing these compatibility branches increases the effort involved in releasing Mir significantly. Changes need to made and tested across a family of projects belonging to separate teams. Because the pain involved increased gradually, this didn’t get the attention I felt it deserved.
The unstable server API has another, indirect, cost: it makes it impractical for anyone outside of the few Canonical teams we work with to write and maintain a Mir server.
This seemed unlikely to change in the normal course of events. The API was not designed with ABI stability in mind and the development focus was on delivering more features and not reducing these costs. While some efforts have been made by the team which reduced the API ‘churn’, they didn’t affect the underlying issue.
Elevating a system from chaos to order takes energy and conscious effort. And energy was constantly being drained by managing the release process.
Scratching the itch
Canonical has a policy of allowing staff to work on projects they choose for half a day each week (subject to some reasonable conditions). And, having checked with management, I elected to work on providing an alternative, stable API and ABI for writing of window managers.
I began by setting up a separate ‘Mir Abstraction Layer’ project (MirAL) and populating it with a copy of the code from the Mir ‘example’ servers. This immediately identified a series of bugs in the Mir packaging that had gone undetected. Nothing hard to fix, but obstacles to using Mir: headers referenced but not installed, overlooked dependencies on other projects, incorrect pkg-conf files, and so forth. I filed the Mir bugs and fixed them in my ‘day job’.
I then started separating out the generic window management logic from the specifics in the examples and building an API between them. Thus emerged the three principles interfaces of this library: a ‘window management policy’, a ‘basic window manager’ into which a policy slotted and ‘window management tools’ which provides functionality.
This meant that the basic window management functionality like the placement of menus could be shared between different approaches to window management: a ‘normal’ desktop, a ‘tiling’ version and ‘kiosk’ that could support embedded uses while not allowing the user to manipulate windows.
Having got these in place, along with some other meaningful concepts, I started rework to protect against the types of ABI breakage that were all too common with the existing server APIs. Data structures and virtual function tables in particular are fragile with respect to changes. One technique I used a lot was the ‘Cheshire Cat’ idiom as that avoids ABI breaking changes to virtual function tables.
I’d got to the point where I’d proved to myself that this approach could work when a new priority arrived in my ‘day job’. This was to provide window management support for Unity8 on the desktop. Until this point, Unity8 had only had to deal with the ‘one screen, one active application, one window’ use case of the phone and then an extension of this to support ‘sidestage’ on tablets. And in Mir much of the ‘window management support’ was example and test code.
What was needed was a place to consolidate the existing window management support and iterate quickly towards a more integrated approach. Also, to support additional projects beyond Unity8 (both from within Canonical or from outside) this also needed to be a place where other shells and desktop environments can leverage this functionality.
It sounded a lot like what I’d started with MirAL. So MirAL switched from being my hobby to being my ‘day job’ and gained Unity8, a ‘real world’ shell, as a prospective downstream.
A colleague (Gerry Boland) who had done much of the work integrating Unity8 with Mir and I started working to make it possible to migrate the QtMir project (which did the integration) to use the new API and exploit the window management support it provided.
We copied the code from the ‘QtMir’ project into the MirAL source tree and started work on joining things together. This proved very helpful in refining the concepts in the MirAL API, identifying gaps in the functionality it provides and soon gave us confidence that this was a workable approach.
The effectiveness of this work has been established and recently work was started on joining things up the all the way into Unity8 and integrating with the more sophisticated window management it implements.
Working with applications
Toolkits with Mir backends
Another piece of work happening around the same time was the effort to get third party applications to work correctly with Mir shells. Most applications are not written directly against X-Windows but use ‘toolkits’ that provide higher level concepts. And these have requirements on window management (like putting tooltips in the right place).
Two toolkits of immediate significance are GTK+ (on which gnome applications are built) and Qt (which is widely used in Canonical) both of which already have optional Mir ‘backends’. But the amount of testing these had got was limited whilst Mir work was focussed on the phone.
The window management work I was doing in MirAL and especially the sample ‘miral-shell’ became a testing ground how window management features interact with the Mir support in gtk-mir and qtubuntu. (And other client libraries such as SDL2.)
To aid with testing, MirAL comes with a handy script (miral-run) to set up the environment needed by these toolkits and run them against a Mir server.
Not all applications use these toolkits and supporting X11 applications by running the Xmir an X-server based on Mir is a bit fiddly. To facilitate testing this approach with MirAL there’s another script ‘miral-xrun’ that finds a free port, starts an X server, runs the application and then closes the X server when the application exits.
Debugging window management
While working to track down problems in the interaction between toolkits and MirAL’s window management I found the time to introduce an immensely helpful logging facility that logs all calls into the window management policy and all the calls made to the window management tools. This has been in discovering why what we see happens, happens. It has helped diagnose bugs in both MirAL and the toolkit backends. This can be used with any server based on MirAL by adding
to the command-line.
The state of MirAL right now
MirAL is available either from the Ubuntu archives, or from Launchpad [ Launchpad ] for building from source.
Using MirAL, it is very easy to create Mir based window managers. As an experiment colleague created this (rather silly) shell in under an hour: https://github.com/BrandonSchaefer/bad-shell .
Work is continuing to improve the window management capabilities and offer the ‘missing’ Mir facilities used by QtMir that are not currently supported by the new API. These will be presented in a form suitable for consumption by other projects.
For the latest information visit my ‘Canonical Voices’ blog [ voices ].