December 13, 2021

webassembly: the new kubernetes?

I had an "oh, duh, of course" moment a few weeks ago that I wanted to share: is WebAssembly the next Kubernetes?

katers gonna k8s

Kubernetes promises a software virtualization substrate that allows you to solve a number of problems at the same time:

  • Compared to running services on bare metal, Kubernetes ("k8s") lets you use hardware more efficiently. K8s lets you run many containers on one hardware server, and lets you just add more servers to your cluster as you need them.

  • The "cloud of containers" architecture efficiently divides up the work of building server-side applications. Your database team can ship database containers, your backend team ships java containers, and your product managers wire them all together using networking as the generic middle-layer. It cuts with the grain of Conway's law: the software looks like the org chart.

  • The container abstraction is generic enough to support lots of different kinds of services. Go, Java, C++, whatever -- it's not language-specific. Your dev teams can use what they like.

  • The operations team responsible for the k8s servers that run containers don't have to trust the containers that they run. There is some sandboxing and security built-in.

K8s itself is an evolution on a previous architecture, OpenStack. OpenStack had each container be a full virtual machine, with a whole kernel and operating system and everything. K8s instead generally uses containers, which don't generally require a kernel in the containers. The result is that they are lighter-weight -- think Docker versus VirtualBox.

In a Kubernetes deployment, you still have the kernel at a central place in your software architecture. The fundamental mechanism of containerization is the Linux kernel process, with private namespaces. These containers are then glued together by TCP and UDP sockets. However, though one or more kernel process per container does scale better than full virtual machines, it doesn't generally scale to millions of containers. And processes do have some start-up time -- you can't spin up a container for each request to a high-performance web service. These technical contraints lead to certain kinds of system architectures, with generally long-lived components that keep some kind of state.

k8s <=? w9y

Server-side WebAssembly is in a similar space as Kubernetes -- or rather, WebAssembly is similar to processes plus private namespaces. WebAssembly gives you a good abstraction barrier and (can give) high security isolation. It's even better in some ways because WebAssembly provides "allowlist" security -- it has no capabilities to start with, requiring that the "host" that runs the WebAssembly explicitly delegate some of its own capabilities to the guest WebAssembly module. Compare to processes which by default start with every capability and then have to be restricted.

Like Kubernetes, WebAssembly also gets you Conway's-law-affine systems. Instead of shipping containers, you ship WebAssembly modules -- and some metadata about what kinds of things they need from their environment (the 'imports'). And WebAssembly is generic -- it's a low level virtual machine that anything can compile to.

But, in WebAssembly you get a few more things. One is fast start. Because memory is data, you can arrange to create a WebAssembly module that starts with its state pre-initialized in memory. Such a module can start in microseconds -- fast enough to create one on every request, in some cases, just throwing away the state afterwards. You can run function-as-a-service architectures more effectively on WebAssembly than on containers. Another is that the virtualization is provided entirely in user-space. One process can multiplex between many different WebAssembly modules. This lets one server do more. And, you don't need to use networking to connect WebAssembly components; they can transfer data in memory, sometimes even without copying.

(A digression: this lightweight in-process aspect of WebAssembly makes it so that other architectures are also possible, e.g. this fun hack to sandbox a library linked into Firefox. They actually shipped that!)

I compare WebAssembly to K8s, but really it's more like processes and private namespaces. So one answer to the question as initially posed is that no, WebAssembly is not the next Kubernetes; that next thing is waiting to be built, though I know of a few organizations that have started already.

One thing does seem clear to me though: WebAssembly will be at the bottom of the new thing, and therefore that the near-term trajectory of WebAssembly is likely to follow that of Kubernetes, which means...

  • Champagne time for analysts!

  • The Gartner ✨✨Magic Quadrant✨✨™®© rides again

  • IBM spins out a new WebAssembly division

  • Accenture starts asking companies about their WebAssembly migration plan

  • The Linux Foundation tastes blood in the waters

And so on. I see turbulent waters in the near-term future. So in that sense, in which Kubernetes is not essentially a technical piece of software but rather a nexus of frothy commercial jousting, then yes, certainly: we have a fun 5 years or so ahead of us.

December 12, 2021

Can you help with bulk storage firmware updates?

Does anyone have any examples of peripheral devices that can have their firmware upgraded by dropping a new firmware file onto a mounted volume? e.g. insert device, new disk appears, firmware file is copied over, then the firmware update completes?

Could anyone with a device that supports firmware upgrade using bulk storage please fill in my 2 minute questionnaire? I’m trying to create a UF2-compatible plugin to fwupd and need data to make sure it’s suitable for all vendors and devices. The current pull request is here, but I have no idea if it is suitable yet. Thanks!

December 10, 2021

Loop: A simple music application

In the last year I've seen some really good musician that performs all the instruments in a song with just a loop machine, recording each instrument one by one in tracks and looping.

I was thinking that it should be easy to have a desktop application that does exactly the same, just some tracks to record some sounds and the playback with a loop option, and that's what I created during this week.

The Loop application is just a simple Gtk4 application that uses gstreamer to record tracks and then you can play each one at the same with or without loop option. With that, a good musician could create the base melody of the song and then sign on top of that. Unfortunately, I'm not a good musician, but I can use this to play around.

I've just created the request on flathub to add the application, so if everything is okay it will be available there soon, so more people can play with this awesome toy.

Right now it has the basic record, play and loop functionality with just four tracks, so don't expect to have a professional music app (yet). The recording and play times are not perfect and there's a delay, that's a known issue, but I'm planning to fix this issue and add more functionality in the future, like:

  • Make number of tracks configurable
  • Import track from files
  • Add a trim slider per track, to be able to adjust the recorder track to loop
  • Metronome tick and clock to have a visual reference for recording tracks
  • A record button, but export the combination of all tracks and mic to a mp3 file

And that's all. The logo and design is an initial version done by myself, so if any designer wants to take a look, all contributions are welcome. And of course any code contribution is also welcome.

If you use this application and do some good or fun performance, please, ping me on social networks and let me know.

Cambalache 0.8.0 released!

Cambalache is a new RAD tool for Gtk 4 and 3 with a clear MVC design and data model first philosophy.

Exactly one year ago I made the first commit…

commit 51d4185cd8556f0358cc463578df5a4138ac90b5
Author: Juan Pablo Ugarte
Date: Wed Dec 9 19:14:53 2020 -0300

Initial commit

Supports type system and interface data model.
Basic history (undo/redo stack) implementation with triggers.

It consisted of just 3 files, the data model, a python script to generate history triggers automatically and a small sql script to test it.

Fast forward one year and I am starting to believe it can be on feature parity with Glade sooner than expected.

Having a pretty solid backend this release focus on adding all the big missing UX parts, like a good type selector, workspace placeholders and basic clipboard actions like copy/paste.

Type chooser bar

Borrowing the design from Glade I implemented a type chooser that categorizes object classes to make it easier to find what you need.

Workspace placeholders

Containers now have placeholders to make it easier to add children in a specific positions

It supports the following actions:

  • Double click on a placeholder to create a new widget in place
  • <Control> + Insert to add more placeholders
  • <Control> + Delete to remove placeholders
  • <Shift><Control> + Insert to add a new row
  • <Shift><Control> + Delete to remove a row

Translatable properties

Thanks to the work of Philipp Unger it is possible to mark properties as translatable and add comments for translators.

Clipboard actions

To make life easier, common clipboard actions like, Copy, Paste, Cut and Delete where added.

Better unsupported features report

Cambalache will make its best effort to notify the user about unsupported features when importing UI files and export to a different filename as a precaution to avoid loosing data.

Matrix channel

Have any question? come chat with us at #cambalache:gnome.org

Where to get it?

As always you can get the code in gitlab

git clone https://gitlab.gnome.org/jpu/cambalache.git

or download the bundle from flathub*

flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user flathub ar.xjuan.Cambalache

* You might need to wait for a few hours before the build is actually published.

 

Happy coding!

#22 Spring Time...?

Update on what happened across the GNOME project in the week from December 03 to December 10.

Core Apps and Libraries

Libadwaita

Building blocks for modern GNOME apps using GTK4.

Alexander Mikhaylenko says

just in time for beta, the second part of Manu ’s work has landed and libadwaita now has physics-based spring animations. Leaflet, flap and carousel have all been updated to use them, and swipe tracker now provides velocity to pass into a spring animation, rather than a duration for a timed animation.

Mutter

A Wayland display server and X11 window manager and compositor library.

Georges Stavracas (feaneron) announces

Thanks to Carlos Garnacho, Mutter now sends input events at the device rate to applications. This should significantly increase perceived responsiveness for games and artistic applications. You can read more here: https://blogs.gnome.org/shell-dev/2021/12/08/an-eventful-instant/

GNOME Shell

Core system user interface for things like launching apps, switching windows, system search, and more.

YaLTeR reports

The work-in-progress new GNOME Shell screenshot UI is slowly but surely making its way to completion.

I added an area indicator during screencast recording making the boundaries easy to see. Also, screencasts no longer produce files with broken length.

The screenshot/screencast switch and the preferences button got keyboard hotkeys, and window selection got arrow navigation, making the screenshot UI fully keyboard-accessible. New tooltips show the hotkeys, making them easier to learn.

Finally, the screenshot UI mode is now preserved across screenshots letting you quickly take multiple window screenshots for example.

Circle Apps and Libraries

Video Trimmer

Trim videos quickly

Ivan Molodetskikh announces

Video Trimmer v0.7 is out, featuring Adwaita updates, dark style & high contrast support, optional re-encoding for accurate trimming, “Show in Files” button and new translations.

NewsFlash feed reader

Follow your favorite blogs & news sites.

jangernert says

NewsFlash 2.0 (aka the Gtk4 port) now has functional CI flatpaks. It was blocked for a long time by the Gtk4 version of webkit. 🥳 to the maintainers of the org.gnome.Sdk runtime. More details about whats new will follow as we’re inching closer to a release. In addition Felix Bühler (aka @Stunkymonkey) added FreshRSS support to NewsFlash.

Fragments

Easy to use BitTorrent client.

Felix says

Earlier this week I released the first beta version of Fragments 2.0. To make the final version as bug-free as possible, please download the beta version and test it as much as possible (feedback is welcome!). I showcased many of the new features in a Twitter thread.

Third Party Projects

Maximiliano reports

Now App Icon Preview, Emblem and Icon Library count with support for drag and drop!

You can drag icons from icon library into emblem, nautilus, or any svg editor. Both Emblem and App Icon Preview can now open SVG files by dragging them directly into the app.

Squeekboard

An on-screen-keyboard input method for Wayland

Guido reports

Squeekboard now features PIN, url and email layouts. We also reworked the theme handling so squeekboard defaults to dark-mode when run with phosh and matches its high contrast setting. Translations are now done via regular po files.

Phosh

A pure wayland shell for mobile devices.

Guido announces

We’ve released phosh 0.14.1 featuring

  • avatars during phone calls on lockscreen
  • DTMF during phone calls on lockscreen
  • an initial “Run command” prompt (Alt-F2)
  • better thumbnails in the overview
  • docked mode improvements
  • plenty of bug fixes and cleanups
  • updated translations

and much more. Check the full release notes for more details and contributors.

GNOME Shell Extensions

Simon Schneegans says

The new Desktop Cube Extension does not increase your productivity but gives some good old Compiz vibes!

heartmire reports

New extension - Focus changer. Change focus between windows in all directions using your keyboard. The extension will first try to find a suitable window within the same monitor. If there is none, it will try to find one on the next monitor in that direction (in a multi-monitor setup).

Available for GNOME Shell 3.6 - 41

https://extensions.gnome.org/extension/4627/focus-changer/

That’s all for this week!

See you next week, and be sure to stop by #thisweek:gnome.org with updates on your own projects!

December 09, 2021

PSA: The 5.17 kernel will require some initrd generator changes for kms drivers

Starting with kernel 5.17 the kernel supports the builtin privacy screens built into the LCD panel of some new laptop models.

This means that the drm drivers will now return -EPROBE_DEFER from their probe() method on models with a builtin privacy screen when the privacy screen provider driver has not been loaded yet.

To avoid any regressions distors should modify their initrd generation tools to include privacy screen provider drivers in the initrd (at least on systems with a privacy screen), before 5.17 kernels start showing up in their repos.

If this change is not made, then users using a graphical bootsplash (plymouth) will get an extra boot-delay of up to 8 seconds (DeviceTimeout in plymouthd.defaults) before plymouth will show and when using disk-encryption where the LUKS password is requested from the initrd, the system will fallback to text-mode after these 8 seconds.

I've written a patch with the necessary changes for dracut, which might be useful as an example for how to deal with this in other initrd generators, see: https://github.com/dracutdevs/dracut/pull/1666

I've also filed bugs for tracking this for Fedora, openSUSE, Arch, Debian and Ubuntu.

December 08, 2021

An Eventful Instant

Artist, gamers, rejoice! GNOME Shell 42 will let applications handle input events at the full input device rate.

It’s a long story

Traditionally, GNOME Shell has been compressing pointer motion events so its handling is synchronized to the monitor refresh rate, this means applications would typically see approximately 60 events per second (or 144 if you follow the trends).

This trait inherited from the early days of Clutter was not just a shortcut, handling motion events implies looking up the actor that is beneath the pointer (mainly so we know which actor to send the event to) and that was an expensive enough operation that it made sense to do with the lowest frequency possible. If you are a recurrent reader of this blog you might remember how this area got great improvements in the past.

But that alone is not enough, motion events can also end up handled in JS land, and it is in the best interest of GNOME Shell (and people complaining about frame loss) that we don’t need to jump into the JavaScript machinery too often in the course of a frame. This again makes sense to keep to a minimum.

Who wants it different?

Applications typically don’t care a lot about motion events, beyond keeping up with the frame rate. Others however have a stronger reliance on motion event data that this event compression is suboptimal.

Some examples where sending input events at the device rate matters:

  • Applications that use device input for velocity/direction/acceleration calculations (e.g. a drawing app applying a brush effect) want as much granularity as it is possible, compressing events is going to smooth values and tamper with those calculations.
  • Applications that render more often than the frame rate (e.g. games with vsync off) may spend multiple frames without seeing a motion event. Many of those are also timing sensitive, and not just want as much granularity as possible, but also want the events to be delivered as fast as possible.

How crazy is crazy?

As mentioned, events are now sent at the input device rate, but… what rate is that? This starts at tens of times per second on cheap devices, up to the lower hundred-or-so in your regular laptop touchpad, to the low hundreds on drawing tablets.

But enter the gamer, high end gaming mice have an input frequency of 1000Hz, which means there are approximately 16 events per frame (in the typical case of a 60Hz display) that must get through to the application ASAP. This usecase is significantly more demanding than the others, and not by a small margin.

A look under the hood

Having to look up the actor beneath the pointer 1000 times a second (16x as often) means it doesn’t suffice to avoid GPU based picking in favor of SIMD operations, there has to be a very aggressive form of caching as well.

To keep the required calculations to a minimum, Mutter now caches a set of rectangles that approximates the visible, uncovered area of the actor beneath the pointer. These are in the same coordinate space than input events so comparisons are direct. If the pointer moves outside the expressed region or the cache is dropped by other means (e.g. a relayout), the actor is looked up again and the new area cached.

