Site logo
Stories around the Genode Operating System RSS feed
Johannes Schlatow avatar

Adding a dynamic desktop background to Sculpt


For getting to know LVGL, I wrote a configurable desktop background for Sculpt OS that shows certain system information (e.g. clock, battery state).

LVGL (Light and Versatile Graphics Library) is a popular library for creating nice graphical user interfaces with modern looks. The idea of getting to know LVGL and making it available for app development on Genode was lingering in my head for a while. Fortunately, Josef had already spent some efforts at porting LVGL to Genode. Since I thought this would be a good opportunity to apply Goa's library-porting support, I moved his LVGL port to Goa. Moreover, as I wanted to get to know LVGL better, I decided to implement a simple application that displays system state information and that can be used as a desktop background in Sculpt OS.

This effort resulted in the pretty useful system_info package. In this article, I will demonstrate its usage. At the end of this article, I will also briefly give a few insights into the development of this LVGL application with Goa.

Installation

You can find the system_info package in my depot index so that you are able to install it on the current Sculpt OS. The package requires ROM access to the system reports. You must therefore install the fs_rom component first as shown in the screenshots below.

The fs_rom component is available in my depot under Tools → Utilities.
Route the file system session to the read-only system reports.

Moreover, you need to make sure that you have installed an RTC (real-time clock) provider. For x86 devices, the default Sculpt OS index contains the system_clock-pc package that accesses the hardware RTC. On non-PC hardware, you may use the sntp_dummy_rtc package. Because my hardware clock was showing the wrong time, I recently published the system_clock_rw-pc package on my depot, which does the same job but additionally accepts a set_rtc report to set the hardware clock. Such a report is generated by the sntp_client component, which you also find on my depot.

When you have decided for an RTC provider, you can install the system_info package from my depot (GUI section). Wire up the services as shown in the screenshots below. The GUI service shall be routed to the desktop background, the RTC to the previously installed RTC provider and the ROMs to the previously installed fs_rom component.

The system_info package requires a GUI, an RTC and a few ROM sessions.

After installing the system_info package as shown above, it appears as a desktop background. By default, system info shows the current time, date and calendar along with the NIC router's IP addresses. It is also supposed to show the IOMMU state as reported by the platform driver. As of Sculpt 23.10, however, the IOMMU is still driven by the NOVA kernel, hence the "no IOMMU present" message:

The default configuration also evaluates the acpi_battery from the acpica component. After installing acpica, we get a nice battery indicator as well.

Configuration

The system_info package is configurable. Its configuration determines what widgets are instantiated and in what order they are shown. This is the default configuration:

 <config default_timezone="CET-1CEST,M3.5.0,M10.5.0">
   <vfs> <dir name="dev"> <log/> <rtc/> </dir> </vfs>
   <libc stdout="/dev/log" rtc="/dev/rtc"/>
   <clock/>
   <calendar/>
   <battery rom="runtime/acpica/acpi_battery"/>
   <tabular rom="runtime/nic_router/state" alt="no IP found">
     <node type="domain" name="uplink">
       <row label="Uplink" attribute="ipv4"/>
     </node>
     <node type="domain" name="default">
       <row label="Default" attribute="ipv4"/>
     </node>
   </tabular>
   <tabular rom="drivers/iommu" alt="no IOMMU present">
     <node type="intel">
       <row label="IOMMU" attribute="name" highlight="yes"/>
       <row label="DMA Remapping" attribute="dma_remapping"/>
       <row label="IRQ Remapping" attribute="irq_remapping"/>
     </node>
   </tabular>
 </config>

Every node (except <vfs> and <libc>) instantiates a certain widget. In the default config, you see the clock, calendar, battery as well as the tabular widgets for the NIC router and IOMMU state. The widgets are arranged automatically in columns from left to right. The available widgets and their attributes is documented in the README.

