    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Making a Linux Desktop: Painting Some Wallpaper</title>
        <link>https://members.accu.org/index.php/articles/2714</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Design of applications and programs + CVu Journal Vol 31, #5 - November 2019</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c67/">Design</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c404/">315</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c67-404/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c67+404/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
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/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Making a Linux Desktop: Painting Some Wallpaper</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 04 November 2019 18:17:17 +00:00 or Mon, 04 November 2019 18:17:17 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Alan Griffiths continues his series on coding with the Mir library.</p>
<p><strong>Body:</strong>&nbsp;<p>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 are 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.</p>

<p>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.</p>

<p>Last issue we finished with a basic but functional desktop shell. This time weâ€™ll extend that with the capability to launch full screen â€˜applicationsâ€™ within the desktop and use that to paint some a simple wallpaper.</p>

<h2>Preparation</h2>

<p>The code in this article needs Mir 1.2 (or later). On Ubuntu 18.04 (and later), Mir 1.4 is available from the mir-team/release PPA. It is also useful to install the <code>weston</code> package as the example makes use of <code>weston-terminal</code> as a Wayland based terminal application and the Qt toolkitâ€™s Wayland support: <code>qtwayland5</code>. And finally, the <code>g++</code> compiler and <code>cmake</code>.</p>

<pre class="programlisting">
  $ sudo apt-add-repository ppa:mir-team/release
  $ sudo apt install libmiral-dev mir-graphics-  drivers-desktop
  $ sudo apt install weston qtwayland5
  $ sudo apt install g++ cmake</pre>

<p>All these we installed last time; this time weâ€™ll use a few more:</p>

<pre class="programlisting">
  $ sudo apt install libwayland-dev libfreetype6-  dev libxkbcommon-dev</pre>
  
<p>We need <code>libwayland-dev</code> to write our full-screen client, to draw some text and to support the keyboard handling weâ€™ll need in the following articles.</p>

<p>Mir 1.4 is available on Fedora and can be built from source for many versions of Linux.</p>

<h3>Building the example</h3>

<p>The full code for this example is available on github:</p>

<pre class="programlisting">
  $ git clone https://github.com/AlanGriffiths/  egmde.git
  $ git checkout Article-2</pre>
  
<p>Naturally, the code is likely to evolve, so you will find other branches, but the <code>Article-2</code> branch goes with this article. Assuming that youâ€™ve MirAL installed as described above you can now build egmde as follows:</p>

<pre class="programlisting">
  $ mkdir egmde/build
  $ cd egmde/build
  $ cmake ..
  $ make</pre>

<h3>Running the example</h3>

<p>After this you can start egmde:</p>

<pre class="programlisting">
  $ ./egmde</pre>
  
<p>This time the Mir-on-X window should have a coloured gradient with the words â€œCtrl-Alt-T = terminal | Ctrl-Alt-BkSp = quitâ€ at the bottom. But thereâ€™s more: the background can be configured by the user. If you type:</p>

<pre class="programlisting">
  $ ./egmde â€“help</pre>
  
<p>youâ€™ll get a list of options that includes the following:</p>

<pre class="programlisting">
  --wallpaper-top arg (=0x000000)      Colour of   wallpaper RGB
  --wallpaper-bottom arg (=0x92006a)   Colour of   wallpaper RGB</pre>
  
<p>These are two options that allow you to experiment with different colours for the background gradient. For example:</p>

<pre class="programlisting">
  $ ./egmde --wallpaper-top 0x171717 --wallpaper-  bottom 0x7f7f7f</pre>
  
<p>Once you have found some favoured colours you can save them in a config file:</p>

<pre class="programlisting">
  $ cat ~/.config/egmde.config 
  wallpaper-top=0x170000
  wallpaper-bottom=0x7f1f1f</pre>
  
<p>A background that can be configured by the user makes egmde look a little more finished than it did last time (even if it doesnâ€™t do cat photos).</p>

<h3>Installing the example</h3>

<p>If you install egmde and it will be added to the greeter menu (typically a â€˜cog wheelâ€™ on the sign-on screen):</p>

<pre class="programlisting">
  $ sudo make install</pre>
  
<p>Depending upon the greeter used on your system, it may be necessary to reboot before egmde appears as a login shell.</p>

<p>To register applications with deskop environments we install a .desktop file in <span class="filename">/usr/share/applications</span> and to register Wayland based desktops with the greeter we install a <span class="filename">.desktop</span> file in <span class="filename">/usr/share/wayland-sessions/</span>. The content needed for both cases is similar, so for this example we use the same <span class="filename">.desktop</span> file and install it to both places.</p>

<h2>The example code</h2>

<p>Thereâ€™s a lot more code (about 20Ã—) than last time, so I wonâ€™t attempt to put it all in a listing with the article:</p>

<pre class="programlisting">
  $ wc -l *.cpp *.h
    616 egfullscreenclient.cpp
     90 egmde.cpp
    176 egwallpaper.cpp
     46 egwindowmanager.cpp
    201 printer.cpp
    236 egfullscreenclient.h
     58 egwallpaper.h
     43 egwindowmanager.h
     54 printer.h
   1520 total</pre>

<h3>egmde.cpp</h3>

<p>First letâ€™s look at the changes to <span class="filename">egmde.cpp</span>:</p>

<pre class="programlisting">
  #include &quot;egwallpaper.h&quot;
  #include &quot;egwindowmanager.h&quot;
  #include &lt;miral/command_line_option.h&gt;
  #include &lt;miral/internal_client.h&gt;</pre>
  
<p>There are two headers from the example project and three from the MirAL library. Weâ€™ll see the use of the MirAL library in the rest of this file and examine the example files after that.</p>