This is of course most optimal when the actors are big, with pointer picking virtually dropping to 0 on e.g. fullscreen clients, but it helps even when blazing your pointer across many actors in the screen. Crossing a button from left to right can take a surprising amount of events.

But what about JavaScript? Would it maybe trigger a thousand times a second? Absolutely not, events as handled within Clutter (and GNOME Shell actors) are still motion compressed. This unthrottled event delivery only applies in the direction of Wayland clients.

There were other areas that got indirectly stressed by the many additional events, there’s been a number of optimizations across the board so it doesn’t turn bad even when Mutter is doing so much more.

How does it feel?

This is something you’d have to check for yourself. But we can show you how this looks!

Green is good.

This is a quick and dirty test application that displays timing information about the received events. Some takeaways from this:

  • Due to human limitations, it is next to impossible to produce a steady 1000Hz input rate for a full second. Moving the mouse left and right wastes precious milliseconds decelerating to accelerate again, even drawing the most perfect circle is too slow to have them need one event per millisecond. The devices are capable of shorter 1000Hz bursts though.
  • The separation between events (i.e. the time difference between the current and last events as received by the client) is predominantly sub-frame. There is only some larger separation when Mutter is busy putting images onscreen.
  • The event latency (time elapsed between emission by the hw/kernel and reception by the application) is <2ms in most cases. There are surely a few events that take a longer time to the application, but it is essentially noise.

Gamers (and other people that care about responsiveness) should notice this as “less janky”.

Didn’t drawing tablets have this before?

Yes and no. Mutter skipped motion compression altogether for drawing tablets, since the applications interested in these really preferred the extra events despite the drawbacks. With these changes in place, drawing tablet users will purely benefit of the improved performance.

Why so loooong

If you have been following GNOME Shell development, you might have heard about this change before. Why it took so long to have this merged?

The showstopper was probably what you would suspect the least: applications that are not handling events. If an application is not reading events in time (is temporarily blocking the main loop, frozen, slow, in a breakpoint, …), these events will queue up.

But this queue is not infinite, the client would eventually be shutdown by the compositor. With these input devices that could take a long… less than half a second. Clearly, there had to be a solution in place before we rolled this in.

There’s been some back and forth here, and several proposed solutions. The applied fix is robust, but unfortunately still temporary, a better solution is being proposed at the Wayland library level but it’s unlikely to be ready before GNOME 42. In the mean time , users can happily shake their input devices without thinking how many times a second is enough.

Until the next adventure!

State persistence for apps and sessions: Endless Orange Week

The second part of my project in Endless Orange Week was to look at state persistence for apps and sessions. At its core, this means providing

  • some way for apps to save and restore their state (such as which part of the UI you’re looking at, what’s selected, and unsaved content);
  • code in the session manager to save and restore the state of all applications, and a list of which applications are running, when shutting down/restarting/logging out/logging in/starting up.

Those two bullet points hide a lot of complexity, and it’s not surprising that I didn’t get particularly far in this project! It requires coordinated changes in a lot of components: GLib, GTK, gnome-session and applications themselves.

A lot of these changes have been prototyped or worked on before, by various people, but nothing has yet come together. In fact, gnome-session used to fully support restoring apps to a certain degree — before it was ported away from XSMP, it used to support saving the set of apps when closing a session, and re-starting those apps when starting the session again. It did not support restoring the state of each app, though, just the fact that it was running.

Breaking down the problem

Updating and building on the proposals and branches from others so far, we end up with:

  • Changes to GLib to add a ‘restart data’ property to GApplication, which allows the application to expose its current state to the session manager (to be saved), and which is initialised with the restored state from the session manager on startup. These build heavily on changes proposed by Bastien Nocera, but my tweaks to them are still pretty exploratory and not ready for review.
  • Code in GTK to support serialising the widget tree. This implements saving the state of the UI, and was prototyped by Matthias Clasen. My additions (also not yet ready for review) tie it in to the gnome-session API. Further work (but not very much of it) would have to be done to tie Matthias’ proposals into the final shape of the GLib API.
  • Preparatory cleanups of old code in gnome-session (this one is ready to review and hopefully merge!).
  • Work to re-support session restore in gnome-session. This is mostly ready, but needs tidying up and testing (which is likely to be a significant amount of work). It ties in with systemd transient scope work which Benjamin Berg and Iain Lane have been working on.

The final two pieces of the puzzle above took most of my week, and included a lot of time spent learning the architecture of gnome-session, and working out a bit of a protocol for apps to register for session restore and, in particular, for gnome-session to be able to re-launch apps the right way when restoring a session. That’s something which deserves a blog post of its own at some point in the future, once I’m sure I’ve got everything straight in my head.

In summary, there’s not been much progress in terms of creating merge requests. But the week was, I think, well spent: I’ve learned a lot about the shape of the problem, and feel like I have a better idea of how to split it up into chunks which it might be possible to land over time to get the feature working. Many thanks to Endless for giving me the opportunity to do so.

Certainly, I think this project is too big to easily do in a single GNOME release. There’s too much coordination required between different projects with different cadences and development resources.

The next step will be to land the preparatory gnome-session cleanups, and to discuss and land the GLib API so that people can start building with that.

December 06, 2021

New things in AppStream 0.15

On the road to AppStream 1.0, a lot of items from the long todo list have been done so far – only one major feature is remaining, external release descriptions, which is a tricky one to implement and specify. For AppStream 1.0 it needs to be present or be rejected though, as it would be a major change in how release data is handled in AppStream.

Besides 1.0 preparation work, the recent 0.15 release and the releases before it come with their very own large set of changes, that are worth a look and may be interesting for your application to support. But first, for a change that affects the implementation and not the XML format:

1. Completely rewritten caching code

Keeping all AppStream data in memory is expensive, especially if the data is huge (as on Debian and Ubuntu with their large repositories generated from desktop-entry files as well) and if processes using AppStream are long-running. The latter is more and more the case, not only does GNOME Software run in the background, KDE uses AppStream in KRunner and Phosh will use it too for reading form factor information. Therefore, AppStream via libappstream provides an on-disk cache that is memory-mapped, so data is only consuming RAM if we are actually doing anything with it.

Previously, AppStream used an LMDB-based cache in the background, with indices for fulltext search and other common search operations. This was a very fast solution, but also came with limitations, LMDB’s maximum key size of 511 bytes became a problem quite often, adjusting the maximum database size (since it has to be set at opening time) was annoyingly tricky, and building dedicated indices for each search operation was very inflexible. In addition to that, the caching code was changed multiple times in the past to allow system-wide metadata to be cached per-user, as some distributions didn’t (want to) build a system-wide cache and therefore ran into performance issues when XML was parsed repeatedly for generation of a temporary cache. In addition to all that, the cache was designed around the concept of “one cache for data from all sources”, which meant that we had to rebuild it entirely if just a small aspect changed, like a MetaInfo file being added to /usr/share/metainfo, which was very inefficient.

To shorten a long story, the old caching code was rewritten with the new concepts of caches not necessarily being system-wide and caches existing for more fine-grained groups of files in mind. The new caching code uses Richard Hughes’ excellent libxmlb internally for memory-mapped data storage. Unlike LMDB, libxmlb knows about the XML document model, so queries can be much more powerful and we do not need to build indices manually. The library is also already used by GNOME Software and fwupd for parsing of (refined) AppStream metadata, so it works quite well for that usecase. As a result, search queries via libappstream are now a bit slower (very much depends on the query, roughly 20% on average), but can be mmuch more powerful. The caching code is a lot more robust, which should speed up startup time of applications. And in addition to all of that, the AsPool class has gained a flag to allow it to monitor AppStream source data for changes and refresh the cache fully automatically and transparently in the background.

All software written against the previous version of the libappstream library should continue to work with the new caching code, but to make use of some of the new features, software using it may need adjustments. A lot of methods have been deprecated too now.

2. Experimental compose support

Compiling MetaInfo and other metadata into AppStream collection metadata, extracting icons, language information, refining data and caching media is an involved process. The appstream-generator tool does this very well for data from Linux distribution sources, but the tool is also pretty “heavyweight” with lots of knobs to adjust, an underlying database and a complex algorithm for icon extraction. Embedding it into other tools via anything else but its command-line API is also not easy (due to D’s GC initialization, and because it was never written with that feature in mind). Sometimes a simpler tool is all you need, so the libappstream-compose library as well as appstreamcli compose are being developed at the moment. The library contains building blocks for developing a tool like appstream-generator while the cli tool allows to simply extract metadata from any directory tree, which can be used by e.g. Flatpak. For this to work well, a lot of appstream-generator‘s D code is translated into plain C, so the implementation stays identical but the language changes.

Ultimately, the generator tool will use libappstream-compose for any general data refinement, and only implement things necessary to extract data from the archive of distributions. New applications (e.g. for new bundling systems and other purposes) can then use the same building blocks to implement new data generators similar to appstream-generator with ease, sharing much of the code that would be identical between implementations anyway.

2. Supporting user input controls

Want to advertise that your application supports touch input? Keyboard input? Has support for graphics tablets? Gamepads? Sure, nothing is easier than that with the new control relation item and supports relation kind (since 0.12.11 / 0.15.0, details):

<supports>
  <control>pointing</control>
  <control>keyboard</control>
  <control>touch</control>
  <control>tablet</control>
</supports>

3. Defining minimum display size requirements

Some applications are unusable below a certain window size, so you do not want to display them in a software center that is running on a device with a small screen, like a phone. In order to encode this information in a flexible way, AppStream now contains a display_length relation item to require or recommend a minimum (or maximum) display size that the described GUI application can work with. For example:

<requires>
  <display_length compare="ge">360</display_length>
</requires>

This will make the application require a display length greater or equal to 300 logical pixels. A logical pixel (also device independent pixel) is the amount of pixels that the application can draw in one direction. Since screens, especially phone screens but also screens on a desktop, can be rotated, the display_length value will be checked against the longest edge of a display by default (by explicitly specifying the shorter edge, this can be changed).

This feature is available since 0.13.0, details. See also Tobias Bernard’s blog entry on this topic.

4. Tags

This is a feature that was originally requested for the LVFS/fwupd, but one of the great things about AppStream is that we can take very project-specific ideas and generalize them so something comes out of them that is useful for many. The new tags tag allows people to tag components with an arbitrary namespaced string. This can be useful for project-internal organization of applications, as well as to convey certain additional properties to a software center, e.g. an application could mark itself as “featured” in a specific software center only. Metadata generators may also add their own tags to components to improve organization. AppStream gives no recommendations as to how these tags are to be interpreted except for them being a strictly optional feature. So any meaning is something clients and metadata authors need to negotiate. It therefore is a more specialized usecase of the already existing custom tag, and I expect it to be primarily useful within larger organizations that produce a lot of software components that need sorting. For example:

<tags>
  <tag namespace="lvfs">vendor-2021q1</tag>
  <tag namespace="plasma">featured</tag>
</tags>

This feature is available since 0.15.0, details.

5. MetaInfo Creator changes

The MetaInfo Creator (source) tool is a very simple web application that provides you with a form to fill out and will then generate MetaInfo XML to add to your project after you have answered all of its questions. It is an easy way for developers to add the required metadata without having to read the specification or any guides at all.

Recently, I added support for the new control and display_length tags, resolved a few minor issues and also added a button to instantly copy the generated output to clipboard so people can paste it into their project. If you want to create a new MetaInfo file, this tool is the best way to do it!

The creator tool will also not transfer any data out of your webbrowser, it is strictly a client-side application.

And that is about it for the most notable changes in AppStream land! Of course there is a lot more, additional tags for the LVFS and content rating have been added, lots of bugs have been squashed, the documentation has been refined a lot and the library has gained a lot of new API to make building software centers easier. Still, there is a lot to do and quite a few open feature requests too. Onwards to 1.0!

December 04, 2021

Pango updates

I was hoping to wrap up my Pango work after the previous update, but unexpected trouble came in from the side – Benjamin made GtkLabel more serious about height-for-width, and that uncovered some inaccuracies in Pango’s line wrapping implementation. Sometimes, we would make our lines shorter than necessary, and sometimes, we would let a hyphen leak out of the allotted width, creating an overlong line.

Fixing all this up took some serious effort,  but I think it was time well spent. One of the outcomes is that Pango now has APIs to serialize PangoLayout objects, and these are used  in the testsuite.

A Layout Editor

To get some (visual) insight into what was going wrong with line breaking, I wrote a quick utility called layout-editor. This is how it looks:

It lets you tweak all the parameters of a PangoLayout object and shows you the results of your changes. It can also show details about pango’s analysis of the text. And it can overlay extra information, such as extents of lines, runs, glyphs, caret positions, and more.

Since the layout editor also uses the serialization APIs to load and save your layouts, you can directly use it to inspect the test cases in Pango’s testsuite and create new ones. This should help improve test coverage, going forward.

If you want to gain more insight into what is happening inside Pango,  this tool might be for you.

Better Tabs

With this new tool in hands, I felt the urge to see if it can help for feature development too. One long-standing feature gap in Pango is the lack of support for tab stops with alignments other than left.

Amazingly, an almost 15 year old patch found in this bug still mostly applied, and worked, after some small adaptations. The new tool was indeed very helpful in working out some of the finer points.

If you always felt like you should be able to line up numbers properly at their decimal point, instead of picking a monospace font and hoping for the best, voila! now you can.

Wrapping up

All of this is available in Pango 1.50. Enjoy

December 03, 2021

A Quick PSA on Writing Portal-friendly Application Code

For various reasons, desktop applications sometimes need to know whether they are running under a sandbox made by a technology such as Flatpak or Snap. Some portal APIs, such as the file chooser dialog, are used transparently so that the application code doesn’t need to make any distinction between the sandboxed and unsandboxed cases, and if you ask me that’s a pretty impressive magic trick on its own. Other portal APIs such as the screencast one are used by both sandboxed and unsandboxed apps thanks to the secure architecture of Wayland compositors. But still other portal APIs are used conditionally depending on whether the app is running sandboxed; this is the case for the OpenURI portal used by Epiphany.

 

It’s also useful for applications to know when they are sandboxed in order to disable features that don’t work (yet) under Flatpak, as Epiphany does for web apps, or to access host resources via sandbox holes, as in the case of GNOME Builder.

 

Currently apps can check for the existence of a /.flatpak-info file to check if they are in a Flatpak sandbox, but this is not good enough to know if they should use portals! Snaps also use the same portals as Flatpaks, and for this reason xdg-desktop-portal has code to detect if the calling process is running as a Snap by checking cgroups membership. However since this check is not trivial it is not ideal for every app to keep a separate copy of it, so I submitted a patch to add API to libportal with some helper functions. Once that is merged apps can use it to easily check their sandboxed status.

 

As a side note, the /.flatpak-info mechanism for identifying a process as untrusted to a portal is perhaps not ideal. It was at the heart of a recent security vulnerability and it is used by WebKit’s UI process so it is treated as untrusted even when not running under Flatpak, which seems like a potential source of confusion/bugs. Perhaps an area for improvement if anyone has ideas?

 

I found this issue while working on Epiphany as part of the effort to improve the support for Progressive Web Apps in GNOME (which I just started this week!) and I’ll submit a patch shortly to make Epiphany’s sandbox detection Snap-friendly.

sizable news

