Debugging mir server/toolkit interactions


A feature added to the lp:miral trunk yesterday is making life a lot easier for developers working on MirAL based servers, and the toolkit extensions that support Mir. The feature is:

miral-shell --window-management-trace

Actually, the –window-management-trace switch will work with any MirAL base server (so miral-kiosk and egmde support it too).

What this does is cause the server to log every interaction with the window management policy – all the notifications it receives and all the calls it makes to the tools as a result.

This means that it is easy to find out that, for example, a “modal” gtk based dialog window is being created without specifying a parent. (Which is why the behaviour isn’t quite as expected – Mir servers will treat it as non-modal.)

To use this feature before the next MirAL release you do need build it yourself, but this only takes a minute (depending on your kit).It really is the easiest way to see exactly what is going on and why.

MirAL hits the Yakkety archives

Just a quick note: thanks to the efforts of my colleague Larry Price, libmiral is now available from the yakkety archive.

This means that if you’re running Ubuntu 16.10 you can install MirAL using apt and don’t need to build it yourself. Here’s what’s available:

  • libmiral-dev Developer files for the Mir ABI-stable abstraction layer
  • libmiral1 Display server for Ubuntu – ABI preserving abstraction layer
  • miral-doc API documentation for MirAL
  • miral-examples Display server for Ubuntu – demonstration programs

For example, before building egmde you just need to do this:

$ sudo apt install libmiral-dev

You can also install and run the miral-shell program with:

$ sudo apt install miral-examples
$ miral-shell

If you want to run X11 applications under miral-shell on X11 then you can do that too:

$ sudo apt install xmir
$ miral-shell&
$ Xmir -rootless :1&
$ DISPLAY=:1 gedit

An Example Mir Desktop Environment

The world of Mir

Mir is a set of libraries supporting the development of display servers, desktop environments, shells and implementing toolkit support for applications running on them.

As part of their “convergence” of computing devices Canonical are committed to providing Mir on a range of platforms including desktops, phones, tablets and “the internet of thing”. You can read about the work to provide it as a “snap” in the “internet of things” on Kevin Gunn’s blog [kg’s blog].

Toolkits and other “client” platforms that have support for Mir include GTK, Qt and SDL – which mean that applications using these can work on Mir. There’s a separate Xmir project to support X11 applications on Mir.

On the driver side of things Mir works with Mesa on desktop-like systems and, using libhybris, on an android based stack on a number of devices. The Mesa support is a work in progress and Ubuntu carries a set of patches to enable it. There are some notes about how to incorporate these on other platforms here: [Enabling Mir EGL]. Work is in progress to upstream Mir support.

The “Mir Abstraction Layer” (MirAL) packages the server-side functionality in a way that makes it easy to use. My previous post[MirAL] introduced MirAL in more detail.

Before we begin

If you want to experiment with this code I suggest using Ubuntu 16.04 or later on desktop for the reasons mentioned above. On an Ubuntu phone you can use the current stable version with this code, but doing development on a phone is a whole other article. On other distributions you likely need to patch Mesa and rebuild toolkits with Mir support enabled.

Having got an Ubuntu desktop you also need to install MirAL, at present this is not available from the Ubuntu archives, so you have to build and install it yourself:

$ sudo apt-get install devscripts equivs bzr
$ bzr branch lp:miral
$ sudo mk-build-deps -i --build-dep miral/debian/control
$ mkdir miral/build
$ cd miral/build
$ cmake ..
$ make
$ sudo make install

egmde [Example Mir Desktop Environment]

To illustrate MirAL I’m going to show what is involved in writing a (very simple) window manager. It runs on desktops, tablets and phones and supports keyboard, mouse and touch input. It will support applications using the GTK and Qt toolkits, SDL applications and (using Xmir) X11 applications.

The full code for this example is available on github:

$ git clone

Naturally, the code is likely to evolve, especially if I write a follow-up article but the version presented here is tagged v1.0. Assuming that you’ve MirAL installed as described above you can build it as follows:

$ mkdir egmde/build
$ cd egmde/build
$ cmake ..
$ make

The example code

A lot of the functionality (default placement of windows, menus etc.) comes with the MirAL library. For this exercise we’ll implement one class and write a main function that injects it into MirAL. The main program looks like this:

