Journal Articles

CVu Journal Vol 32, #4 - September 2020 + Design of applications and programs
Browse in : All > Journals > CVu > 324 (9)
All > Topics > Design (236)
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: Making a Linux Desktop

Author: Bob Schmidt

Date: 08 September 2020 18:46:41 +01:00 or Tue, 08 September 2020 18:46:41 +01:00

Summary: Alan Griffiths adds support for shell components to the desktop environment.

Body: 

I’m working on a project (Mir) that, among other things, aims to make it easy to develop graphical ‘desktop environments’ for Linux. There are a lot of features that are common between all designs for desktop environments and, in addition, a lot that is common between the majority of designs. For example, it is common for applications to draw ‘windows’ and for these to be combined onto the screen.

By providing the common features, and for the rest offering both sensible defaults and an easy way to customise them, Mir is designed to support a range of possible designs. This series of articles demonstrates how to make use of the facilities Mir provides.

So far, all the articles in the series show features of the egmde ‘desktop environment’ being implemented in the egmde program itself. But there are often reasons to add features in separate programs: these can be developed and updated separately, or even replaced to tailor the user experience.

Because such programs are part of the ‘desktop environment’ they often use features of the compositor that are not (or should not be) available to ordinary applications. In particular, they might need to request that they are docked to an edge of the display or appear behind (or in front) of applications. These are things a normal Wayland application isn’t expected to do but are part of shell-specific Wayland extensions.

Mir provides implementations of several of these ‘shell component’ specific protocols, but leaves them disabled by default. In this article we’re going to see how egmde enables these protocols just for shell components.

Configuring shell components

The first thing we need to do is identify the programs we want to run as shell components. In egmde, I recently added a configuration option ‘shell-components’ as follows:

  CommandLineOption{
    run_shell_components,
    "shell-components",
    "Colon separated shell components to launch on    
    startup", ""},

This, like the options we’ve seen in previous articles, is passed to the run_with() method of MirRunner. In common with other Mir configuration options, users of egmde can specify shell components on the command line, with an environment variable or in a config file. In this case, we’ll just use a config file:

  echo shell-components=waybar >>
  ~/.config/egmde.config

Oh, while we’re at it, we ought to install ‘waybar’ – a simple, Wayland based, docking bar that can be used for this article (it doesn’t have to be Waybar, for example, ‘mate-panel’ works too).

  sudo apt install waybar

Identifying and running shell components

Now we need to launch the shell components on startup, and also ensure that we can identify them later so that we can allow them access to the special Wayland protocol extensions. We do that by keeping a note of their process identifiers (see Listing 1).

std::set<pid_t> shell_component_pids;
auto run_shell_components = 
  [&](std::string const& apps)
{
  for (auto i = begin(apps); i != end(apps); )
  {
    auto const j = find(i, end(apps), ':');
    shell_component_pids.insert(
      launcher.run_app(
        std::string{i, j},
        egmde::Launcher::Mode::wayland));
    if ((i = j) != end(apps)) ++i;
  }
};
			
Listing 1

The run_shell_components lambda is passed to the CommandLineOption we saw above and handles the shell-components option configured. We’ll use the list of shell_component_pids shortly.

Configuring the Wayland protocol extensions

The protocol extensions we’re interested in for shell components are wlr_layer_shell and xdg_output_manager. We can, with the list of process identifiers we built earlier, enable these just for shell components as shown in Listing 2.

// Protocols we're reserving for shell components
std::set<std::string> const shell_protocols{
  WaylandExtensions::zwlr_layer_shell_v1,
  WaylandExtensions::zxdg_output_manager_v1};
WaylandExtensions extensions;
for (auto const& protocol : shell_protocols)
{
  extensions.enable(protocol);
}
extensions.set_filter([&](Application const& app,
  char const* protocol)
{
  if (shell_protocols.find(protocol) 
    == end(shell_protocols))
    return true;
  return shell_component_pids.find(pid_of(app)) 
    != end(shell_component_pids);
});
			
Listing 2

This configures extensions to enable these protocol extensions but also run all enabled protocol extensions through a filter that disables them for any processes not found in shell_component_pids.

The only thing left after this, is to pass extensions to the run_with() method of MirRunner.

Running the changes

You can install and run egmde as a snap:

  snap install egmde --classic --edge

If you want to build it yourself, the source is on github, so you can download and build it (these instructions in Listing 3 are for Ubuntu, the details might vary for other distros).

sudo apt-add-repository ppa:mir-team/release
sudo apt install libmiral-dev mir-graphics-drivers-desktop libwayland-dev
sudo apt install libfreetype6-dev libxkbcommon-dev libboost-filesystem-dev
sudo apt install qtwayland5
sudo apt install g++ cmake
git clone https://github.com/AlanGriffiths/egmde.git
mkdir -p egmde/build
cd egmde/build
cmake ..
make
sudo make install
			
Listing 3

Either way, you can then select egmde at the greeter.

Conclusion

The format of this article has changed from earlier ones in the series. There have been a lot of incremental improvements to egmde in since the last one and the changes discussed here were not simple to separate into a branch based on the previous article.

The current versions has, in addition to the ‘shell component’ support discussed here, workspaces, and some additional keyboard shortcuts. (And quite a few bugs fixed.) The program has grown, but is still a manageable size for a ‘hobby project’:

$ wc -l *.cpp *.h
  658 egfullscreenclient.cpp
  766 eglauncher.cpp
  115 egmde.cpp
  187 egshellcommands.cpp
  176 egwallpaper.cpp
  382 egwindowmanager.cpp
   53 egworker.cpp
  229 printer.cpp
  241 egfullscreenclient.h
   67 eglauncher.h
   80 egshellcommands.h
   58 egwallpaper.h
   83 egwindowmanager.h
   52 egworker.h
   54 printer.h
 3201 total

There’s still some way to go before it is a full featured ‘desktop environment’, but I’ve found it usable for the majority of my computing needs.

References

The Mir homepage: https://mir-server.io/

The egmde git repo: https://github.com/AlanGriffiths/egmde

Alan Griffiths Alan Griffiths has delivered working software and development processes to a range of organizations, written for a number of magazines, spoken at several conferences, and made many friends.

Notes: 

More fields may be available via dynamicdata ..