For the upcoming GTK 4.6, we have overhauled a lot of the sizing infrastructure to make widgets fit even tighter and to make sure our sizing infrastructure actually does what it says.

halign/valign

When using the GtkWidget::halign or GtkWidget::valign properties, GTK 4.4 would look at the default size of the widget and then place the widget accordingly. This leaves a lot of extra space when one of the values was set to fill. In GTK 4.6, GTK will measure the size of the other dimension relative to the filled dimension. This makes the widget thinner but avoids extra space.

A centered label with empty space in GTK 4.4
A centered label with empty space in GTK 4.4

A centered label with no extra space in GTK 4.6
A centered label with no extra space in GTK 4.6

What if you like the old behavior?

If you do not use fill in either direction, the behavior will be as before. So update the other dimension to not be the default fill and you should get the old behavior back.

GtkBox

GtkBox has learned to assign size to widgets as needed. In GTK 4.4, size was always distributed equally among children that had the same default size. GTK 4.6 will query the children for their actual size to decide which child to distribute how much of the extra size to.

You can see this in the example, where the box was given enough space for 3, 4, 5 or 6 lines of text.

A left-aligned box in GTK 4.4
A left-aligned box in GTK 4.6

GtkLabel

As you could see above, GtkLabel also learned to properly wrap to any given number of lines. This allows labels to take a lot less widths as before, so they no longer take up empty space when they can just line-break.

xalign and halign

It’s worth pointing out that in a lot of cases applications used GtkWidget::halign = GTK_HALIGN_START; when they should have used GtkLabel::xalign = 0.0;. The first aligns the widget as far to the left as possible while the seconds aligns the text inside the assigned space to the left. So if your widgets suddenly look glued to the left edge, you might want to look into that.

GtkWindow

GtkWindow has learned how to adapt minimum size to the aspect ratio. So you can now resize your windows any way you like and they will never get too small, but they will always get as small as possible, no matter if you want to make them flat and wide or thin and high.

a new warning

While doing this work, we figured out that a few widgets do not conform to measuring requirements and added a new warning. So if you see something like:
Gtk-CRITICAL **: 00:48:33.319: gtk_widget_measure: assertion 'for_size >= minimum opposite size' failed: 23 >= 42
It means you have a widget that reports an minimum size for size -1 that is larger than the minimum size it reports for a different size, and that should never happen. You can use GTK_DEBUG=size-request and redirect to a file to find the offending widget. We also added code to work around any problems that warning, but it should be fixed nonetheless. After all, if a widget reports a wrong size, it’s likely it’s doing something wrong.

Text Editor Happenings

Text Editor has really been shaping up in the past couple weeks as we race towards getting things ready for GNOME 42.

Preferences Dialog

A screenshot of the preferences dialog We removed the preferences sidebar experiment because it was a bit clunky and none of the other core apps shared the design metaphor. Instead we’ve brought back a preferences dialog, albeit with an improved design. It builds on the previous GtkSourceStyleSchemePreview work but with a filtered set based on the current light/dark desktop setting.

Open Popover

A screenshot of the files popover The “Open” popover also got another round of design work based on using it for a while. The style is a bit slimmer and more to the point. It is also much more keyboard navigable now. It’s nice to be able to hit Ctrl+K, type a few characters, and either hit Return to open the first match or navigate through the list with arrows. Escape will return you back to the editor. Easy stuff.

Spaces Drawing

I added a GSetting for those that rely on visual spaces. Even though there is no UI for this at the moment you can still get what you want fairly easily using the gsettings command line tool.

flatpak run --command=gsettings org.gnome.TextEditor.Devel \
    set org.gnome.TextEditor draw-spaces \
    "['space','tab','trailing']"

Vim

If you’re feeling experimental you can even try my easter egg to test out the Vim emulation using GtkSourceVimIMContext. It probably will never be an advertised feature, but it’s there.

flatpak run --command=gsettings org.gnome.TextEditor.Devel \
    set org.gnome.TextEditor keybindings vim # or "default"

Recoloring

The most visual piece of work this week was in introducing recoloring support. It builds atop libadwaita and uses a CSS provider to override the colors in the theme. I expect there will be a recoloring API in the not-too distant future for libadwaita which will provide this for us.

When you select a style-scheme Text Editor will now use the colors defined in the scheme to alter how the entire application looks. For example, below are screenshots for a number of style-schemes both bundled with GtkSourceView and found on the internet.

A screenshot of a style scheme A screenshot of a style scheme
A screenshot of a style scheme A screenshot of a style scheme
A screenshot of a style scheme A screenshot of a style scheme
A screenshot of a style scheme A screenshot of a style scheme
A screenshot of a style scheme

A screenshot of the preferences And yes, the coloring is reflected throughout the entire interface.

As always, I tend to be slow to blog but quick to drivel over here.

2021-12-03 Friday.

  • Mail chew; re-amazed by the crypto.com video: a popular actor, an emotive sound-track, appeals to consumer risk taking; we have to be close to peak-nonsense - surely? "History is filled ..." also with egregious examples of speculative bubbles. Buying and selling URLs that don't necessarily have anything backing them sprains my brain; but then I'm still invested in Tulip bulbs: growth is more organic there. Then again - I'm not hearing 'buy crypto' from children yet, and the world is awash with cheap money so perhaps we have some time to the peak.
  • Georgie popped over with a ladder - oddly not ours; nice to have tea.
  • Call with Eloy & Cor, mail chew; 1:1 with Cor.

#21 Software Cleanup

Update on what happened across the GNOME project in the week from November 26 to December 03.

Core Apps and Libraries

Software

Lets you install and update applications and system extensions.

Philip Withnall says

Also in gnome-software, Phaedrus Leeds has fixed a long-standing issue where installing a flatpakref file wouldn’t use flatpak transactions (the modern flatpak API). This should fix a few bugs with flatpakrefs in gnome-software, and behaviour differences from the command line flatpak command.

Adrien Plazas has been refreshing the appearance of app reviews in gnome-software, implementing a design by Tobias Bernard

Calls

A phone dialer and call handler.

Evangelos announces