<p>This creates a <code>Wallpaper</code> object and ensures that the runner calls <code>stop()</code> on it just before closing down the server:</p>

<pre class="programlisting">
  egmde::Wallpaper wallpaper;
  runner.add_stop_callback([&amp;] { 
    wallpaper.stop(); });</pre>
	
<p>Instead of the window manager provided by MirAL we use our own. There is only a small change and weâ€™ll see what that is later:</p>

<pre class="programlisting"><span style="text-decoration:line-through;">
set_window_management_policy
  &lt;MinimalWindowManager&gt;(),</span>

  set_window_management_policy
    &lt;egmde::WindowManager&gt;(wallpaper),</pre>
	
<p>These three lines provide configuration options for the wallpaper and start an â€˜internal clientâ€™ application that provides the wallpaper:</p>

<pre class="programlisting">
  CommandLineOption{[&amp;](auto&amp; option) {
    wallpaper.top(option);}, &quot;wallpaper-top&quot;,
    &quot;Colour of wallpaper RGB&quot;, &quot;0x000000&quot;},
  CommandLineOption{[&amp;](auto&amp; option) {
    wallpaper.bottom(option);}, &quot;wallpaper-bottom&quot;,
    &quot;Colour of wallpaper RGB&quot;,
    EGMDE_WALLPAPER_BOTTOM},
  StartupInternalClient{std::ref(wallpaper)},</pre>
  
<p>As we saw above, the configuration options are not just â€˜command-lineâ€™: like other Mir configuration options they can be provided via environment variables and a config file.</p>

<h3>egfullscreenclient.*</h3>

<p>The largest chunk of new code is an abstract <code>FullscreenClient</code> class that provides a framework for managing full-screen windows. While useful, both for this article and for the next, it doesnâ€™t use the Mir APIs and wonâ€™t be explored further here.</p>

<h3>egwallpaper.*</h3>

<p>The example <code>Wallpaper</code> class (Listing 1) provides the interface required to start an â€˜internal clientâ€™ application: two function call operators, one to provide the Wayland connection to use, one for the server-side â€˜sessionâ€™ used by the window manager to identify the application.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
class Wallpaper
{
public:
  void operator()(wl_display* display);
  void operator()(std::weak_ptr
    &lt;mir::scene::Session&gt; const&amp; session);
  auto session() const -&gt;
    std::shared_ptr&lt;mir::scene::Session&gt;;
  void stop();
  // Used in initialization to set colour
  void bottom(std::string const&amp; option);
  void top(std::string const&amp; option);
private:
  std::mutex mutable mutex;
  std::weak_ptr&lt;mir::scene::Session&gt;
    weak_session;
  uint8_t bottom_colour[4] = { 0x0a, 0x24, 0x77,
    0xFF };
  uint8_t top_colour[4] = { 0x00, 0x00, 0x00,
    0xFF };
  struct Self;
  std::weak_ptr&lt;Self&gt; self;
};
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>It also provides two functions we need to retrieve the â€˜sessionâ€™ and to stop the wallpaper application running on shutdown (as seen in <code>runner.add_stop_callback()</code> above).</p>

<p>Finally, it provides two functions to allow the wallpaper colour gradient to be configured.</p>

<p>Internally, the <code>Wallpaper::Self</code> class derives from <code>FullscreenClient</code> and provides (Wayland based) code to paint the wallpaper on each screen. This is also where the <span class="filename">printer.*</span> files are used; they are a convenience wrapper around <code>libfreetype</code> for drawing text into a graphics buffer. Once again, a close examination of that code goes beyond this exploration of the Mir APIs.</p>

<h3>egwindowmanager.*</h3>

<p>The example <code>WindowManager</code> class (Listing 2) extends the <code>MinimalWindowManager</code> we saw in the last issue. The only change it makes is to extend the <code>place_new_window()</code> to check the session against the wallpaper and, for the wallpaper, ensure that the window can never get input focus (and, as a side effect, is never raised above other windows). Thereâ€™s currently no Wayland extension that allows a client to exploit the rich semantics of Mirâ€™s window type systems. But, as this is an internal client, we can work-around it by setting the type ourselves.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
class WindowManager : public MinimalWindowManager
{
public:
  WindowManager(WindowManagerTools const&amp; tools,
    Wallpaper const&amp; wallpaper);
  auto place_new_window(
    ApplicationInfo const&amp; app_info,
    WindowSpecification const&amp;
      requested_specification)
  -&gt; miral::WindowSpecification override;
private:
  Wallpaper const* const wallpaper;
};
// Implementation
auto WindowManager::place_new_window(
  ApplicationInfo const&amp; app_info,
  WindowSpecification const&amp;
    requested_specification)
-&gt; WindowSpecification
{
  auto result =
    MinimalWindowManager::place_new_window(
    app_info, requested_specification);
  if (app_info.application() == 
    wallpaper-&gt;session())
  {
    // Setting the window type.
    result.type() = mir_window_type_decoration;
  }
  return result;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<h2>Conclusion</h2>

<p>This article shows how the Mir library can provide a stable starting point for adding functionality to a â€˜desktop environmentâ€™. The next article will continue from this point and add a â€˜launcherâ€™ for selecting and starting applications.</p>

<h2>References</h2>

<ul>
	<li>The Mir homepage: <a href="https://mir-server.io/">https://mir-server.io/</a></li>
	<li>The egmde git repo: <a href="https://github.com/AlanGriffiths/egmde">https://github.com/AlanGriffiths/egmde</a></li>
</ul>

<p class="bio"><span class="author"><b>Alan Griffiths</b></span> 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.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