Since the system_info package merely comprises the equally-named component, you may easily provide your own configuration by means of a launcher file. I created a /config/launcher/system_info file by installing the system_info package and copying the corresponding <start> node from /config/managed/deploy. I renamed the <start> node to <launcher>, removed superfluous attributes and inserted my custom config:

 <launcher pkg="jschlatow/pkg/system_info/2024-02-06">
   <route>
     <service name="Gui">
       <parent label="backdrop"/>
     </service>
     <service name="Rtc">
       <child name="system_clock-pc"/>
     </service>
     <service name="ROM" label="runtime/acpica/acpi_battery">
       <child name="fs_rom"/>
     </service>
     <service name="ROM" label="drivers/iommu">
       <child name="fs_rom"/>
     </service>
     <service name="ROM" label="runtime/nic_router/state">
       <child name="fs_rom"/>
     </service>
   </route>

   <config ...>
     ...
   </config>
 </launcher>

Typical examples of customisation are: changing the background colour, reordering widgets, adding/removing widgets, changing the time zone. Time zones are specified according to the POSIX TZ variable scheme. Let's add a few clock widgets with different time zones:

 <config default_timezone="CET-1CEST,M3.5.0,M10.5.0">
   <vfs> <dir name="dev"> <log/> <rtc/> </dir> </vfs>
   <libc stdout="/dev/log" rtc="/dev/rtc"/>

   <label>Berlin</label>
   <clock/>
   <calendar/>

   <label>New York</label>
   <clock timezone="UTC5"/>
   <calendar timezone="UTC5"/>

   <label size="20">Broken Hill,
   New South Wales</label>
   <clock timezone="UTC-10:30"/>
   <calendar timezone="UTC-10:30"/>
 </config>

Beautification

If you got used to the sticks_blue_backdrop background, you are probably going to notice the dull looks of the coloured background of system_info. Fortunately, I managed to integrate alpha-channel support, which allows combining a backdrop image with system_info. All you need to do is setting an eight-digit background colour. The last two digits of this colour determine the alpha channel from transparent (00) to completely opaque (ff). Let's try a semi-transparent background colour:

 <config background_color="#11558833">
   ...
The system_info background can be combined with a backdrop image.

Development

The system_info component uses LVGL. I have added an lvgl project to my goa-projects repository in order to make a Genode port of LVGL available in form of an api archive. Typically, LVGL is used as a static library and specifically tailored to the application. Since Goa only supports shared libraries, however, I enabled most of the features in its lv_conf.h.

In addition to the LVGL port, Josef came up with an lvgl_support library that simplifies the usage of LVGL in Genode. The support library handles the initialisation of LVGL and its interfacing to Genode's GUI session. In particular, it handles framebuffer resize events and input events. Note that the support lib is still in experimental state, especially for interactive scenarios. Nonetheless, with this support library, LVGL is easily initialised via config struct and a single init call:

 Lvgl::Config _lvgl_config { .title              = "System Info",
                             .initial_width      = 800,
                             .initial_height     = 600,
                             .allow_resize       = true,
                             .use_refresh_sync   = true,
                             .use_alpha          = true,
                             .use_keyboard       = false,
                             .use_mouse          = false,
                             .use_periodic_timer = true,
                             .periodic_ms        = 5000,
                             .resize_callback    = &_resize_callback,
                             .timer_callback     = &_timer_callback,
 };

 Lvgl::init(_env, _lvgl_config);

During the development of the system_info component with Goa, I greatly benefited from goa run, which executes the component on the host system using base-linux and an SDL-based framebuffer. By resizing the SDL window, I could conveniently test the automatic arrangement and scaling of the widgets. I also made use of the fact that Goa routes all unknown ROM sessions to an lx_fs at var/rom. This was highly comfortable as this allowed me to emulate the required system reports.

Enjoy!

Links

Goa project

https://github.com/jschlatow/goa-projects/tree/master/lvgl/system_info

README

https://raw.githubusercontent.com/jschlatow/goa-projects/master/lvgl/system_info/pkg/system_info/README