    <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 â€“ Launching Applications</title>
        <link>https://members.accu.org/index.php/articles/2761</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">Programming Topics + CVu Journal Vol 32, #1 - March 2020</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/c65/">Programming</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/c408/">321</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+408/">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 â€“ Launching Applications</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 03 March 2020 23:03:18 +00:00 or Tue, 03 March 2020 23:03:18 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Alan Griffiths continues his series on the Mir desktop.</p>
<p><strong>Body:</strong>&nbsp;<p>Iâ€™m working on a project (Mir <a href="#[1]">[1]</a>) that, among other things, aims to make it easy to develop graphical â€˜desktop environmentsâ€™ for Linux. Thereâ€™s 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.</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 with some wallpaper. This time weâ€™ll extend that with the capability to select and launch applications from the desktop.</p>

<h2>Preparation</h2>

<p>The code in this article needs Mir 1.2 (or later). On Ubuntu 18.04 (and later) Mir 1.7 is available from the mir-team/release PPA. To build it requires a few additional packages as indicated below. It is also useful to install the Qt toolkitâ€™s Wayland support: qtwayland5. And finally, the g++ compiler and cmake.</p>

<pre class="programlisting">
  $ 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</pre>
  
<p>Mir 1.6 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 <a href="#[2]">[2]</a>:</p>

<pre class="programlisting">
  $ git clone https://github.com/AlanGriffiths/
    egmde.git
  $ git checkout Article-3</pre>
  
<p>Naturally, the code is likely to evolve, so you will find other branches, but the Article-3 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-A = app launcher | Ctrl-Alt-T = terminal | Ctrl-Alt-BkSp = quitâ€ at the bottom.</p>

<p>If you press <span class="pattern">Ctrl-Alt-A</span> you will see the name of one of the programs available on your computer, pressing up or down arrows will change the named program (as will pressing the initial letter of another program), pressing <span class="pattern">Space</span> or <span class="pattern">Enter</span> will (attempt to) launch the program.</p>

<p>If you have a touchscreen, you can activate the app launcher by swiping from the left edge, launch the shown app by touching the middle of the screen and change apps by touching the top or bottom area.</p>

<p>Normally launching the program will succeed, but if the program doesnâ€™t run using Wayland then it will fail. (A future article will explore supporting X11-only applications.)</p>

<h3>Listing â€˜desktopâ€™ applications</h3>

<p>The â€˜Desktop Entry Specificationâ€™ <a href="#[3]">[3]</a> details how desktops identify the available programs, the icons and text to display (in potentially many languages) and the command(s) to run them. Like GNOME, KDE, Unity and other desktop environments, egmde follows this specification.</p>

<p>This specification covers the places to look for <span class="filename">.desktop</span> files, and the content of these files. A large chunk of the new code deals with finding these files and extracting the name and command to execute.</p>

<p>The remaining code is based on the <code>FullscreenClient</code> class we saw in the last article and deals with offering a selection from the applications found in the <span class="filename">.desktop</span> files.</p>

<h2>The example code</h2>

<p>Iâ€™ll leave the interested reader to find and read the code of the new <code>Launcher</code> class, it deals with parsing files, handling the display and user input. Iâ€™ll just show the changes to the main file. Listing 1 shows the keyboard and touchscreen handling code to show the launcher.</p>

<table class="sidebartable">
    <tr>
        <td>
            <pre class="programlisting">
ExternalClientLauncher external_client_launcher;
egmde::Launcher launcher
  {external_client_launcher};
â€¦
  switch (mir_keyboard_event_scan_code(kev))
  {
    case KEY_A:launcher.show();
      return true;
â€¦
auto touch_shortcuts = [&amp;, gesture =
  false](MirEvent const* event) mutable
  {
    if (mir_event_get_type(event) !=
        mir_event_type_input)
      return false;
    auto const* input_event =
        mir_event_get_input_event(event);
    if (mir_input_event_get_type(input_event) !=
        mir_input_event_type_touch)
      return false;
    auto const* tev =
    mir_input_event_get_touch_event(input_event);
    if (gesture)
    {
      if (mir_touch_event_action(tev, 0) ==
          mir_touch_action_up) gesture = false;
        return true;
    }
    if (mir_touch_event_point_count(tev) != 1)
      return false;
    if (mir_touch_event_action(tev, 0) !=
        mir_touch_action_down)
      return false;
    if (mir_touch_event_axis_value(tev, 0,
        mir_touch_axis_x) &gt;= 5)
      return false;
    launcher.show();
    gesture = true;
    return true;
  };
â€¦
runner.add_stop_callback([&amp;] {launcher.stop();});
            </pre>
        </td>
    </tr>
    <tr>
        <td class="title">Listing 1</td>
    </tr>
</table>

<p>In the initial article of this series, the program simply expected to use weston-terminal as a Wayland based terminal emulator. This version actually tries to find a terminal thatâ€™s already installed. (There are two mechanisms for identifying a default terminal emulator on Linux: x-terminal-emulator from Debian and xdg-terminal from XDG. Sadly neither reflects user preferences, or Wayland support.) Listing 2 shows the new code.</p>

<table class="sidebartable">
    <tr>
        <td>
            <pre class="programlisting">
namespace
{
// Neither xdg-terminal nor x-terminal-emulator
// is guaranteed to exist, and neither is a good
// way to identify user preference...
  std::string const terminal_cmd 
    = []() -&gt;   std::string
  {
    auto const user_bin = &quot;/usr/bin/&quot;;
    for (std::string name : { &quot;weston-terminal&quot;,
        &quot;gnome-terminal&quot;, &quot;konsole&quot;, &quot;qterminal&quot;,
        &quot;lxterminal&quot;, &quot;xdg-terminal&quot;})
    {
      if (boost::filesystem::exists(user_bin
          + name))
        return name;
    }
    return &quot;x-terminal-emulator&quot;;
  }();
}
â€¦
    external_client_launcher.launch(
        {&quot;weston-terminal&quot;});
    case KEY_T: external_client_launcher.launch
        ({terminal_cmd});
      return true;
            </pre>
        </td>
    </tr>
    <tr>
        <td class="title">Listing 2</td>
    </tr>
</table>

<h2>Conclusion</h2>

<p>The program has grown from the 75 lines in the initial working example, but has started to look a little more polished and is a lot more functional. It is still not a big program (see below).</p>

<pre class="programlisting">
$ wc -l *.cpp *.h
  616 egfullscreenclient.cpp
  639 eglauncher.cpp
  147 egmde.cpp
  176 egwallpaper.cpp
   46 egwindowmanager.cpp
   53 egworker.cpp
  201 printer.cpp
  236 egfullscreenclient.h
   53 eglauncher.h
   58 egwallpaper.h
   43 egwindowmanager.h
   52 egworker.h
   54 printer.h
 2374 total</pre>
 
<h2>References</h2>

<p class="bibliomixed"><a id="[1]">[1]</a> The Mir homepage: <a href="https://mir-server.io/">https://mir-server.io/</a></p>

<p class="bibliomixed"><a id="[2]">[2]</a> The egmde git repo: <a href="https://github.com/AlanGriffiths/egmde">https://github.com/AlanGriffiths/egmde</a></p>

<p class="bibliomixed"><a id="[3]">[3]</a> â€˜Desktop Entry Specificationâ€™:<a href="https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html">https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html</a></p>


<p class="bio"><span class="author"><b>Alan Griffiths</b></span> 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>