int main(int argc, char const* argv[])
    miral::MirRunner runner{argc, argv};

    return runner.run_with(

Yes, you’ve guessed it: the class we’ll be implementing is ExampleWindowManagerPolicy. It looks like this:

class ExampleWindowManagerPolicy : public CanonicalWindowManagerPolicy
    using CanonicalWindowManagerPolicy::CanonicalWindowManagerPolicy;

    // Switch apps  : Alt+Tab
    // Switch window: Alt+`
    // Close window : Alt-F4
    bool handle_keyboard_event(MirKeyboardEvent const* event) override;

    // Switch apps  : click on the corresponding window
    // Switch window: click on the corresponding window
    // Move window  : Alt-leftmousebutton drag
    // Resize window: Alt-middle_button drag
    bool handle_pointer_event(MirPointerEvent const* event) override;

    // Switch apps  : tap on the corresponding window
    // Switch window: tap on the corresponding window
    // Move window  : three finger drag
    // Resize window: three finger pinch
    bool handle_touch_event(MirTouchEvent const* event) override;

    void pointer_resize(Window const& window, Point cursor, Point old_cursor);
    void resize(WindowInfo& window_info, Point new_pos, Size new_size);

    // State held for move/resize by pointer
    Point old_cursor{};
    bool resizing = false;
    bool is_left_resize = false;
    bool is_top_resize = false;

    // State held for move/resize by touch
    int old_touch_pinch_top = 0;
    int old_touch_pinch_left = 0;
    int old_touch_pinch_width = 0;
    int old_touch_pinch_height = 0;

For this simple example the only functionality we’ll be providing is the handling of input events to allow the user to switch between applications and windows and to resize and move windows.

We only need to provide three handle_XXX_event() functions as we’re relying on the default behaviour for everything else. The first of these functions is the simplest:

bool ExampleWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event)
    auto const action = mir_keyboard_event_action(event);
    auto const shift_state = mir_keyboard_event_modifiers(event) & shift_states;

    if (action == mir_keyboard_action_down &&
        shift_state == mir_input_event_modifier_alt)
        switch (mir_keyboard_event_scan_code(event))
        case KEY_F4:
            return true;

        case KEY_TAB:
            return true;

        case KEY_GRAVE:
            return true;


    return false;

I don’t think this needs a lot of explanation: we select key presses while only the Alt button is pressed and act according to the button pressed.

The other two functions are a bit longer as they need to remember some state in order to interpret mouse or touchpad gestures. There’s in them nothing I consider worth pointing out here and the full code is available on github. There’s not much:

$ wc *
15 28 446 CMakeLists.txt
357 957 10528 egmde.cpp
372 985 10974 total

I have much to compare it with, bit I don’t think 372 lines is bad for a functional window manager.

Running egmde

Once egdme has been built you can run it in two modes: the simplest is the “Mir-on-X” mode:

$ ./egmde

This will produce a rather boring black “Mir-on-X” window. You can attach Mir clients to this:

$ miral-run gnome-system-monitor
$ miral-run gnome-terminal

These will run in the window and make it less boring. You can also have egmde launch them when it starts as follows:

$ ./egmde --startup gnome-terminal:gnome-system-monitor

If you don’t want to run in a window under X11 you can also give egmde access to your hardware directly by running it as root and specifying a “virtual terminal”. But I think it is probably better to use mir_demo_server in “system-compositor” mode to handle the hardware and launch egdme a normal user.

$ sudo apt install mir-demos
$ sudo mir_demo_server --vt 3 --window-manager system-compositor

You’ll find this switches you to vt3, switch back with Ctrl-Alt-F7 and, from another terminal, you can connect egdme to this. (We need the VT switch here as the host mir_demo_server is paused while X11 is in control.)

$ sudo chvt 3&&./egmde --host /tmp/mir_socket --startup gnome-terminal

You don’t have to start the gnome-terminal, but it is convenient as you can launch other applications. For example:

$ mir_demo_client_eglplasma


I hope that the egmde example is enough to spark someone’s interest in MirAL and to provide a starting point for developing something more ambitious.

Much of what has been discussed is a work-in-progress, especially MirAL which I hope to get added to the Ubuntu archives soon. I am optimistic this will happen as it is in the interests of both Canonical and the wider community to have a stable server ABI against which to write desktop environments (including Unity8). Indeed I’ve been working with the main developer of the QtMir abstraction layer to migrate it to MirAL.

Similarly, a significant portion of the work needed on Mesa to support Mir is similar to the work to support Wayland/Weston and everyone would benefit from cleaning this up (and, for example, removing hard dependencies on X11).