You can now use the keypad to send DTMF while on phosh’s lockscreen. This needed some DBus work on the Calls side and UI tweaks in libcall-ui. So if you have to interact with an automated calling assistant (“Please press 1 to buy a washing machine, please press 2 …") this should work too now.

GLib

The low-level core library that forms the basis for projects such as GTK and GNOME.

Philip Withnall says

Nishal Kulkarni and Emmanuel Fleury have been tidying up some old tests in GLib, ensuring those test results are machine readable, and making the code more maintainable in future

Circle Apps and Libraries

Obfuscate

Censor your private information on any image.

Bilal Elmoussaoui announces

Obfuscate 0.0.4 got released, it includes fixes of various bugs that were introduced during the GTK4 port and some improvements brought to you by Alexander Mikhaylenko. This also means the next TWIG entry of the built-in Shell screenshot/screencast won’t feature a development version of Obfuscate.

Gaphor

A simple UML and SysML modeling tool.

danyeaw says

Gaphor feature release version 2.7.0 is now out! We have added an extension for Sphinx to generate diagrams for your docs, support for Information Flows on connectors, lots of improvement to influence diagrams, improved autocomplete in our Python console, and usability updates.

Fragments

Easy to use BitTorrent client.

Felix announces

The new sessions stats dialog got merged. It displays information about the current session, e.g. how much data has been transferred in total, the current network load and more. I re-implemented desktop notification supports in the fragments-v2 branch. Fragments also automatically restores the last used remote connection now. This is useful if you’re using Fragments mainly as a client to control a Transmission server. And last but not least Maximiliano and I added support for the remove-all / pause-all torrents actions.

Third Party Projects

Bilal Elmoussaoui reports

During the same week, we managed to finish up an other GTK 4 / libadwaita port of Icon Library. The port was done by Maximiliano as part of the last Google Summer of Code as well. It also includes the traditional updated icons.

Bilal Elmoussaoui reports

The GTK 4 & libadwaita port of App Icon Preview done by Maximiliano during the last Google Summer of Code got released.

Junction

Lets you choose the application to open files and links.

sonnyp announces

Junction got a UI refresh and a new option to open the location with any application.

Documentation

Bilal Elmoussaoui reports

The documentation of GtkSourceView 5 was ported to gi-docgen and is available at gtksourceview5.

GNOME Shell Extensions

Simon Schneegans says

Fly-Pie, the marking-menu extension for GNOME Shell, has received a major update including proper support for touch screens and Wacom tablets, as well as a new clipboard menu. Watch the trailer: https://www.youtube.com/watch?v=BGXtckqhEIk

That’s all for this week!

See you next week, and be sure to stop by #thisweek:gnome.org with updates on your own projects!

December 02, 2021

2021-12-02 Thursday.

  • Catch-up with Miklos, Andras, COOL community call. Caught up with Simon, partner call. Got on with annual review preparations.

Files and GTK 4

When is everyone’s favorite cephalopod file browser getting ported to GTK 4?

Back a few years

Let’s start with some history. GTK 4 has been in development since 2016 and it’s been expected that the Files application would be ported, obviously.

In 2018, a Google Summer of Code project from Ernestas Kulik produced a port of Files to GTK 3.9x, the development version of what would become GTK 4. It included a port of the custom EelCanvas widget (used to implement the Files icon view).

Although it was not meant for general use, Ernestas’s port was very useful, both for the development of GTK 4 itself, as well as the preparation of the Files app for the future. Many compatible changes were applied to the master branch, which both improved the code design and laid the preparations for a later port to GTK 4.

Since then, GTK 4 has grown a framework of scalable list model views which are expected to revolutionize what content-browsing apps like Files can do.

Fast forward to today

GTK 4 has been stable for a year now and other GTK 4-ready dependencies are available now (libgnome-desktop-4 and libadwaita).

However, GTK 4 has changed a lot since 2018, so much that a rebase of the early port branch was no longer viable. Instead, I’ve been cherry-picking as much as possible from Ernestas’s branch and prepared a new roadmap with help from our community.

When is it happening?

The always safe reply is: when it’s ready.

The main development branch is already dedicated to this porting effort, and I’m focusing my personal contributions on that.

My desire is for the switch to happen before the GNOME 42.alpha release. If we miss that target, don’t expect a new version before GNOME 43.

How to help?

If you, like me, wish to see GTK 4 Files ready for GNOME 42, let’s join efforts!

Currently, the low-hanging fruits are from this ticket to stop using gtk_dialog_run(). In most cases it should be easy to replace with the “response” signal. Just pick a task from there!

I’d also like to get some help from developers who already have experience porting applications to GTK 4, namely with peer-reviewing the merge requests I’ve been pushing.

 

Nothing to show yet?

No. There isn’t a GTK 4 build yet.

However, some enhancements are already being prepared with GTK 4 in mind, such as a new scrollable pathbar and the thumbnail shadows.

Here is how they look like under GTK 3:

Runtime control of debug output: Endless Orange Week

Recently at Endless we had a week of focused working on projects which are not our day-to-day work. It was called ‘Endless Orange Week’, and everyone was encouraged to explore a topic of their choosing.

I chose to look at two projects, both of which included a D-Bus/API component. My thinking was that review of the new interfaces on each project might take a while, so it would make sense to have two projects running in parallel so I could switch between them when blocked.

I’m going to blog about the two projects separately, to avoid one mega-long post.

The first project was to add a D-Bus debug interface for applications. This would allow debug output from an application to be turned on and off at runtime, rather than just being set with a command line argument or environment variable when the application is first started.

This would allow users and developers to get debug output from long-running applications without having to restart them, as quite often restarting a process will destroy the state you were hoping to debug.

What I came up with is GDebugController, which is awaiting review in GLib now. It’s an interface, currently implemented by GDebugControllerDBus. When instantiated, GDebugControllerDBus creates a new D-Bus object and interface for controlling the debug output from the application. It hooks into the standard g_debug() message functions, and can be hooked into a custom log writer function if your application uses one of those.

It essentially exists to expose one D-Bus property and allow that to be hooked in to your log writer. It has to be a bit more complex than that, though, as it needs to be able to handle authorisation: checking that the D-Bus peer who’s requesting to enable debug output on your application is actually allowed to do so. For services in particular, this is important, as allowing any peer to enable debug output could count as a privilege escalation. They might be able to slow your process down due to the volume of debug output it produces; fill the disk up; or look at the outputted logs and see private information. GDebugControllerDBus has an authorize signal to support this, and it works quite similarly to the GDBusInterfaceSkeleton::g-authorize-method signal.

Using it in an application

Firstly, you need to wait for it to be reviewed and land in GLib. The API might change during review.

Once it’s landed, assuming nothing changes, you just need to create an instance of GDebugControllerDBus. It will create the D-Bus object and hook it all up. When peers change the debug level in your application, the default handler will call g_log_set_debug_enabled() which will change the behaviour of GLib’s default log writer function.

If you have a custom log writer function, you will need to change it to check g_log_get_debug_enabled() and output debug messages if it’s true.

Using it in a service

Using it in a service will typically involve hooking up authorisation. I’ve implemented support for it in libgsystemservice, so that it will be enabled for any user of libgsystemservice after version 0.2.0.

To use polkit for authorisation, set the GssService:debug-controller-action-id property to the ID of the polkit action you want to use for authorising enabling/disabling debug mode. libgsystemservice will handle the polkit checks using that. Here’s an example.

If that property is not set, a default policy will be used, where debug requests will be accepted unconditionally if your service is running on the session bus, and rejected unconditionally if it’s running on the system bus. The thinking is that there’s no security boundary on the session bus (all peers are equally trusted), whereas there are a lot of security boundaries on the system bus so libgsystemservice is best to fail closed and force you to write your own security policy.

That’s it! Reviews and feedback welcome. Many thanks to Endless for running this week and actively encouraging everyone to make use of it.

November 29, 2021

Firmware “Best Known Configuration” in fwupd

I’ve just deployed some new functionality to the LVFS adding support for component <tag>s. These are used by server vendors to identify a known-working (or commercially supported) set of firmware on the machine. This is currently opt-in for each vendor to avoid the UI clutter on the components view, and so if you’re a vendor reading this post and realize you want this feature, let me know and it’s two clicks on the admin panel.

The idea is that when provisioning the machine, we can set HostBkc=vendor-2021q1 in /etc/fwupd/daemon.conf and then any invocation of fwupdmgr sync-bkc will install or downgrade firmware on all compatible devices (UEFI, RAID, network adapter, & SAS HBA etc.) to make the system match a compatible set. This allows two things:

  • Factory recovery where a system in the field has been upgraded
  • Ensuring a consistent set of vendor-tested firmware for a specific workload

The tags are either assigned in the archive firmware.metainfo.xml file or added post-upload on the LVFS and are then included in the public AppStream metadata. A single firmware can be marked with multiple tags, and tags can be duplicated for different firmwares. This would allow a server vendor to say “this set of firmware has been tested as a set for workload A, and this other set of firmware has been tested for workload B” which is somewhat odd for us consumer-types, but seems to be pretty normal for enterprise deployments.

As a bonus feature, updating or downgrading firmware away from the “Best Known Configuration” is allowed, but we’ll show a semi-scary warning. Using fwupdmgr sync-bkc will undo any manual changes and bring the machine back to the BKC. Needless to say fwupd will not ship with a configured BKC.

We’ll include this somewhat-niche-but-required feature with fwupd 1.7.3 which will hopefully be released before Christmas. Questions and comments welcome.

November 25, 2021

CMSes & static site generators: why I (still) chose WordPress for my business websites

For many years, until 2021, the idéemarque* website was my own static HTML hand-written codebase, which had the advantage of performance and flexibility (vs “what a theme dictates”), but was also impossible to scale, because it had a bus factor of 1 and a pain level over 9000. I even had it version-controlled in Git all the way back to 2014 (back when I finally joined the Git masochists sect). I was the only person in the world who could maintain it or contribute to it, because, quite frankly, you need to reach geek level 30+ to enter that dungeon, while most people, including new generations, don’t know how to use computers.

Pictured: How I felt whenever I had to make changes to my static website.

I spent time evaluating various alternatives to “coding everything by hand”, including Hugo and Publii (I’ll spare you all the framework-style templating systems turbonerd crap like Bootstrap, Smarty, Django, etc.). Hugo and Publii are very cool conceptually, and would work wonders for a casual geek’s blog, but there are a number of problems they cannot address conceptually, in my view:

  • Not advanced and flexible enough for me to do “anything” easily (oh you want to integrate XYZ dynamic features? Yeah, let’s see how well you paint yourself into that corner)
  • Relies on their own themes that I can’t be bothered to learn hacking (and I don’t want to be hiring a dev specialized in those technologies to do it for me) just to be able to accomplish my vision (“I want it to look just like that!“). It’s easy to make a nice-looking hello-world website if you fit within the theme’s planned usecases, but as soon as you start saying “I want every core page to have a unique layout depending on the contents” and “I want the front page to look & behave differently from all the rest”, you run into limitations pretty quickly and say “Screw this, if I’m going to start hacking this thing, I’m no better off than writing my own custom website codebase myself.”
  • They are arguably designed and best suited for the “one user” usecase. Collaborative editing and permissions management? Not happening.
  • Nobody but turbonerds has the skills to understand and manage a static site generator. Most people can’t be bothered to handle files and folders. They live in the browser, and simply giving them a log-in to your site is the only way I can see to lower the barriers to entry among your team.

As much as we geeks love to hate WordPress and the bloat it represents, it is pretty much the standard website building platform that is visibly thriving, and that we know will still be Free & Open-Source and available ten years from now; and for all its warts, with enough experience and geekdom you can tweak and harden it into something fairly reliable and somewhat secure (the fact that automatic updates are now available for both the core and extensions helps; yes, it makes me nervous to think that things may change and possibly break on their own, but you can’t afford to have an un-patched website nowadays, and I think the security benefits of automatic updates outweigh the theoretical compatibility worries).

Combined with the new Gutenberg editing experience, some themes out there are also flexible enough to easily lay out complex pages without feeling like I’m running into limitations all the time.

Pictured: me deploying WordPress for my mostly-static sites and trying to make it fast.

Not everything is perfect of course. As of 2021, on the performance front, getting consistent and reliable caching working with SuperCache is a mindboggling experience, full of “mandelbugs” (like this one); in my case, each of my websites has at least some (or all) of the caching behavior not working (whether it is some pages never being able to generate cache files, or the cached files not being retained, no matter what you do and what combination of voodoo incantation and settings you use), but maybe someday someone will complete a heavy round of refactoring to improve the situation (maybe you can help there?) and things will Just Work™. But for now, I guess I’ll live with that.

All in all, it is only from 2019 onwards, after much research (and much technological progress in general), that I found myself with enough tooling to make this work in a way that would meet my expectations of design & workflow flexibility, and therefore feel confident enough that this will be my long-term solution for a particular type/segment of my websites. My personal website (of which this blog is only a subset) still is hand-coded, however, because it “does the job.”

Years ago, someone once told me that whenever someone in your team decides to write your company’s website from scratch (or using some templating system), they “inevitably end up reimplementing WordPress… poorly.”

So yeah. We’re using WordPress.


*: idéemarque is the first and only Free & Open-Source branding agency that contributes to the desktop Linux landscape on a daily basis, because that's what I do and I'm already in too deep. Or, as an academic would say, I'm just "unreasonably persistent."

November 24, 2021

On Flatpak disk usage and deduplication

There is a blog post doing the rounds asserting that Flatpak Is Not The Future. The post is really long, and it seems unlikely that I and the author will ever agree on this topic, so I’m only going to talk about a couple of paragraphs about disk usage and sharing of runtimes between apps which caught my eye. This is highly relevant to my day job because all apps on Endless OS are Flatpaks—for example, the English downloadable version has 58 Flatpak apps pre-installed, and 13 runtimes—and I’ve had and answered some of the same questions discussed in the post.

They claim that they deduplicate runtimes. I question how much can really be shared between different branches when everything is recompiled.

This question is really easy to answer using du, which does not double-count files which are hardlinked together. Let’s compare the 20.08 and 21.08 versions of the freedesktop runtime:

wjt@camille:~$ du -sh /var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/20.08
674M	/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/20.08
wjt@camille:~$ du -sh /var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08
498M	/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08
wjt@camille:~$ du -sh /var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/20.08 /var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08
674M	/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/20.08
385M	/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08
wjt@camille:~$ echo $(( 498 - 385 ))                                                                                                                                                
113

113 MB (out of 498 MB for the smaller, more up-to-date 21.08 runtime) is shared between these two runtimes.

How about the GNOME 41 runtime, which is derived from the 21.08 freedesktop runtime?

wjt@camille:~$ du -sh /var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08                                                                                                
498M	/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08
wjt@camille:~$ du -sh /var/lib/flatpak/runtime/org.gnome.Platform/x86_64/41                                                                                                
715M	/var/lib/flatpak/runtime/org.gnome.Platform/x86_64/41
wjt@camille:~$ du -sh /var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08 /var/lib/flatpak/runtime/org.gnome.Platform/x86_64/41
498M	/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/21.08
327M	/var/lib/flatpak/runtime/org.gnome.Platform/x86_64/41
wjt@camille:~$ echo $(( 715 - 327 ))                                                                                                                                                
388

388 MB (out of 715 MB) of the GNOME 41 runtime is shared with the 21.08 runtime.

I can’t imagine what system updates will be like in the future when you have a few dozen apps storing tens of gigabytes of runtimes that all want to be kept up to date.

There is no need to imagine! I have 163 Flatpak apps on my Endless OS system. Let’s see how many runtimes I have, how big they are, and how many apps use each one:

wjt@camille:~$ flatpak list --app --columns=runtime | sort | uniq -c | wc -l
18
wjt@camille:~$ flatpak list --app --columns=runtime | sort | uniq -c | sort -n
      1 com.endlessm.apps.Platform/x86_64/6
      1 org.freedesktop.Platform/x86_64/18.08
      1 org.gnome.Platform/x86_64/3.34
      1 org.gnome.Sdk/x86_64/41
      1 org.kde.Platform/x86_64/5.14
      2 com.endlessm.Platform/x86_64/eos3.2
      2 org.gnome.Platform/x86_64/3.28
      3 org.freedesktop.Platform/x86_64/19.08
      3 org.freedesktop.Sdk/x86_64/21.08
      3 org.gnome.Platform/x86_64/3.38
      3 org.kde.Platform/x86_64/5.15-21.08
      5 org.gnome.Platform/x86_64/3.36
      9 org.kde.Platform/x86_64/5.15
     10 org.freedesktop.Platform/x86_64/20.08
     24 com.endlessm.apps.Platform/x86_64/5
     28 org.freedesktop.Platform/x86_64/21.08
     30 org.gnome.Platform/x86_64/40
     36 org.gnome.Platform/x86_64/41
wjt@camille:~$ cd /var/lib/flatpak/runtime; flatpak list --app --columns=runtime | sort | uniq | xargs du -sh --total
918M	com.endlessm.apps.Platform/x86_64/5
907M	com.endlessm.apps.Platform/x86_64/6
2.0G	com.endlessm.Platform/x86_64/eos3.2
632M	org.freedesktop.Platform/x86_64/18.08
211M	org.freedesktop.Platform/x86_64/19.08
569M	org.freedesktop.Platform/x86_64/20.08
385M	org.freedesktop.Platform/x86_64/21.08
782M	org.freedesktop.Sdk/x86_64/21.08
26M	org.gnome.Platform/x86_64/3.28
329M	org.gnome.Platform/x86_64/3.34
264M	org.gnome.Platform/x86_64/3.36
263M	org.gnome.Platform/x86_64/3.38
198M	org.gnome.Platform/x86_64/40
277M	org.gnome.Platform/x86_64/41
264M	org.gnome.Sdk/x86_64/41
436M	org.kde.Platform/x86_64/5.14
231M	org.kde.Platform/x86_64/5.15
215M	org.kde.Platform/x86_64/5.15-21.08
8.7G	total

I have 18 runtimes, totalling 8.7 GB of storage (deduplicated), not “tens of gigabytes”. The top 5 most-used runtimes on my system cover 128 of the 163 apps. (I am ignoring the .Locale extensions of each runtime: the English and French translations of the 21.08 runtime total 17 MB, compared to 498 MB for the runtime itself, so I think this is a reasonable simplification for rough numbers.) As for updates? GNOME Software applies them automatically and silently. I don’t think about them at all.

People may disagree about whether the numbers above are large or small, compared to the upsides that Flatpak does or does not bring. But the numbers themselves are readily accessible, as is much of the past and ongoing work that has gone into making them as small/large as they are.

Personally, I think the trade-off is absolutely worth it for me and for Endless OS users, particularly since going all-in on Flatpak means that the base, immutable Endless OS install is just 4.2 GB. Of course there is room for improvement, and years ago I wrote a quick hack to help study exactly which files would ideally be shared between two runtimes but are not. At the time, the primary cause was non-reproducible builds. Since then, the Flatpak ecosystem has moved over to Buildstream which should help a lot, though I haven’t rerun the experiments except for what you see above. Automated statistics about apps using obsolete runtimes might be useful for the Flathub community, as might automated runtime updates, and some further work on understanding if and how the derived runtimes (GNOME & KDE) could share more with the freedesktop runtime version they are based on. And, would widespread use of filesystems that support block-level deduplication (like btrfs) help?

Toolbx is now on Matrix

Toolbx now has its own room on matrix.org. Point your Matrix clients to #toolbx:matrix.org and join the conversation.

We are working on setting up an IRC bridge with Libera.Chat but that will take a few more months as we go through the process to register our project channel.

November 21, 2021

Pixel Sites

I’ve created a couple of minisites for key OS components, built using no frameworks, but plain CSS. Just having CSS grid and variables made it viable for me to avoid using frameworks recently. Having includes/imports one wouldn’t even need Jekyll.

The founding stone on all of these is the pixel art, which is now becoming my favorite art form.

Flatpak Fleet Comander Toolbox Zbus

If you maintain an upstream OS component and are looking to replace a wiki or a markdown readme with a simple site, I’ve created a template to get you started quickly.

November 20, 2021

Flatseal 1.7.5

A new Flatseal release is out 🥳🎉, and it comes with subtle visual improvements, a few bugs fixes, one more permission and a big quality of life improvement.

Starting with the visuals, @BrainBlasted replaced the custom widgets, used in the applications list, for proper libhandy’s widgets. Plus, he fixed a small styling detail to make applications icons look sharper!

This change results in more consistent visuals and less custom code for me to maintain 😊

On the permissions side of things, @Arxcis added support for  the per-app-dev-shm permission, which was added to Flatpak a few releases ago.  Also, I extended the Other files subsection to allow negated filesystem overrides, e.g. !home.

Moving on to quality of life improvements, I took the time to make the UI fully usable with keyboard input. For some of us, who prefer the keyboard, this makes the UI faster to navigate. For other people, it makes Flatseal accessible for the first time. Thanks to @sophie-h for reminding me of this 🙌

With a good combination of shortcuts and mnemonics Flatseal has finally become keyboard friendly. Still far from perfect, but it’s the perfect start.

On the bug fixing front, @Arxcis fixed an issue that prevented users from overriding originally-negated permissions, and I fixed a couple more that caused undefined values to appear in override files. Although these were very rare, both issues were present since the original version of Flatseal.

Additionally, by popular demand, applications are now sorted by the application’s name 😅

Last but never least, thanks to @AsciiWolf, @ovari, @cho2, @Vistaus, @BigmenPixel0 and @eson57 for keeping their translations up to date, and to @TheEvilSkeleton and @usnotv for new French and Turkish translations, respectively.

November 19, 2021

Fair Weather Friends

Today I released libgweather-3.90.0, the first developers snapshot of GWeather 4:

Behold! A project logo

This release is mostly meant to be used as a target for porting existing code to the new API, and verifying that everything works as it should.

The major changes from GWeather-3.0 are:

  • the GTK3 widgets have gone to a farm up state, so you’ll have to write your own UI for searching locations
  • GWeatherLocation is a GObject type, so you can use it with GListModel and friends, which should help with the point above
  • the deprecated API has been removed
  • the API that will be part of GWeather 4.0 will be stable, and regular API/ABI stability guarantees will apply

If you are using libgweather in your application, you should head over to the migration guide and check out what changed.

Ideally, there are still things that need to be cleaned up in the GWeather API, for instance:

  • GWeatherTimezone parses the tzdata file directly, which comes with its own set of issues, like having to track whether the time zone database has changed or not; we should use GTimeZone instead, but the API provided by the two types do not match entirely. I need to check the current users of that API, and if possible, just drop the whole type.
  • GWeatherInfo has a bunch of getter functions that return the bare values and that can fail, and additional getter functions that always return a formatted string, and cannot fail; it’s not a great API.
  • GWeatherLocation returns the localised names by default, and has additional getters for the “English” (really: POSIX C locale) names.

If you encounter issues when porting, please: file an issue on GitLab.

November 18, 2021

FCC unlock procedure updates in ModemManager 1.18.4

If you own a laptop (Dell, HP, Lenovo) with a WWAN module, it is very likely that the modules are FCC-locked on every boot, and the special FCC unlock procedure needs to be run before they can be used.

Until ModemManager 1.18.2, the procedure was automatically run for the FCC unlock procedures we knew about, but this will no longer happen. Once 1.18.4 is out, the procedure will need to be explicitly enabled by each user, under their own responsibility, or otherwise implicitly enabled after installing an official FCC unlock tool provided by the manufacturer itself.

See a full description of the rationale behind this change in the ModemManager documentation site and the suggested code changes in the gitlab merge request.

If you want to enable the ModemManager provided unofficial FCC unlock tools once you have installed 1.18.4, run (assuming sysconfdir=/etc and datadir=/usr/share) this command (*):

sudo ln -sft /etc/ModemManager/fcc-unlock.d /usr/share/ModemManager/fcc-unlock.available.d/*

The user-enabled tools in /etc should not be removed during package upgrades, so this should be a one-time setup.

(*) Updated to have one single command instead of a for loop; thanks heftig!

Introducing GNOME Crosswords

GNOME Crosswords

Howdy folks! I want to announce a game for GNOME that I’ve been working on for a few months.

I’ve always enjoyed solving Crossword puzzles. It’s something I grew up doing as a kid, and we continue to do them as a family at the dinner table at night. I’ve wanted to try my hand at writing crosswords for a while, but there isn’t really a good tool available for doing so, and certainly no free software ones that work well with a recent GNOME release. I recently bought myself a lovely new Fedora-loaded Lenovo, and after it arrived, I thought I’d take a shot at writing such a tool.

Over the past four months or so I managed to get something worth releasing. The code is available here. It should build on relatively recent Linux distributions, though it does need libadwaita from git (toasts!). I also put together a flatpak file for testing here (no repo yet, as getting that set up defeated me). Once I’m more confident that the puzzles are solvable and fun I plan to publish it to flathub.

A dog's day
Non-traditional grid
Guardian cryptic No 28,605
The Guardian Daily Cryptic with reveal answers enabled

Features:

It’s still early, but it already has some fun features:

  • Puzzle Sets. The heart of the game is the Puzzle Set. It’s a collection of crossword puzzles that are tied together by a theme. Solving a puzzle unlocks more puzzles. I currently have one puzzle set (“Cats and Dogs”) with nine puzzles in it, but I have a few more puzzle sets planned. It contains mostly traditional puzzles, but I threw in a cryptic to keep people on their toes.
  • Nontraditional shapes and styles: I wanted to make something a bit little more whimsical and fun, as well as the more traditional puzzle grids. So I added support for colors and shapes as well. My son had fun doing pixel art to create some of the grids.
  • Reveal mistakes: For when you get stuck! It also supports checksums for puzzles that don’t include the solution.
  • Scalable grid: Currently the UI only exposes four sizes, but we have all the pieces to scale crosswords to different sizes.
  • Support for the .ipuz spec: This spec supports a ton of things, and I don’t support it fully yet, but most of the crossword part of the spec is included. There aren’t a ton of .ipuz files floating around, but you can use puzzlepull to download the Guardian Daily puzzle if you want to try some other examples.
Puzzle Set
The first Puzzle Set

Crossword Editor

GNOME Crosswords Editor

As part of building this app, I realized that creating grids was as big a part of the app as writing the actual game itself. To facilitate that, I started writing a crossword editor as well. It’s in the early stages, but it already has one of the most important features: a tool to create the initial grid. Making puzzles that fit well together is surprisingly hard. To make it easier, I wrote a crossword solver that quickly suggests words to fill in the grid. I’m proud of the design – it’s able to efficiently suggest options out of a list of 500K words really quickly (<1 μs on my machine). I was able to use it to build an autofill dialog that can recursively fill in a section of the puzzle when making a grid.

I still have more work to do on the editor and it’s clear that the autofill dialog isn’t a panacea, but it helped me figure out out some tricky corners. Here’s a video of the autofill dialog in action:

Thanks

I especially want to thank Rosanna and my kids for play-testing this and suggesting clues, as well as their patience while I was writing it. Thanks also to Federico for giving great advice, great code, and for being a star. Matthias for helping me relearn GTK and explaining GtkIMContext. Also, the example code in GNOME Builder was immensely helpful for getting this started.

What’s next?

There are a ton of features I’d like to add to this game. It really needs printing support, which should be relatively easy. I’d also love to see it get internationalized (and not just translated) – are crosswords in non-Latin languages a thing? And I’ve seen enough of Benjamin‘s GUADEC presentations over the years to know GTK can do something cooler than popup a dialog when you finish a crossword.

But the most important thing is that the game needs to be fun! For that, we need more puzzles and the existing puzzles need to be better. If you’re interested in joining me in creating a good set of puzzles for Linux, try the game out and let me know.

November 17, 2021

Status update, November 2021

I am impressed with the well-deserved rise of Sourcehut, a minimalist and open source alternative to Github and Gitlab. I like their unbiased performance comparison with other JavaScript-heavy Git forges. I am impressed by their substantial contributions to Free Software. And I like that the main developers, Drew DeVault and Simon Ser, both post monthly status update blog posts on their respective blogs.

I miss blog posts.

So I am unashamedly copying the format. I am mostly not paid to work on Free Software but sometimes I am so the length of the report will vary wildly.

This month I got a little more Codethink time to work on openqa.gnome.org (shout out Javier Jardón for getting me that time). Status report here.

image

I spoke at the first ever PackagingCon to spread the good word about Freedesktop SDK and BuildStream.

As always, I did a little review and issue triage for Tracker and Tracker Miners.

And I have been spending time working on an audio effect. More about that in another post.

open source is flexible

I had as main objective when I started my Coding Experience(CE) to get to grips with C or C++ since I am convinced that understanding one or both languages will help me become a better developer. Cog is developed in C which explained my excitement when I was introduced to the project. The first couple of tasks assigned to me were challenging but quite beginner-friendly.

Like it usually happens to many developers, I got stuck on an issue. After weeks of working on it, I couldn’t complete it. My mentor and I had a couple of meetings/coding sessions which helped me move ahead though not to the point of finishing the work. I could feel that there was a knowledge gap I had to bridge in C which studies and practice hadn’t given me that ability yet. Cutting the long story short I got really exhausted and anxious and suggested to my mentor that we move to something else and revisit this issue later.

After a couple of days, I was presented with a new program that can help me make the most of the CE. It turns out I will be moving back to contributing actively on GJS since there was good progress when I previously contributed to it. The only difference is most of my contributions will be in C++ and will probably include more core stuff.

Most if not all open source communities work to help contributors stay motivated and to keep making progress. For this reason they have very flexible methods of working. It’s a more free culture than you’ll find when building proprietary software. It’s very easy to find situations where a couple of contributors sit down to take their time and come up with a plan that makes the environment more conducive for new contributors. GNOME does this, Igalia and Mozilla too based on my interactions. It makes sense to mention that not everyone gets the opportunity of venturing into open source through Outreachy hence I will be talking later about other opportunities in open source for beginners and a handful of success stories I have come across.

This blog post can be considered a reason why you can start your software development career in open source. You just need to find an organization that meets your needs. By the way Cog 0.12 is soon be released. Release notes will be available here.

Thanks for reading and I will love to hear how flexible you think open source is in the comments and how this has helped you make progress. Please do not forget to like, share and subscribe and let’s connect on twitter and linkedIn.

November 16, 2021

Endless Orange Week: GNOME on WSL

The week of 8th–12th November was Endless Orange Week, a program where the entire Endless OS Foundation team engaged in projects designed to grow our collective learning related to our skills, work and mission. My project was to explore running a complete GNOME desktop in a window on Windows, via Windows Subsystem for Linux.

Screenshot of Windows Remote Desktop Connection window, containing a GNOME desktop running Hack and GNOME Setttings, in turn showing Virtualization: wsl

Why?!

We’ve long faced the challenge of getting Endless OS into the hands of existing PC users, whether to use it themselves or to try it out with a view to a larger deployment. Most people don’t know what an OS is, and even if they have a spare PC find the process of replacing the OS technically challenging. Over the years, we’ve tried various approaches: live USBs, an ultra-simple standalone installer (as seen in GNOME OS), dual-booting with Windows (with a 3-click installer app), virtual machine images, and so on. These have been modestly successful – 5% of our download users are using a dual-boot system, for example – but there’s still room for improvement. (I have a personal interest in this problem space because it’s what I joined Endless to work on in 2016!)

In the last few years, it’s become possible to run Linux executables on Windows, using Windows Subsystem for Linux (WSL). Installing the Debian app from the Windows Store gives you a command-line environment which works pretty much like a normal Debian system, running atop a Microsoft-supplied Linux kernel. Most recently, unmodified applications can present X11 or Wayland windows and play audio through PulseAudio; behind the scenes, a Microsoft-supplied distribution with their branches of Weston and PulseAudio exports each Wayland or X11 window & its audio over RDP to the host system, where it appears as a free-standing window like any other. There is also support upstream in Mesa for using the host system’s GPU, with DirectX commands forwarded to the host via a miraculous kernel interface.

This raises an interesting question: rather than individual apps installed and launched from a command line, could the whole desktop be run as a window, packaged up into an easy-to-use launcher, and published in the Windows Store? If so, this would be a nice improvement on the other installation methods we’ve tried to date!

Proofs of concept

I spent last week researching this. Yes, you can indeed run a complete GNOME desktop under WSL. I tried two approaches, which each have strengths and weaknesses. I worked with Debian Bookworm, which has GNOME 41 and an up-to-date Mesa with the Direct3D backend. Imagine telling someone 20 years ago that Debian would one day include development headers for DirectX in the main repository!

I packaged up my collection of scripts and hacks into something which can build a suitable rootfs to import into WSL and launch either demo with a single command. There may be things that I got working in my “pet” container that don’t quite work in this replicable “cattle” container, but I did my best.

GNOME desktop as X11 app

GNOME Shell can be run as a so-called “nested session”, with the entire desktop appearing as a window inside your existing session. Thanks to my team-mate Georges Stavracas for his help understanding this mode, and particularly the surprising (to me) detail that the nested session can only be run as an X11 window, not a Wayland window, which explained some baffling errors I saw when I first tried to get this going.

Once you’ve got enough of the environment GNOME expects running (more on this below), you can indeed just run it with a carefully-crafted set of environment variables and command-line arguments, and it appears on your Windows system, resplendent with Weston’s window decorations:

GNOME desktop running a game, in a window on Windows

Apps can even emit sound over PulseAudio as normal, or at least they could once I fixed an edge case in Flatpak’s handling of the PulseAudio socket. It’s hard to show audio in a screenshot, but you can see the sounds being emitted by Sidetrack (the WebKitWebViewProcess) as well as Hack somewhere in the background (the python3 process), both of which are Flatpak apps, and the RDP sink as output.

So on the face of it this seems quite promising! But Shell’s nested mode is primarily intended for development, with the window size fixed at launch by an environment variable with DEBUG in its name.

I found WSLg to be quite fragile. WSLg’s Xwayland often fell over for unknown reasons. I had to go out of my way to install a newer Intel graphics driver than would automatically be used, to get the vGPU support needed for Mesa’s Direct3D backend to work. But having done this, on one of my machines, the driver would just crash with SIGILL – apparently the driver unconditionally uses AVX instructions even if the CPU doesn’t support them. On my higher-end machine, most apps worked fine, but Shell on this stack would display just a few frames and then hang. In both cases, I could work around the problem by forcing Mesa to use software rendering, but this means losing one of the key advantages of WSLg!

Another weird anecdote: using the D3D12 backend, the GTK demo app’s shadertoy demo works fine, but its gears demo doesn’t render anything – and nor does glxgears! Apparently D3D12 just doesn’t like gears⁈

Thanks to Daniel Stone at Collabora for his patient help navigating Mesa and D3D12 passthrough.

GNOME desktop exported over RDP

In the past few GNOME releases, it’s become possible to access the desktop remotely using RDP. This is Windows’ native remote-access protocol, and is also the mechanism used by WSLg to export windows and audio to the host.

So another approach is to launch GNOME Shell in its headless mode, and then explicitly connect to it with Windows’ RDP client. A nice touch in WSL is that, by the magic of binfmt_misc and an automatic mount of the host system’s drive, you can invoke Windows executables on the host from within the WSL environment, so a single launch script can bring up GNOME, then spawn the Windows RDP client on the host with the correct parameters. (This is how WSLg works too.)

Not pictured below are the ugly authentication and certificate warning dialogs during the connection flow:

GNOME desktop, accessed over RDP, showing GTK 4's Shadertoy GL demo

Here, GNOME Shell is (AFAICT) rendering using Mesa’s accelerated D3D12 backend, as are GL applications running on it (the GTK 4 Shadertoy demo). But in this model we lose WSLg’s PulseAudio forwarding, and its use of shared memory to send the pixel contents of the desktop to the client. Both of these are solvable problems, though. GNOME Remote Desktop uses the same RDP library, FreeRDP, as WSLg, and all the other supporting code on the Linux side is open-source. GNOME Remote Desktop uses Pipewire rather than PulseAudio, and Mutter rather than Weston, so WSLg’s RDP plugins for PulseAudio and Weston could not be used directly, but audio forwarding over RDP seems a desirable feature to support for normal remoting use-cases. Supporting the shared-memory transport for RDP in GNOME Remote Desktop is perhaps a harder sell, but in principle it could be done.

Just like the nested session, the dimensions of a headless GNOME Shell session are currently fixed on startup. But again I think this would be desirable to solve anyway: this already works well for regular virtual machines, and when connecting to Windows RDP servers.

Rough edges

When you start a WSL shell, PID 1 is an init process provided by WSL, and that’s pretty much all you have: no systemd, no D-Bus system or session bus, nothing. GNOME requires, at least, a functioning system and session bus with various services on them. So for this prototype I used genie, which launches systemd in its own PID namespace and gives you shells within. This works OK, once you change the default target to not try to bring up a full graphical session, disable features not supported by the WSL kernel, and deal with something trampling on WSLg’s X11 sockets. (I thought it is systemd-tmpfiles, but I tried masking the x11.conf file with no success, so I hacked around it for now.) It may be easier to manually launch the D-Bus system bus and session bus without systemd, and run gnome-session in its non-systemd mode, but I expect over time that running GNOME without a systemd user instance will be an increasingly obscure configuration.

Speaking of X11 sockets: both my demos launch GNOME Shell as a pure Wayland compositor, without X11 support. This is because Mutter requires the X11 socket directory to have the sticky bit set, for security reasons, and refuses to start Xwayland if this is not true. But on WSLg /tmp/.X11-unix is a symlink; it is not possible to set the sticky bits on symlinks, and Mutter uses lstat() to explicitly check the symlink’s permissions rather than its target. I think it would be safe to check the symlink’s target instead, provided that Mutter also checked that /tmp had the sticky bit (preventing the symlink from being replaced), but I haven’t fully thought this through.

WSL is non-trivial to set up. The first time you try to run a WSL distro installed from the Windows Store, you have to follow a link to a support article which tells you how to install WSL, which involves a trip deep into the Settings app followed by a download and reboot. As mentioned above, I also had issues with the vGPU support in Intel’s driver on both my systems, which I had to go out of my way to install in the first place, and WSLg’s Xwayland session was somewhat unstable. So I fear it may not be much easier for a non-technical user than our existing installation methods. Perhaps this will change over time.

GNOME Remote Desktop’s RDP backend needs some manual set-up at present. You have to manually generate a TLS key and certificate, set up a new username & password combo, and set the session to be read-write. You also have to arrange for the GNOME Keyring to be unlocked in your headless session, which is a nice chicken-and-egg problem. Once you’ve done all this (and remembered to install a PipeWire session manager in your minimal container) it works rather nicely, and I know that design and engineering work is ongoing to make the set-up easier.

Conclusions

Although I got the desktop running, and there are some obvious bits of follow-up work that could be done to make the experience better, I don’t think this is currently a viable approach for making it easier to try GNOME or Endless OS. There is too much manual set-up required; while it might be possible to bundle some of the Linux side of this into the WSL wrapper app, installing WSL itself is still quite cumbersome, if not exactly rocket science. The many moving parts are still rather new, and I hit various crashes and strange behaviour. Even with software rendering, the performance was fine on my relatively high-end developer laptop, but performance was pretty bad on my normal Windows machine, a lower-spec device that might be more representative of computers in general.

I do still think this general approach of running the desktop windowed in a container on a foreign OS is an interesting one to keep an eye on and re-evaluate periodically. Chrome OS is another potential target, since it also supports running arbitrary Linux containers with Wayland forwarding, though my understanding is that it also involves rather a lot of manual set-up and is not supported on managed devices or when parental controls are in use…

I was happy to experience first-hand the progress GNOME has made in supporting RDP. This kind of functionality may not be important to most GNOME developers and enthusiasts but it’s really important in some contexts. I used to work in an environment where I needed remote access to my desktop, and RDP was the only permitted protocol. Back in 2014, the tools to do this on my Linux system were truly dire, particularly if you want to access a normal desktop remotely rather than a virtualised desktop; by contrast, accessing my Windows system from a Windows, Linux or macOS client worked really well. GNOME Remote Desktop has made some big strides in the right direction, with better integration with the desktop and fewer fragile hacks. I’ll keep watching this space with interest.

WSL itself is also an impressive technical achievement, and the entire Linux side of it is free software. There is nice integration with the host system – for example, you can run Visual Studio Code on the host by running code in WSL, and everything works transparently.

On a personal level, I learnt many new things during the course of Endless Orange Week. Besides learning about WSL, I also learnt how to break on a syscall in gdb (catch syscall 16 for ioctl() on x86_64) and inspect the parameter registers; how Mesa chooses its backend (fun fact: most of the modules in /usr/lib/x86_64-linux-gnu/dri/ are hardlinks of one another); the importance of a PipeWire session manager; more about how PID and mount namespaces work; and so on. It was a nice change from my usual day-to-day work, and I think the research is valuable, even if it doesn’t immediately translate into a production project.

Calculator and GTK4


It was a long time since I last wrote, but important news coming up, so I thought it's time to post again.

The kind Christopher Davis has spent some time on porting Calculator to GTK4, a process which looks like complete to me know, with the merge into master happening fairly soon. This was a lot of work, given the framework changes, and would be nice to have some testing mileage on it, so I'm asking the curious people to check it out, and report any issues you may find.

Currently it is only available on the merge request branch, but it is fairly easy to try out using Builder. Thanks go out to the developers behind Builder+Flatpak for building up the whole ecosystem which makes development fairly easy without breaking the local environment, and without having to maintain a full JHBuild environment.

Looking at the changes in a bit more detail:

libadwaita instead of libhandy

With the introduction of libadwaita there were quite a few steps to migrate from libhandy, but fortunately the migration steps are well-described in libadwaita docs, so it was not really hard, except for a couple of trial and errors to get the preferences comboboxes getting to work due to model class changes.

gtk4 instead of gtk3

The steps are well-described in the case of GTK too, but the amount of changes to be done was overwhelming, so after attempting twice to do the full migration by going step by step (replacing deprecated APIs, migrating to APIs already existing in GTK3, etc) but failing badly, thankfully Christopher showed up with a rough port (creating several tasks to be fixed on the MR, which I could act upon). I helped wherever I could by testing and fixing here and there:

  • ported financial dialogs to fit the Human Interface Guidelines, resizing them to proper sizes, moving action buttons into headerbars, and other minor tweaks

  • given that GTK4 combobox doesn't support long models (and our currency selection is fairly long) as in "there is no scrolling for comboboxes", and GtkDropDown only supports plain models, not tree models (which we used for representing UnitCategory -> Unit selection) something had to be done, and I decided to split the conversion comboboxes into conversion category and conversion unit selectors, adding an additional GtkDropDown to select the unit category, reducing technical debt (keeping the units of both comboboxes in sync added some complexity) , and allowing us to use GtkDropDown for unit selection, which does make search in the unit selectors possible (of course search bar is only shown in case there are more than 10 elements to search from, there is no need to search in less than 10 units)


 

gtksourceview5 instead of gtksourceview4

Now, even this might not be visible for everyone, Calculator uses gtksourceview component for the calculator entry due to some convenience functions (like function name autocompletion, variable name autocompletion) the code had to be updated there too, and even though the migration steps are short here, it contains completion code changes, which is exactly what we are using.

Disclaimer

Important thing to note is that this is only a development version for now. libadwaita and gtksourceview are still moving targets (as we are fairly early in the GNOME 42 development cycle APIs might change, e.g. there was a change over the weekend in libadwaita breaking the build, fixed now), so breakage might happen.

Further plans

Search in the selectors works, but currently only direct text search for the full name, I absolutely want to support case-insensitive, match-anywhere, search-symbol-too, plus it would be great to add support for favorite currencies/units too, but none of these is blocking the GTK4 merge, but would be nice to have.

Another important development recently was the refactoring of currency conversion backend, which now should make the addition of new currency conversion sources (currently two hard-coded ones available) and enable/disable for any of them via code fairly easy. Taking this idea further adding a plugin system for enable/disable/implement new providers via libpeas would also be a nice thing, and would help in lots of areas.

If you would like to help in any of the above areas, or have other ideas, just drop me a note, report issues, comment on existing ones, let's improve this small utility a bit.

November 15, 2021

Toolbx: Red Hat is hiring a software engineer

The Desktop Team at Red Hat wants to hire a software engineer to work full-time on Toolbx (formerly known as Toolbox) with me, and hopefully go on to maintain it in the near future. You will be working upstream and downstream (Fedora and RHEL) to improve the developer and troubleshooting experience on OSTree-based Linux operating systems like Fedora Silverblue and CoreOS, and extend some of the benefits to even traditional package-based OSes like Fedora Workstation.

If you are excited to work across the different layers of a modern Linux operating system, with a focus on container and desktop technologies, and aren’t afraid of getting your hands dirty with C and Go, then please go ahead and apply. Toolbx is a relatively young project with a rapidly growing community, so you are sure to have a fun ride.

November 14, 2021

Endless Orange Week: Hack content creators platform (2)

The past Friday was the last day of the Endless Orange Week. It was a nice and fun experience, and even if I was not able to do as much as I wanted, we were able to make something that "works" in the Hack project.

The Hack Quest editor

The first step to have custom quests on the Hack app was to complete the Ink language support. We started to work on this some time ago, but never completed the functionality.

I worked on that the first three days, updating the ink library and building the missing pieces to be able to load quests from random paths. I've implemented that in a way that the Hack application is able to receive a path to a .ink file, and it's able to build and run the quets.

The Quests are not just the script, but they have some metadata, like title, subtitle, description, difficulty and the card image to show on the interface. To solve that I defined a "custom quest bundle format", that's bassically a folder with:

  • questId
  • quest.jpg
  • metadata.json
  • quest.ink

So I also added the functionality to import a bundle zip file and export with the quest information.

I created some command line options to use this new functionality:

  --play-ink=FULL_INK_FILE_PATH                 Start a custom ink quest.
  --import-quest=PATH_TO_BUNDLE_OR_INK_FILE     Import a custom ink quest.
  --export-quest=CUSTOM_QUEST_ID                Export a custom quest bundle.

Quest creation interface and the Inky Editor

The first idea was to try to provide a full quest creation experience in the app, but that was too much, so we decided to simplify the way to create quests and depend on the Inky editor external tool. Manuel Quiñones took some time to update the flatpak application with the latests ink version, so we can use to create custom quests.

The Inky editor provides help about the language, syntax highlighting and a simple way to test the script, so it's a nice tool. The main problem with this tool is that it doesn't provide a way to launch it with a file path so it's not possible to integrate with the Hack app.

So at the end, the Quest creation dialog is just a way to define the metadata and to select the Quest ink files from your filesystem. How the ink script is created is a decision to make for the content creator.

The future

We've no time to complete all we wanted to do, and I didn't create a new release, so this new functionality is still not there. But we'll try to do a release soon.

Simon is working on some interface improvements and also on a new tutorial Quest, so we can introduce the Custom Quest creation tool in the same app.

The Character editor

The other part of this week planning was the character editor. Joana did a really nice work designing the application, the initial assets and the user experience, but I had not too much time to work on the implementation. So I spent just one day working on this.

The main idea was to create a new independent app, and then provide a way to integrate with the Hack application and the custom Quest creation dialog. And it'll be a simple application so maybe it could be useful or interesting for other people, it's a fun way to play around and create random faces.

We just created the application Avatar Creator. I created a simple python Gtk4 application and worked a bit on the basic functionality. So right now it loads a list of svg assets and provide the 3x3 grid. You can click on a grid cell and then choose what basic image should go there.

I added the initial set of basic images, created by Joana, to create this funny robot faces, but the format is simple enough to extend with different "avatar libraries" in the future.

Right now it's also possible to export to png, so the app is functional, but it needs a bit more work.

My idea is to work a bit more in the following weeks, when I have some time, on weekends or holidays and at some point, publish it in flathub. And lets see if there are more developers interested on this app so it can grow.

The application is simple enough to be a good place for GNOME newcomers and it's also a fun project to work on. A simple toy app to create faces that could have some potential, some future ideas:

  • "Smart" random faces generator
  • Configurable grid: Maybe is interesting to make it bigger or smaller to play around
  • Programmed simple base image manipulations, like rotation, mirror, color
  • Animation creation, maybe be able to export to gif

The Endless Orange Week experience

This week was a really nice experience, because we were working in a "personal" chosen project, that we liked and without the day to day meetings, times schedules and other related work stuff.

But that was not all. In Endless we've different teams that work mostly isolated, because we're working on different fields, we've some overlapping, but we work day to day as small teams, and this week we were all using the same slack channel to show our progress, and it was nice.

Maybe now that we're not a big organization with a lot of workers, we can do something like this more often, it's always good to know more about other coworkers and to learn something that maybe it's not related with your main project, but it could be interesting.

I'm really happy that we did this Endless Orange Week, it's sad that it ended too soon, I'm waiting to learn from my coworkers what amazing things they do during this week and I'm looking forward the next year Orange Week!

November 13, 2021

Adventures with portals

This week (November 8th – 12th) is the Endless Orange Week, a program where the entire Endless team engages in projects designed to grow our collective learning related to our skills, work and mission.

My project for this program was improving XDG portals. I set myself out to work on the following problems:

  • Improve the ScreenCast portal by introducing a new feature to restore previous screencasts.
  • Add an portal-based audio access mechanism
  • Modernize libportal

Let’s have a look at what these features are, and what’s the progress.

Portal-based Screen Casting

One of the portals introduced for applications to capture the contents of a monitor or a window was the ScreenCast portal. This portal has gained some relevance, since it is the primary – and in most cases, the only – way to capture windows and monitors on Wayland. This is the mechanism used by OBS Studio, Chromium, Firefox, etc.

This portal has a well defined set of steps centered around “sessions”:

  1. Applications initiate the process by asking the ScreenCast portal to create a screencast session. The portal replies with a handler for this session
  2. Applications then configure this session. They set if they want monitors or windows or both; the way they’d like to receive cursor (metadata, embedded in each frame, or hidden); and whether they allow multiple sources or not. The portal replies acknowledging this configuration.
  3. Finally, applications start the screencast session. This is when a dialog shows up asking you to select a window or a monitor. The portal replies with a list of streams. Each stream has a corresponding PipeWire node, width and height, and position.

This process is repeated every time an application wants to screencast. It’s a robust series of steps, and has served us well so far, but having to select a monitor or window every time can be a frustrating experience.

For some use cases, this process is problematic. Take Steam’s recent introduction of PipeWire-based Remote Play: the whole purpose of this feature is to allow playing remotely, potentially without physical access to your computer. Evidently, in this case, showing a dialog to select a monitor is not going to work if the person is probably not in front of the machine.

This is where my new proposal to the ScreenCast portal comes in.

The mechanism proposed there is composed of two new properties: (i) a persist mode, where applications can tell the portal that they want to restore this screencast session later; and (ii) a restore token to restore a previous screencast session.

In summary, when configuring (step 2) a screencast session, applications can tell the portal “hey, I’d like to restore this session later”; in this case, after you select a monitor or window and start the stream (step 3), the portal will give the app what I called a restore token. Applications should store this token however they want (ideally using the platform’s preferred preferences systems, such as GSettings for GNOME).

Applications that have a restore token should use them when configuring the screencast session (step 2). The portal will receive this token, and try to restore the previous session’s windows and monitors. If that fails, e.g. when you changed monitors or the windows is not open, the selection dialog is presented again. From the application’s perpective, it doesn’t know (nor does it matter) if the previous session is restored or not, as the application will receive a list of streams and PipeWire nodes regardless of what it happens.

If you look closely, it is possible to endlessly restore the same session by passing both the token to restore a previous session, and asking the portal to restore it again later.

I was not confident of this mechanism when proposing it, but after implementing it on the GNOME portals, I realized this mechanism is actually really robust. It allows for very sophisticated features to be implemented by portal implementations without any additional property.

My initial implementation is merely a “Remember this decision” checkbox, purely to test this feature, so this will change soon. After discussing with peers both in the design and development fronts, a few ideas on how to manage these permissions came up:

  • Revoking these permissions after a reasonably long period of time – 6 months, or more, or less. That can help preventing applications to have access to a certain window or monitor forever.
  • Improve the indication of ongoing screencasts. GNOME currently shows an orange icon in the titlebar, but we’re considering other alternatives such as notifications when starting and stopping streams, adding a minimum visibility time to the indicator, etc.
  • Add a way to manage these permissions in GNOME Settings, either with new panel under the Privacy group, or a new section inside the Applications panel.

The goal behind these ideas is allow fine control over what is being shared with who, and when, without being annoying. There is a lot to do in this front, but I’m hopeful that most use cases will be covered.

And here it is, a proof-of-concept that this idea works:

Audio access

Another area that is a bit lacking in the portals front is device access. We currently have the Device portal, with which applications can ask for permission to access specific devices such as cameras, speakers, and microphones.

PipeWire has some support for this type of device access in place, but currently only for cameras. We need the same kind of access control for microphones and speakers, specially microphones, and that’s what I’ve been working on during the week.

I initially approached this by proposing a new Audio portal, which was basically a copy-pasted version of the Camera portal. The basics of these portals are:

  1. Applications request audio access, which queries permissions for using audio devices; applications should say whether they want to use speakers, or microphones, or both.
  2. Portals potentially ask you if you would allow that application to access these devices.
  3. Application gets a PipeWire connection with only the allowed devices exposed.

This is exactly how the Camera portal operates. Peer reviews, however, raised one very important point: there are situations where we can’t have separate PipeWire connections for cameras and microphones. So we had to come up with another solution that could satisfy these requirements.

In the end, after some rounds of discussions, we agreed on making this live in the Device portal. This is still under review, and things may change, but it seems to me that we found the best course of action with this last round of discussions.

What does that mean in terms of UX? Not much, I’m afraid, except that people would be able to have greater control over what sandboxed applications can access. You could, for example, prevent a proprietary app you don’t trust from accessing your cameras and microphones.

Modernizing libportal

libportal is a small library written to help application developers interact with portals without having to manually call the D-Bus APIs. Some of these D-Bus APIs can be quite verbose and complicated to deal with, and libportal abstracts that away in a nice and simple way.

libportal, however, currently relies on some tricky dance with headers to work with GTK3, GTK4, and Qt 5 without actually linking to these libraries. Sadly, this means libportal is not introspectable, which prevents it from being used in other languages such as JavaScript or Python.

I took part of this week to work on that. I started by cleaning up the build system (#52); then the next step was to split each toolkit-specific header into its own library that effectively links against the toolkit (#53). This finally allowed adding introspection to libportal and the GTK3 and GTK4 variants (#54). I also used this chance to rewrite libportal’s GTK4 demo app in JavaScript to exercise the language bindings.

At last, libportal’s CI now produces Flatpak bundles for the GTK3, GTK4, and Qt 5 test apps (#55). This should make it easier to ask for people to test new changes, since they can just download a Flatpak bundle and test it.

Conclusion

I think this was a successful week, there was significant progress in these fronts and half of these pull requests were merged already. I was hoping that the other ones could land before the week ends; sadly they didn’t, but we’re very close to that. In special, the screencast session restore work is just in a stone’s throw from landing!

Thanks Endless OS Foundation for allowing me to work on portals as part of the Endless Orange Week program!

Buy Me a Coffee at ko-fi.com

November 11, 2021

Record Live Multiple-Location Audio immediately in GNOME Gingerblue 2.0.1

GNOME Gingerblue 2.0.1 is available and builds/runs on GNOME 41 systems such as Fedora Core 35.

It supports immediate, live audio recording in compressed Xiph.org Ogg Vorbis encoded audio files stored in the private $HOME/Music/ directory from the microphone/input line on a computer or remote audio cards through USB connection through PipeWire (www.pipewire.org) with GStreamer (gstreamer.freedesktop.org) on Fedora Core 34 (getfedora.org) as well as XSPF 1.0 playlist stored in the private $HOME/Music/GNOME.xspf playlist of the previous, latest recording.

See the GNOME Gingerblue project (www.gingerblue.org) for screenshots, Fedora Core 35 x86_64 RPM package and GNU autoconf installation package (https://download.gnome.org/sources/gingerblue/2.0/gingerblue-2.0.1.tar.xz) for GNOME 41 systems and https://gitlab.gnome.org/ole/gingerblue.git for the GPLv3 source code in my GNOME Git repository.

Gingerblue music recording session screen. Click “Next” to begin session.

The default name of the musician is extracted from g_get_real_name(). You can edit the name of the musician and then click “Next” to continue ((or “Back” to start all over again) or “Finish” to skip the details).

Type the name of the musical song name. Click “Next” to continue ((or “Back” to start all over again) or “Finish” to skip any of the details).

Type the name of the musical instrument. The default instrument is “Guitar”. Click “Next” to continue ((or “Back” to start all over again) or “Finish” to skip any of the details).

Type the name of the audio line input. The default audio line input is “Mic” ( gst_pipeline_new("record_pipe") in GStreamer). Click “Next” to continue ((or “Back” to start all over again) or “Finish” to skip the details).

Enter the recording label. The default recording label is “GNOME” (Free label). Click “Next” to continue ((or “Back” to start all over again) or “Finish” to skip the details).

Enter the Computer. The default station label is a Fully-Qualified Domain Name (g_get_host_name()) for the local computer. Click “Next” to continue ((or “Back” to start all over again) or “Finish” to skip the details).

Notice the immediate, live recording file. The default immediate, live recording file name falls back to the result of g_strconcat(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC), "/", gtk_entry_get_text(GTK_ENTRY(musician_entry)), "_-_", gtk_entry_get_text(GTK_ENTRY(song_entry)), "_[",g_date_time_format_iso8601 (datestamp),"]",".ogg", NULL) in gingerblue/src/gingerblue-main.c

Click on “Cancel” once in GNOME Gingerblue to stop immediate recording and click on “Cancel” once again to exit the application (or Ctrl-c in the terminal).

The following Multiple-Location Audio Recording XML file [.gingerblue] is created in G_USER_DIRECTORY_MUSIC (usually $HOME/Music/ on American English systems):

<?xml version='1.0' encoding='UTF-8'?>
<gingerblue version='2.0.1'>
<musician>Wilber</musician>
<song>Gingerblue Track 0001</song>
<instrument>Piano</instrument>
<line>Mic</line>
<label>GNOME Music</label>
<station>streaming.gnome.org</station>
<filename>/home/wilber/Music/Wilber_-_Song_-_2021-07-12T21:36:07.624570Z.ogg</filename>
<album>/home/wilber/Music/GNOME</album>
<studio>file://streaming.gnome.org/</studio>
</gingerblue>

You’ll find the recorded Ogg Vorbis audio files along with the Multiple-Location Audio Recording XML files in g_get_user_special_dir(G_USER_DIRECTORY_MUSIC) (usually $HOME/Music/) on GNOME 41 systems configured in the American English language and can launch the latest recording by opening $HOME/Music/GNOME.xspf:

<?xml version="1.0" encoding="UTF-8"?>
<playlist version="1" xmlns="http://xspf.org/ns/0/">
<trackList>
<track>
<title>Song_-_2021-11-11T00:28:10.306448Z</title>
<location>file://streaming.gnome.org//home/wilber/Music/Wilber_-_Song_-_2021-07-12T21:36:07.624570Z.ogg</location>
</track>
</trackList>
</playlist>

November 10, 2021

Pango Updates

Here is another update on what will appear in Pango 1.50 soon. Quite a few things, as it turns out. (This is a continuation of my last Pango update)

Bidi Improvements

Pango has long claimed to have good support for bidirectional text rendering and editing. But until recently, there were some annoying bugs: you could end up in loops when moving the cursor through mixed-direction text.

The relevant code has been rewritten, closing a very old bug (#157).

Useful Information

Modern fonts can contain a lot of different information – there can be colormaps, and glyphs can be represented not just as splines, but also as pngs or svgs.

For GTK, an important piece of information for each glyph is whether it is colored or monochrome. With the new PangoGlyphVisAttr.is_color field,  GTK no longer needs to poke directly at the font data to find out.

Another case where GTK needed data that wasn’t available through Pango APIs has been closed with pango_font_get_languages(). This data is used in the font chooser filter popup:

Superscripts and subscripts

Superscripts and subscripts now use font metrics information for size changes and baseline shift.  They can also be properly nested, so markup like

2<sup>2<sup>2</sup></sup>

yields the expected rendering:

Customizing segmentation

Pango determines word and sentence boundaries according to the Unicode Text Segmentation Spec (TR29). The specification can’t deal with all the complexities of formatted text, so sometimes its results need tailoring, which can now be done with the new word and sentence attributes:

$ pango-segmentation --kind=word --text=\
    "<span segment='word'>1-based</span> index"

|1-based| |index|

Better Markup

Besides the new attributes that have been mentioned, Pango markup now lets you specify many attributes in more natural units.

For example,  you can now say

<span font_size='12.5pt'>

instead of

<span font_size='12800'>

Small Caps

Pango has had the PangoVariant enumeration with its PANGO_VARIANT_SMALL_CAPS value since forever, but it has never done anything. Since we’ve added support for OpenType features (in Pango 1.37), it has been possible to produce Small Caps by using the smcp=1 feature, if the font supports it. Sadly, most fonts don’t.

With the text transformation and font scaling infrastructure now in place, it was easy to emulate Small Caps for fonts that don’t  support this natively:

While at it, we’ve expanded the PangoVariant enumeration to cover all the CSS casing variants, and made the GTK CSS engine use them instead of OpenType features.

Better debugging

Pango ships with a versatile test utility called pango-view, which has options to test many of Pangos layout features. It has recently learned to show more auxiliary information in visual form, like glyph extents, caret positions and slopes:

$ pango-view --text Boxes \ --annotate=glyph,caret,slope

Enjoy!

System76: A Case Study on How Not To Collaborate With Upstream

Preface: the following post was written in the context of the events that happened in September. Some time has passed, and I held off on publishing in the hopes we could reach a happy ending with System76. As time has passed, that hope has faded. Attempts to reach out to System76 have not been productive, and I feel we’ve let the impression they’ve given the wider tech community about GNOME sit for far too long.  Some things have changed since I originally wrote the post, so some bits have been removed.


Recently there’s been some heated discussion regarding GNOME’s future. This has led to a lot of fear, uncertainty, and doubt being spread about GNOME, as well as attacks and hostility toward GNOME as a whole and toward individual contributors. This largely started due to the actions of one company’s employees in particular: System76.

This is not the first time System76 has been at the center of a public conflict with the GNOME community, nor is it the first time it was handled poorly. At this point, I no longer feel comfortable working with System76 without some sort of acknowledgment and apology for their poor behavior, and a promise that this won’t happen again.

You might be thinking: what sort of behavior are you talking about? What has System76 done to deserve this treatment? Well, it’s not any one incident – it’s a pattern of behavior that’s repeated multiple times over the past few years. I’ll share incidents I know of from the past, what their behavior has been like in the present, and my own thoughts on the future.

Disclaimer: The following content is my opinion and my opinion alone. I do not speak for GNOME as a whole, only for myself using the observations I’ve made. These observations may be incorrect.

System76 & the LVFS

This is the first major issue that I’m aware of. It will also showcase some of the behaviors that will repeat. Back in 2017 and 2018, Richard Hughes was communicating with System76 to get their firmware working on the LVFS and fwupd. Then in a sudden move, System76 announced their own infrastructure and software for firmware updates. They also told Richard that he should use their infrastructure instead of his. Richard expressed his surprise and disappointment at this move on his blog.

Initially this seems like a case of a communication breakdown alongside a technical disagreement. However, the real unacceptable behavior comes with System76’s response to Richard’s post. They start by sharing part of the correspondence between both parties. I believe the communication breakdown occurs in this section, where Richard explains why their current methods will not work for the LVFS. Then they go further and imply that the LVFS is handing away private data:

Be wary

We had intended to use LVFS in the future, but that is no longer the case; there are too many problems with the project.
If you want to use LVFS, disable the data collection. There’s no need for it. Understand that the first instinct of the project leaders was to unnecessarily opt-in data collection from user installations.
Understand that you’re electing for your distribution to communicate with third party servers. The more servers your distribution communicates with out of the box (especially as root), the more surface area there is for vulnerabilities. Heavily scrutinize any addition of a third-party server for updates.
Understand that if you are a company specializing in Linux-only devices and considering using LVFS, you are handing your private sales data to LVFS. We suggest hosting LVFS on your own servers.

System76 employees continued to spread this idea into early 2019 online, likely prompting a post from Richard to refute their claims. Later on the LVFS team put in work to support the use case of System76 so that vendors could use the LVFS without any sort of reporting. Soon after System76 began using the LVFS and fwupd without any fanfare or retraction of their prior statements.

Now, before we move on to the next incident there are a few key takeaways that should be kept in mind. These will be repeating behaviors:

  • System76 blindsided upstream with criticism and advertised their own in-house solutions.
  • System76 spread misinformation for months after not getting their way.

System76, Ubuntu, & Bug Fixes

In 2019 Sebastien Bacher from Canonical shared a post about System76’s treatment of upstreams – in this case, both Ubuntu and GNOME:

I saw a few cases of those situations happening recently

  1. System76 / Pop! OS finds a bug (where ‘find’ often means that they confirm an existing upstream bug is impacting their OS version)

  2. They write a patch or workaround, include it in their package but don’t upstream the change/fix (or just drop a .patch labelled as workaround in a comment rather than submitting it for proper review)

  3. Later-on they start commenting on the upstream (Ubuntu, GNOME, …) bugs trackers, pointing out to users that the issue has been addressed in Pop! OS, advertising how they care about users and that’s why they got the problem solved in their OSSystem76 / Pop! OS team, while you should be proud of the work you do for you users I think you are going the wrong way there. Working on fixes and including them early in your product is one thing, not upstreaming those fixes and using that for marketing you as better than your upstreams is a risky game.

At this point in time System76 had already established a pattern of behavior where instead of working with upstreams, they take the opportunity to market themselves and their solutions.

System76, GNOME Shell, & Tiling

This is a fairly straightforward incident, but it’s one that’s concerning as it involves a misleading narrative that System76 has been running for two years. In late 2019 System76 began work on an extension that allowed for i3-like tiling in GNOME. When an upstream designer reached out for collaboration on tiling upstream Jeremy Soller, principal engineer at System76, refused to work with him. Now, the true problematic part is that System76 has continued to repeat that upstream is not interested in tiling for the past few years. A few examples:

I’m afraid GNOME does not want to support quarter tiling windows.

It would be nice if GNOME wanted to have tiling window functionalities integrated into their desktop. But the truth is that they don’t.

– Michael Murphy

This is untrue, and the linked tweet shows that. Yet System76 employees keep repeating the idea that we don’t want tiling.

System76 & GNOME 40

Soon after we announced the direction for GNOME 40, Jeremy Soller surprised us with the statement that System76 did not “consent” to the new GNOME Shell design. He also claimed that feedback from their designer was dismissed. GNOME 40’s design was largely discussed on design calls that were not recorded, which makes this claim hard to verify. It’s also hard to address because while there may not have been any intent of harm, their designer may still have felt unheard or hurt – causing pain doesn’t require intending to cause pain. So, I will focus on what I can address.

Jeremy claims and has continued to claim that their proposals were rejected. That is not the case. The reality is that System76 had a designer involved for roughly one year of the three-year design process. Their designer participated in design calls and discussions with the design team, and her role was focused on the UX research itself (defining research questions, running interviews, parsing the results, etc.). There were never any mockups or concrete proposals from System76 during the design process. I’ve also heard that System76 conducted a survey and did not share the results with the team working on the 40 design.

To my understanding, the one time System76 made a proposal was at the very end of the design process during a meeting the design team had with stakeholders. There they pitched COSMIC and didn’t receive the feedback they wanted at the time. Perhaps this is what they were referring to, but at this point it was too late for any proposed changes to be made.

The behavior of the company repeated the initial pattern. When System76 did not get their way with their design, they started sharing misinformation. This particular instance of misinformation has been incredibly harmful for GNOME’s reputation. I’ve often seen the first two tweets brought up as “proof” that GNOME doesn’t want to work with downstreams or listen to users. In reality they are an example of how System76 acts toward others when they don’t get what they want.

System76, libadwaita, & GTK Themes

Now we’ve arrived at the latest incident. I’ve been involved in this one more than the others, and I have watched it unfold from the beginning to the present. I’ve decided to go into further depth, breaking down the most important parts by the day.

September 1

This all started at the beginning of the month, when Jeremy noticed that we override gtk-theme-name and set the Adwaita stylesheet for apps using libadwaita. He shared this on his Twitter. Jeremy then posted misinformation about dark style support. Why is this misinformation?

Jeremy then very publicly called out GNOME as a whole – something that a few people interpreted as a threatening ultimatum. Jeremy was soon made aware that libadwaita is a WIP library and that there is still time to work with us regarding vendor theming. Yet, this was not the end for him posting about this on Twitter. Federico wrote and linked a blog post detailing our goals and what can be done to help resolve the situation, with help from Alexander.

September 2

Jeremy replied to Federico’s blog post with a quote from Alexander. This quote was taken out of context and assumed a different meaning, a meaning that is convenient to the narrative that was building up until this point. In reality Alexander was only explaining the status of things as they are in the present, and what the current goals are. Jeremy also quoted an old blog post from Adrien from before libadwaita existed. Do note that in said blog post Adrien went over the possibility for vendors and users to style within this framework despite his personal opinion. When asked to work with us upstream instead of going to Twitter, Jeremy refused – he would not work with us unless he got exactly what he wanted.

September 3

Jeremy stated that System76 was excited to use libadwaita. The very next day Michael Murphy, one of their core team members, contradicted this saying:

I wasn’t even aware that libadwaita even existed when Jeremy started tweeting about it. I don’t think any of us knew about libadwaita and it’s goals.

Michael also made the claim that we don’t want to collaborate when at this point we’d asked them to collaborate instead of pointing fingers multiple times, as shown in the prior archives.

Finally after three days an opportunity appeared to talk and I took it. Below is a summary of the conversation, of which I also kept screenshots of:

  • Jeremy sent the proposal he mentioned
  • I read through the proposal, then gave my feedback. I said I thought that it was interesting, but I also gave a detailed breakdown on why I didn’t think it would be implemented, including the following points:
    • The GTK team wants to put platform libraries in charge of platform styling
    • Most app developers I know (even those who hadn’t signed the well-known open letter at the time) are not happy with the state of arbitrarily applied stylesheet changes
    • Many app developers don’t want to take on the burden of supporting multiple stylesheets
    • Other stylesheets may not be up-to-date implementing Adwaita’s API, re-creating the existing problem
    • “Hard coding” Adwaita is part of our work toward things like a recoloring API for apps and a properly supported dark style preference
  • I expressed there was room to discuss distro branding of default apps, but not a will to bring back arbitrary stylesheet support.
  • I explained the concerns of app developers regarding custom widgets
  • Jeremy expressed his fear about replacing default apps because of these changes
  • I explained that it would be better to work with us on a non-stylesheet method for vendor branding
  • As the conversation wrapped up, I asked that in the future they take issues to GitLab before going to Twitter. I also expressed the pain they had caused and subtly tried to tell them that some developers would want an apology before working with them.
  • Jeremy did not acknowledge the first part and refused to make an apology.

Jeremy then opened the GTK issue, and was redirected to libadwaita. After some discussion on the libadwaita issue he opened a merge request.

September 6

After a lot of discussion on the issue and the MR, the merge request was closed once was made clear that:

  • Third-party and core application developers largely did not want the proposed solution.
  • Multiple developers, including myself, were not comfortable working with System76 without an acknowledgment of their behavior and an apology.

The Aftermath

Once again, System76 employees decided to spread misinformation and complaints on Twitter instead of making an attempt to work with us upstream on their issues. It’s reasonable to assume that they learned about libadwaita and began posting ultimatums on Twitter on the same day. Once again, they have spread misinformation about the project and our goals.

In the weeks since the MR was closed, a few different employees have continued spreading misinformation on Twitter about the situation. Their existing misinformation has already caused ripples within the community, getting many people stirred up and making claims like GTK4 being only for GNOME, or GNOME wanting to be the “only” desktop on Linux because of the approach to themes we have. We’ve had a lot of vitriol thrown our way.

System76’s words also have reach beyond the Linux ecosystem, and large content creators are only hearing their side of the story.

There have been additional attempts by others to reach out diplomatically, but those seem to have fallen through. Just the other day the CEO claimed that there were no technical or quality reasons for the change, heavily implying that it was done just to hurt downstreams.

With all of the misinformation and the consequences of said misinformation, and with the refusal to listen or engage with our own needs, I do not feel like it is worth my time to engage with System76. Until they recognize their behavior for what it is and make a commitment to stop it, I will not be doing free labor for them. If they can do that, I would be happy to work with them on resolving their issues.

Epilogue: What’s Really Going On With Theming?

Now that we’ve addressed System76’s hand in stirring up controversy, let me clarify what the situation actually is, and what vendors and other desktop environments can do moving forward.

Terms To Know

This is a high-level overview, but since we’re talking about technical details there will be some terms to know:

  • Stylesheet: Compilations of CSS styles for widgets. “Themes” as we know them are stylesheets, e.g. Adwaita, Arc, Pop, or Yaru.
  • Platform library: A platform library is a collection of widgets, useful functions, constants, and styles for apps on a platform to use. Granite and libadwaita are examples of platform libraries.
  • Visual API: An API or “contract” for the visuals of an application.

GTK & Theming

Let me clear this up immediately: nothing about the theming infrastructure has changed in GTK itself between GTK3 and GTK4. The only changes are listed in the migration guide, and are mostly removed or replaced GTK-specific CSS functions. All the changes that have caused controversy have to do with libadwaita.

You might have seen some people bring up two particular issues as counterpoints to this:

What do those two issues mean? Well, it means that the GTK team thinks that these particular issues are better handled in platform libraries. This does not mean only libadwaita or only libgranite, nor does it mean that GTK-based applications would no longer be able to have a dark theme or different themes. The platform library would be responsible for handling those items in accordance with their goals.

Desktops X, Y, and Z could work together and create a libxyz that loads different stylesheets just like GTK does now, or they could each make their own platform library that handles their specific needs. The proposed GTK changes would simply put the choice in the hands of each platform.

GNOME, libadwaita, & Theming

In April when Adwaita was moved to libadwaita, the controversial change to override gtk-theme-name was made. The commit explains the reasoning for this particular change:

Ensure Adwaita is loaded instead of the default, take care to load Adwaita-hc when HighContrast is selected system-wide.

Why do we want to ensure libadwaita is loaded at all instead of other stylesheets? It comes down to two key things:

  • Adwaita for platform integration
  • Adwaita as a visual API

In GNOME, we want to have a stable platform for app developers to use to build new, useful, and well-integrated apps. Part of having a stable platform is having a stable visual API. The GNOME Human Interface Guidelines lay out the ideas and goals for apps targeting GNOME to follow, and libadwaita helps developers implement those ideas. The stylesheet itself is part of keeping interfaces in line with the HIG.

With libadwaita the widgets, the stylesheet, and the HIG are all tied together in one easy to use package. With each new version of GNOME we can iterate on them all at once so it will be easier for developers to keep up with different changes. This is in contrast to the current state of development where app developers need to implement their own versions of common patterns or copy-paste them from other apps.

Adwaita being used this way means that apps also need to rely on it being there, and apps will make assumptions based on that. For example, we want it to be very simple for app developers to recolor widgets. Before if apps wanted to do this, they needed to depend on sassc and libsass and occasionally regenerate the themes on-the-fly. Now all they need to do is set the background-color on a widget.

This new method works perfectly with the new Adwaita stylesheet. Here we have a simple Color Picker app:

Color Picker using the Adwaita Stylesheet
Color Picker using the Adwaita Stylesheet

Recoloring still works well with stylesheets that are based on Adwaita, like Yaru:

Color Picker using the Yaru Stylesheet
Color Picker using the Yaru Stylesheet

Things begin breaking down with stylesheets that deviate too far from Adwaita:

Color Picker using the Pop stylesheet
Color Picker using the Pop stylesheet

Without enforcing Adwaita as the stylesheet apps may not look correct or in some cases may not function at all. For a more in-depth breakdown of the problem with more examples, see Tobias Bernard’s post “Restyling apps at scale.”

November 09, 2021

Typesetting a whole book part III, the analog edition

In earlier editions (part 1, part 2) we looked at typesetting a full book to a PDF file. This is fun and all, but until you actually hold a physical copy in your hands you don't really know how good the end result is. Puddings, eatings and all that.

So I decided to examine how would you go about printing and binding an entire book. For text I used P. G. Wodehouse's The Inimitable Jeeves. It has roughly 220 pages which is a good amount for perfect binding. Typesetting it in LibreOffice only took a few hours. To make things even simpler I used only one font, the Palatino lookalike P052 that comes packaged with Ghostscript. As the Jeeves stories take place in the 1920s something like Century would have been more period accurate but we'll have to work with what we got.

The only printer I had access to was an A4 laser printer that could only print on one side of the page. Thus to keep things as simple as possible the page size became A5, which is easy to obtain by folding A4 paper in half. None of the printer dialogs seemed to do the imposition I needed (single page saddle fold, basically) so I had to convert the A5 originals to A4 printable sheets with a custom Python script (using PyPDF2)

Printing turned out to have its complications as it always does. The printer did not have Cups drivers so I had to print using Windows. I used Acrobat Reader as it should be the gold standard of PDF manipulation. The original documents were in A4 and the printer only had A4 paper capability. And yet, Acrobat insisted on compositing the pages to 8.5x11 and then printing them distorted because AMERICA! After going through every menu (especially the hidden ones) I managed to make it stop doing that. Then I printed the pages by first printing the odd pages, taking the output, adding it back in the paper tray and then printing the even pages. If you want to try the same, note that for the latter batch you need to print the pages in reverse order.

Do this in small batches. I did and was happy that I did, because every now and then I botched it up and had to redo the pages. But eventually I did prevail.

Then you fold each page in half and stack them to get the text block.

Fasten them together using clips and cut out a piece of cardboard for the cover.

Then glue the spine together, first the pages and then bookbinder's mull on top of that. This step is a bit involved, but Youtube has several videos that show you how to do it.

Then glue on the cover and place the whole thing into a press. Low tech solutions work surprisingly well. (Trivia: this box contains 25 Meson mugs.)

Leave like this overnight. In the morning the book is ready for trimming.

Sadly I don't have a heavy duty paper guillotine so the edges remained a bit rough. Other than that the end result looks pretty nice.

All in all this was a surprisingly simple and fun project. The binding process was so simple that even a craft-noob like myself could get it done without too much trouble. I did make a practice run with some empty pages, though. The clips were a bit fiddly, having a proper press or a woodworking bench would have made the end result smoother.

November 08, 2021

A good next step

Some months back (in March to be precise), I completed an amazing outreachy internship at GNOME. The months after that have been full of activity. In July I had the opportunity of presenting at the first open source conference I ever attended- GNOME’s Annual Developer Conference (GUADEC). Here I shared the contributions I made to the community by working on GNOME’s JavaScript Debugger where I wrote JavaScript code, improved on some areas of the documentation and helped new contributors find their way when I could.

Fast-foward to a couple of days later, I was given the opportunity to be part of another enriching open source internship (Coding Experience) at Igalia. I first came across this opportunity through one of my outreachy blog posts “Seeking for career opportunities“. Special thanks to Paul Wise for leaving the link to FOSSjobs website in his/her/their comment (https://www.fossjobs.net/ and https://github.com/fossjobs/fossjobs/wiki/Resources), Philip (my outreachy mentor) and those on the FOSSjobs gnome matrix channel for sharing this opportunity.

At Igalia I work on improving on the user experience of Cog and other WPE-Webkit related tasks. I must and have to say that working at Igalia is very challenging and also interesting. Work at Igalia is exciting to me because of the team and the work culture(there is socialization).I work with amazing people at Igalia-my mentor Chris Lord (who is always very helpful), Adrian(on Cog), just to mention a few. If you agree with me on the need to work on your communication skills to easily contribute to open source, then those skills come in handy at Igalia since we work on open source projects. I am glad to have been able to find time after this long to blog again and I will continue sharing my experiences consistently to help others facing challenges in open source and struggling with learning how to code and staying in the field.

I like to end here so this blog post doesn’t become lengthy. In the weeks that follow, I will be sharing information about my experience at Igalia(work, challenges, improvements since my last internship). This series is called “My Open Source Journey”. Thanks for reading and please keep reading, liking and sharing.

November 05, 2021

Editing a background check policy

We’re implementing a background check policy for some roles at Tidelift, because we see security-critical information from our customers. Our background check provider (who I won’t name, because this isn’t about them) has a template policy that is pretty good! But the rest of their product has a very high standard for UX—their designers generally do not settle for pretty good.

The red pen bleeds during term paper season... (11/52)
“The red pen bleeds during term paper season… (11/52)” by Rodger_Evans is licensed under CC BY-ND 2.0

Since I know they care, and since employment documents (especially ones that relate to bias) are an important way Tidelift communicate about our company values, I took the time to send them my changes. Having done that work I figured I’d make it a blog post too :) Some notes:

Consistency between software and legal documents

A legal document is, in many cases, a part of a company’s user experience. As such, it needs to be vetted for consistency with the rest of the software, just as you’d vet any other part of the UX.

This is hard, and easy to screw up, because let’s face it—who likes reading and re-reading legal documents? Not even lawyers, if we’re being honest. This particular document screws this up in two ways.

First, the tool (very correctly!) encourages companies not to do a background check for every position, since that introduces a significant bias against people who may have been rehabilitated and should have a fair chance at employment. But the legal document says very plainly that “all offers of employment are contingent on … a background check” (emphasis mine). The legal terms must be brought into alignment with the software’s reality.

Similarly, one of the benefits of this tool is that it takes care of the paperwork for you—without pens and paper. And yet the legal document says that a “signed, written consent will be obtained … in compliance with … law”. Now, good American lawyers know that under the E-SIGN Act of 2000, lots of digital things are “signatures” for the purposes of American law, but most people don’t know that. Good drafting will avoid confusing these non-lawyers by simply saying the consent will be “explicit” and recorded by the service.

Multi-clause sentences and checklists

This is not always the case, but many sentences in legal documents would benefit from being broken up into bullet points, so that each criteria is easier to follow or even treat as a checklist. Consider the difference between:

A decision to withdraw an offer of employment will be made only after conducting an individualized inquiry into whether the information obtained is job-related and a decision to withdraw an offer is consistent with business necessity.  

Original policy

And:

A decision to withdraw an offer of employment will be made only after conducting an individualized inquiry into whether:
– the information obtained through the reference check is relevant to the nature and performance of the role; and
– withdrawal is consistent with the business’s needs.

My revisions

This sounds sort of trivial, but clear writing really can help you spot errors. In this case, breaking up a sentence into bullet points made me notice that the document was inconsistent—an important anti-bias process step was listed in another section, but silently dropped in this list. So someone skimming just the one section of the policy might get it very, very wrong. (Programmers reading this will be nodding along right now—this is debugging by using better formatting to ease code inspection.)

Similarly, where a process is spread across multiple paragraphs, consider using numbered bullet points to emphasize the checklist-like nature of the process and improve the ability to discuss. Much easier to ask “did you do step 4” than “did you do the second clause of the third sentence”.

Q&A style

I continue to believe that many legal documents should at least be edited (not necessarily finalized) in a Q&A style—in other words, changing each section header to a question, and making sure the section actually answers the question. I talked a bit more about that in this post about doing it for a draft of the Mozilla Public License.

In all cases, doing this forces you to make sure that each section has a focused, clear purpose. For example, in the original draft of this policy, there was a section titled “Evaluating Background Check Results”. Revising that into a question (“How will we evaluate the results of the background check?”) helped me realize that one sentence was about a related, but different topic—privacy. Breaking that out into its own privacy section both clarifying the original section and allowed the new section to respond more forcefully to employee concerns about confidentiality.

In the best cases the Q&A framing can really help understanding for non-legal (and even legal) readers. In this case, I found that a well-placed question helped differentiate “why the company does it” from “how the company does it”—which was muddled in the original draft, and important to aid understanding of a tricky anti-bias concept.

Be careful about definitions

Last but not least—you can often tell when a document has suffered from copy/paste when it uses a defined term exactly once, rather than multiple times. Not only does this give you the opportunity to remove the defined term (in this case “Company”) but it also reminds you to give extra focus on the ways that term is used, since it is likely to have copy/paste problems. (In this particular case the stray “Company” thankfully didn’t point to anything worse than jarring word choice—but at least it was easy to eliminate!)

Interested in learning more? Come work with me!

I can’t promise we approach everything with this level of detail; we’re still a small startup and one of the ways we balance the tension between pragmatism and idealism is to Just Get Things Done. But I’m also proud of the way so many of us think through the things some other companies get wrong. If that sounds like fun, we’re hiring!