December 20, 2024

December Projects

Not all of my projects this December are code related. In fact a lot of them have been house maintenance things, joy of home ownership and all.

This week was spent building my new office and music space. I wanted a way to have my amplifiers and guitars more accessible while also creating a sort of “dark academia” sort of feeling for working.

The first step was to get the guitars mounted on the walls. I was looking for something blending artistic showpiece and functional use.

After that I quickly framed them in. Just quarter round with the hard edge inwards, 45° miter, some caulking, easy peasy.

My last office had Hale Navy as the color, but the sheen was too much that it made it difficult to actually see the color. This time I went flat and color drenched the space (so ceilings, trim, etc all in matching tone).

Then somewhat final result is here. I still want to have a lighting story for these that doesn’t involve a battery so some electrical fish taping is likely in my future.

I also converted the wide closet into a workstation area with the studio monitors for recording. But that is still partially finished as I need to plane all the slats for the slat wall, frame the builtin, and attach the countertop.

#179 Reduced Memory Usage

Update on what happened across the GNOME project in the week from December 13 to December 20.

GNOME Core Apps and Libraries

Sam Thursfield says

Carlos Garnacho implemented a clever optimisation in the LocalSearch filesystem indexer, which reduces memory usage when crawling large folders. See the MR for details and a before and after comparison.

Khalid Abu Shawarib reports

User Sharing, is a small package that binds together various free software projects to bring easy to use, user-level file sharing to the masses. Earlier this week, a merge request has landed that ports all of the application code over from C to Rust! The file sharing service still retains the same functionality.

See this post for more details.

Libadwaita

Building blocks for modern GNOME apps using GTK4.

Alice (she/her) says

libadwaita now has Adaptive Preview in GTK inspector, a way to test layouts on smaller screen sizes - similar to responsive layout mode in Firefox inspector, device toolbar in Chrome etc. See https://blogs.gnome.org/alicem/2024/12/19/mobile-testing-in-libadwaita/ for more details

Software

Lets you install and update applications and system extensions.

Adrien Plazas announces

Software received a brand new systemd-sysupdate plugin. That was one of the last pieces needed to complete the migration of GNOME OS from OSTree to systemd-sysupdate. Read more in this short blog post.

Calendar

A simple calendar application.

Titouan Real says

GNOME Calendar, your favorite calendaring application, got a much improved event editor for GNOME 48!

  • Adaptive Calendar Selector: The calendar selector dropdown has been updated to use a standard widget, fixing multiple issues along the way;
  • Better Date and Time Entries: entries feature better keyboard navigation and better parsing;
  • Modernized Layout: The new layout is more compact, easier to read, and is more in line with modern design patterns.

Support for timezone editing is also in the testing phase in this merge request. If you would like to help, you can grab the Flatpak artifacts (or build yourself using GNOME Builder), and report any bug you may find. We recommend only using a throwaway calendar for testing.

GNOME Circle Apps and Libraries

Tuba

Browse the Fediverse.

Evangelos “GeopJr” Paterakis announces

Tuba 0.9 is now available, with many new features and bug fixes!

✨ Highlights:

  • Audio Visualizer
  • Accent Colors and other GNOME 47 changes
  • Focus Picker
  • Account Suggestions for new accounts
  • Scheduled & Draft Posts
  • Full emoji reaction support for supported backends
  • FediWrapped
  • Viewing which ones of the people you follow also follow an account
  • Placing favorite lists to the sidebar
  • Poll animations, refresh and show results button
  • Windows installer
  • And much more!

Happy Holidays! ❄️

Third Party Projects

دانیال بهزادی announces

We’re excited to announce the release of Carburetor version 5.0.0, our user-friendly tool for setting up a TOR proxy effortlessly! This release comes with a special significance as we celebrate the longest night of the year, known as Yalda in Persian culture. Yalda symbolizes the endurance of darkness, reminding us that even the longest nights eventually give way to dawn. This resonates deeply with those living under tyranny, as we hold onto hope for a brighter future and the eventual liberation from oppression.

In a momentous turn of events, we also extend our heartfelt congratulations to the brave Syrians around the world on the departure of Bashar Al-Asad, a symbol of tyranny. We hope this new chapter brings them closer to freedom and access to a truly open Internet. With Carburetor, we aim to empower users to prioritize their privacy and security, ensuring that the tool is used for the right reasons—helping others and safeguarding personal information, rather than as a means of mandatory connectivity.

Happy Yalda and cheers to a brighter future! 🌟

Parabolic

Download web video and audio.

Nick says

Parabolic V2024.12.0 is here! This update contains a redesigned Qt application, new features and various bug fixes.

Here’s the full changelog:

  • Added the ability to toggle the inclusion of a media’s id in its title when validated in the app’s settings
  • Added the option to export a download’s media description to a separate file
  • Restored the ability for Parabolic to accept a URL to validate via command line arguments
  • Fixed an issue where auto-generated subtitles were not being embed in a media file
  • Fixed an issue where downloading media at certain time frames were not respected
  • Fixed an issue where video medias’ thumbnails were also cropped when crop audio thumbnails was enabled
  • Fixed an issue where the previously used download quality was not remembered
  • Redesigned the Qt version’s user interface with a more modern style
  • Updated yt-dlp to 2024.12.13

Nick reports

Parabolic V2024.12.1 was also released this week! It contains various bug fixes for issues users were experiencing.

Here’s the full changelog:

  • Fixed an issue where generic video downloads would sometimes incorrectly convert to another file type
  • Fixed an issue where subtitles were not downloaded properly
  • Fixed an issue where desktop notifications were not being displayed

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 19, 2024

A systemd-sysupdate Plugin for GNOME Software

In late June 2024 I got asked to take over the work started by Jerry Wu creating a systemd-sysupdate plugin for Software. The goal was to allow Software to update sysupdate targets, such as base system images or system extension images, all while respecting the user’s preferences such as whether to download updates on metered connections. To do so, the plugin communicates with the systemd-sysupdated daemon via its org.freedesktop.sysupdate1 D-Bus interface.

I didn’t know many of the things required to complete this project and it’s been a lot to chew in one bite for me, hence how long it took to complete. I’m happy it’s finally done, but I’m certain it’s riddled with bugs despite my best efforts, and I’m not happy it’s a single gigantic C file. It needs to be split into modules, but that’s an effort for another time as getting it to work at all was a challenge already. I’m happy I learned a lot along the way. Thanks a lot to Codethink, to the GNOME Foundation, to the Sovereign Tech Agency and for sponsoring this work. Thanks a lot to Abderrahim Kitouni, Adrian Vovk, Philip Withnall and all the other persons who helped me complete this project. 🙂

This was one of the last pieces of software needed to complete the migration of GNOME OS from OSTree to sysupdate. While OSTree is great for operating systems, it has a significant drawback: it can’t support SecureBoot because it can’t support Unified Kernel Images, and SecureBoot requires a signed Unified Kernel Image for its chain of trust. While its A/B partitioning system makes sysupdate more storage hungry and less flexible than OSTree, it allows it to support Unified Kernel Images, to sign them, and to be part of SecureBoot’s chain of trust, ensuring the system hasn’t been maliciously tempered. This will make GNOME OS more secure and its boot trusted. Read more of trusted boot from Lennart Poettering.

Erratum: Timothée Ravier stated that OSTree can support trusted boot and measured boot, see this demostration.

You should be able to test this plugin in GNOME OS soon. Please report any issues with the systemd-sysupdate tag, and the GNOME OS one if relevant. We want to be very sure that this works, as it’s vital that users know whether or not their system is up to date, especially if there are security-related fixes involved.

Christmas / Winter / End-of-the-year Holidays Maps 2024 Yearly Wrap-up



In line with traditions, it's time for the yearly end-of-the year Maps blog post!

There's been some quite nice happenings this year when it comes to Maps (and the underlaying libshumate, our map widget library).


Vector Map Enabled by Default

The biggest change, by large that's happened in 2024 is that we finally did the switch to client-side rendered vector tiles with all the benefits this brings us:

  • A “GNOME-themed” map style
  • Properly support dark mode
  • Localized labels for places (countries, towns, and so on…)
  • POI icons can now be directly clicked on the map, bringing up information of place


 

More Use of Modern libadwaita Widgets

Works has continued replacing the old deprecated GtkDialog instances, instead using libadwaita's new dialogs, which also has the benefit of being adaptive for small screen sizes. Right now the only remaining instance of the old dialog type is the sharing “Send to” dialog.

Since the 47 release, the OSM POI editing dialog has received a refreshed look-and-feel based on Adwaita widgets, designed by Brage Fuglseth, and initial draft implementation by Felipe Kinoshita.


More Visual Improvements

Also since the September release, some more UI refinements have been made.

The action of starring a place now has an accopanying animation to help give a visual clue of the change.


The headerbar icon for showing the menu listing stored favorites now uses the same icon as GNOME Web (Epiphany), the “books on a libray shelf“ icon.

Spinner widgets (for showing progress) has been updated to the new Adwaita variant with a refreshed design.

And the toggle buttons for selecting routing mode (walk, bike, car, transit) now uses the new Adwaita ToggleGroup icon buttons.


Public Transit Routing Using Transitous

I have mentioned the Transitous previously and since 47.0 Maps uses Transitous to provide public transit directions for regions that weren't already covered by our existing plugins and their provided regions.

During the last few months works has progressed on an updated version of MOTIS (the backend used by Transious) that will give better performance, among otheres.

Maps will also soon transition to the new API when Transitous switches over to it.

And speaking of Transitous and MOTIS.

At FOSDEM 2025 me, Felix Gündling, and Jonah Brüchert will give a presentation of MOTIS, Transitous, and the integration into Maps.

https://fosdem.org/2025/schedule/event/fosdem-2025-4105-gnome-maps-meets-transitous-meets-motis/

 

And until next time, happy holidays!

Mobile testing in libadwaita

Screenshot of Highscore, an emulator frontend running Doom 64 with touch controls, inside libadwaita adaptive preview, emulating a small phone (360x720), in portrait, with mobile shell (26px top bar, 18px bottom bar) and no window controls

Lately I’ve been working on touch controls overlays in Highscore1, and quickly found out that previewing them across different screen sizes is rather tedious.

Currently we have two ways of testing UIs on a different screen size – resize the window, or run the app on that device. Generally when developing, I do the former since it’s faster, but what dimensions do I resize to?

HIG lists the 360×294px dimensions, but that’s the smallest total size – we can’t really figure out the actual sizes in portrait and landscape with this. Sure, we can look up the phone sizes, check their scale factor, and measure the precise panel sizes from screenshots, but that takes time and that’s a lot of values to figure out. I did make such a list, and that’s what I used for testing here, but, well, that’s a lot of values. I also discovered the 294px height listed in HIG is slightly wrong (presumably it was based on phosh mockups, or a really old version) and with older phosh versions the app gets 288px of height, while with newer versions with a slimmer bottom bar it gets 313px.

Now that we know the dimensions, the testing process consists of repeatedly resizing the window to a few specific configurations. I have 31 different overlay, each with 7 different layouts for different screen sizes. Resizing the window for each of them gets old fast, and I really wished I had a tool to make that easier. So, I made one.

View switcher dialog in libadwaita demo, running in adaptive preview, emulating large phone (360x760),  in landscape, with mobile shell and window controls turned off

This is not a separate app, instead it’s a libadwaita feature called adaptive preview, exposed via GTK inspector. When enabled, it shrinks the window contents into a small box and exposes UI for controlling its size: specifically, picking the device and shell from a list. Basically, same as what web browsers have in their inspectors – responsive design mode in Firefox etc.

Adaptive Preview row on the libadwaita page in GTK inspector

It also allows to toggle whether window controls are visible – normally they are disabled on mobile, but mobile gnome-shell currently keeps them enabled as not everything is using AdwDialog yet.

It can also be opened automatically by specifying the ADW_DEBUG_ADAPTIVE_PREVIEW=1 environment variable. This may be useful if e.g. Builder wants to include it into its run menu, similar to opening GTK inspector.

If the selected size is too large and doesn’t fit into the window, it scrolls instead.

What it doesn’t do

It doesn’t simulate fullscreen. Fullscreen is complicated because in addition to hiding shell panels almost every app that supports it changes the UI state – this is not something we can automatically support.

It also doesn’t simulate different scale factors – it’s basically impossible to do with with how it’s implemented.

Similarly, while it does allow to hide the window controls, if the app is checking them manually via GtkSettings:gtk-decoration-layout, it won’t pick that up. It can only affect AdwHeaderBar, similarly to how it’s hiding close button on the sidebars.

Future plans

It would be good to display the rounded corners and cutouts on top of the preview. For example, the phone I use for testing has both rounded corners and a notch, and we don’t have system-wide support for insets or safe area just yet. I know the notch dimensions on my specific phone (approximately 28 logical pixels in height), but obviously it will vary wildly depending on the device. The display panel data from gmobile may be a good fit here.

We may also want to optionally scale the viewport to fit into the window instead of scrolling it – especially for larger sizes. If we have scaling, it may also be good to have a way to make it match the device’s DPI.

Finally, having more device presets in there would be good – currently I only included the devices I was testing the overlays for.


Adaptive preview has already landed in the main branch and is available to apps using the nightly SDK, as well as in GNOME OS.

So, hopefully testing layouts on mobile devices will be easier now. It’s too late for me, but maybe the next person testing their app will benefit from it.


1. gnome-games successor, which really deserves a blog post of its own, but I want to actually have something I can release first, so I will formally announce it then. For now, I’m frequently posting development progress on the Fediverse

December 18, 2024

Introducing Project Aardvark

Two weeks ago we got together in Berlin for another (Un)boiling The Ocean event (slight name change because Mastodon does not deal well with metaphors). This time it was laser-focused on local-first sync, i.e. software that can move seamlessly between real-time collaboration when there’s a network connection, and working offline when there is no connection.

The New p2panda

This event was the next step in our ongoing collaboration with the p2panda project. p2panda provides building blocks for local-first software and is spearheaded by Andreas Dzialocha and Sam Andreae. Since our initial discussions in late 2023 they made a number of structural changes to p2panda, making it more modular and easier to use for cases like ours, i.e. native GNOME apps.

Sam and Andreas introducing the new p2panda release.

This new version of p2panda shipped a few weeks ago, in the form of a dozen separate Rust crates, along with a new website and new documentation.

On Saturday night we had a little Xmas-themed release party for the new p2panda version, with food, Glühwein, and two talks from Eileen Wagner (on peer-to-peer UX patterns) and Sarah Grant (on radio communication).

The Hackfest

Earlier on Saturday and then all day Sunday we had a very focused and productive hackfest to finally put all the pieces together and build our long-planned prototype codenamed “Aardvark”, a local-first collaborative text editor using the p2panda stack.

Simplified diagram of the overall architecture, with the GTK frontend, Automerge for CRDTs, and p2panda for networking.

Our goal was to put together a simple Rust GTK starter project with a TextView, read/write the TextView’s content in and out of an Automerge CRDT, and sync it with other local peers via p2panda running in a separate thread. Long story short: we pulled it off! By the end of the hackfest we had basic collaborative editing working on the local network (modulo some bugs across the stack). It’s of course still a long road from there to an actual releasable app, but it was a great start.

The reason why we went with a text editor is not because it’s the easiest thing to do — freeform text is actually one of the more difficult types of CRDT. However, we felt that in order to get momentum around this project it needs to be something that we ourselves will actually use every day. Hence, the concrete use case we wanted to target was replacing Hedgedoc for taking notes at meetings (particularly useful when having meetings at offline, where there’s no internet).

The current state of Aardvark: Half of the UI isn’t hooked up to anything yet, and it only sort of works on the local network :)

While the Berlin gang was hacking on the text editor, we also had Ada, a remote participant, looking into what it would take to do collaborative sketching in Rnote. This work is still in the investigation stage, but we’re hopeful that it will get somewhere as a second experiment with this stack.

Thanks to everyone who attended the hackfest, in particular Andreas for doing most of the organizing, and Sam Andreae and Sebastian Wick, who came to Berlin specifically for the event! Thanks also to Weise7 for hosting us, and offline for hosting the release party.

The Long Game

Since it’s early days for all of this stuff, we feel that it’s currently best to experiment with this technology in the context of a specific vertically integrated app. This makes it easy to iterate across the entire stack while learning how best to fit together various pieces.

However, we’re hoping that eventually we’ll settle on a standard architecture that will work for many types of apps, at which point parts of this could be split out into a system service of some kind. We could then perhaps also have standard APIs for signaling servers (sometimes needed for peers to find each other) and “dumb pipe” sync/caching servers that only move around encrypted packets (needed in case none of the other peers are online). With this there could be many different interchangeable sync server providers, making app development fully independent of any specific provider.

Martin Kleppmann’s talk at Local-First Conf 2024 outlines his vision for an ecosystem of local-first apps which all use the same standard sync protocol and can thus share sync services, or sync peer-to-peer.

This is all still pretty far out, but we imagine a world where as an app developer the only thing you need to do to build real-time collaboration is to integrate a CRDT for your data, and use the standard system API for the sync service to find peers and send/receive data.

With this in place it should be (almost) as easy to build apps with seamless local-first collaboration as it is to build apps using only the local file system.

Next Steps

It’s still early days for Aardvark, but so far everyone’s very excited about it and development has been going strong since the hackfest. We’re hoping to keep this momentum going into next year, and build the app into a more full-fledged Hedgedoc replacement as part of p2panda’s NGI project by next summer.

That said, we see the main value of this project not in the app itself, but rather the possibility for our community to experiment with local-first patterns, in order to create capacity to do this in more apps across our ecosystem. As part of that effort we’re also interested in working with other app developers on integration in their apps, making bindings for other languages, and working on shared UI patterns for common local-first user flows such as adding peers, showing network status, etc.

If you’d like to get involved, e.g. by contributing to Aardvark, or trying local-first sync in your own app using this stack feel free to reach out on Matrix (aardvark:gnome.org), or the Aardvark repo on Github.

Happy hacking!

A new issue policy for libinput - closing and reopening issues for fun and profit

This is a heads up that if you file an issue in the libinput issue tracker, it's very likely this issue will be closed. And this post explains why that's a good thing, why it doesn't mean what you want, and most importantly why you shouldn't get angry about it.

Unfixed issues have, roughly, two states: they're either waiting for someone who can triage and ideally fix it (let's call those someones "maintainers") or they're waiting on the reporter to provide some more info or test something. Let's call the former state "actionable" and the second state "needinfo". The first state is typically not explicitly communicated but the latter can be via different means, most commonly via a "needinfo" label. Labels are of course great because you can be explicit about what is needed and with our bugbot you can automate much of this.

Alas, using labels has one disadvantage: GitLab does not allow the typical bug reporter to set or remove labels - you need to have at least the Planner role in the project (or group) and, well, suprisingly reporting an issue doesn't mean you get immediately added to the project. So setting a "needinfo" label requires the maintainer to remove the label. And until that happens you have a open bug that has needinfo set and looks like it's still needing info. Not a good look, that is.

So how about we use something other than labels, so the reporter can communicate that the bug has changed to actionable? Well, as it turns out there is exactly thing a reporter can do on their own bugs other than post comments: close it and re-open it. That's it [1]. So given this vast array of options (one button!), we shall use them (click it!).

So for the forseeable future libinput will follow the following pattern:

  • Reporter files an issue
  • Maintainer looks at it, posts a comment requesting some information, closes the bug
  • Reporter attaches information, re-opens bug
  • Maintainer looks at it and either: files a PR to fix the issue or closes the bug with the wontfix/notourbug/cantfix label
Obviously the close/reopen stage may happen a few times. For the final closing where the issue isn't fixed the labels actually work well: they preserve for posterity why the bug was closed and in this case they do not need to be changed by the reporter anyway. But until that final closing the result of this approach is that an open bug is a bug that is actionable for a maintainer.

This process should work (in libinput at least), all it requires is for reporters to not get grumpy about issue being closed. And that's where this blog post (and the comments bugbot will add when closing) come in. So here's hoping. And to stave off the first question: yes, I too wish there was a better (and equally simple) way to go about this.

[1] we shall ignore magic comments that are parsed by language-understanding bots because that future isn't yet the present

December 17, 2024

Meson build definitions merged into Git's git repo

The developers of Git have been considering switchibg build systems for a while. No definitive decision have been made as of yet, but they gave merged Meson build definitions in the main branch. Thus it now possible, and even semi-supported, to develop and build Git with Meson instead of the vintage Makefile setup (which, AFAICT, remains as the default build system for now).

The most interesting thing about this conversion is that the devs were very thorough in their evaluation of all the different possibilities. Those who are interested in the details or are possibly contemplating a build system switch on their own are recommended to read the merge's commit message.

Huge congratulations for everyone involved and thank you for putting in the work (FTR i did not work on this myself). 

December 16, 2024

Announcing systemd v257

Last week we released systemd v257 into the wild.

In the weeks leading up to this release (and the week after) I have posted a series of serieses of posts to Mastodon about key new features in this release, under the #systemd257 hash tag. In case you aren't using Mastodon, but would like to read up, here's a list of all 37 posts:

I intend to do a similar series of serieses of posts for the next systemd release (v258), hence if you haven't left tech Twitter for Mastodon yet, now is the opportunity.

December 13, 2024

Outreachy internship for librsvg, December 2024

I am delighted to announce that I am mentoring Adetoye Anointing for the December 2024 round of Outreachy. Anointing will be working on librsvg, on implementing the SVG2 text layout algorithm. This is his first blog post about the internship.

There is a lot of work to do! Text layout is a complex topic, so rather than just saying, "go read the spec and write the code", Anointing and I have decided to have a little structure to our interactions:

  • We are having two video calls a week.

  • During the calls, I'm sharing my screen to walk him through the code.

  • I'm using my friend Abrahm's Pizarra and a Wacom tablet to have a "digital chalkboard" where I can quickly illustrate explanations while Anointing and I chat:

Screenshot of Pizarra, an electronic blackboard

  • Conveniently, Pizarra also produces SVG files from whatever you doodle in it, so it's easier to include the drawings in other documents.

  • We are using a shared document in pad.gnome.org as a development journal. Here I can write long explanations, leave homework, link to stuff, etc. Anointing can put in his own annotations, questions, or anything else. I'm hoping that this works better than scrolling through a Matrix chat channel.

I have big hopes for this project. Please welcome Anointing if you see him around the Rust ♥️ GNOME channel!

2024 GNOME Infrastructure Annual Review

Table of Contents

1. Introduction

Time is passing by very quickly and another year will go as we approach the end of 2024. This year has been fundamental in shaping the present and the future of GNOME’s Infrastructure with its major highlight being a completely revamped platform and a migration of all GNOME services over to AWS. In this post I’ll try to highlight what the major achievements have been throughout the past 12 months.

2. Achievements

In the below is a list of individual tasks and projects we were able to fulfill in 2024. This section will be particularly long but I want to stress the importance of each of these items and the efforts we put in to make sure they were delivered in a timely manner.

2.1. Major achievements

  1. All the applications (except for ego, which we expect to handle as soon as next week or in January) were migrated to our new AWS platform (see GNOME Infrastructure migration to AWS)
  2. During each of the apps migrations we made sure to:
    1. Migrate to sso.gnome.org and make 2FA mandatory
    2. Make sure database connections are handled via connection poolers
    3. Double check the container images in use were up-to-date and GitLab CI/CD pipeline schedules were turned on for weekly rebuilds (security updates)
    4. For GitLab, we made sure repositories were migrated to an EBS volume to increase IO throughput and bandwidth
  3. Migrated away our backup mechanism away from rdiff-backup into AWS Backup service (which handles both our AWS EFS and EBS snapshots)
  4. Retired our NSD install and migrated our authoritative name servers to CloudNS (it comes with multiple redundant authoritative servers, DDOS protection and automated DNSSEC keys rotation and management)
  5. We moved away from Ceph and the need to maintain our own storage solution and started leveraging AWS EFS and EBS
  6. We deprecated Splunk and built a solution around promtail and Loki in order to handle our logging requirements
  7. We deprecated Prometheus blackbox and started leveraging CloudNS monitoring service which we interact with using an API and a set of CI/CD jobs we host in GitHub
  8. We archived GNOME’s wiki and turned it into a static HTML copy
  9. We replaced ftpadmin with the GNOME Release Services, thanks speknik! More information around what steps should GNOME Maintainers now follow when doing a module release are available here. The service uses JWT tokens to verify and authorize specific CI/CD jobs and only allows new releases when the process is initiated by a project CI living within the GNOME GitLab namespace and a protected tag. With master.gnome.org and ftpadmin being in production for literally ages, we wanted to find a better mechanism to release GNOME software and avoid a single maintainer SSH key leak to allow a possible attacker to tamper tarballs and potentially compromise milions of computers running GNOME around the globe. With this change we don’t leverage SSH anymore and most importantly we don’t allow maintainers to generate GNOME modules tarballs on their personal computers rather we force them to use CI/CD in order to achieve the same result. We’ll be coming up shortly with a dedicated and isolated runner that will only build jobs tagged as releasing GNOME software.
  10. We retired our mirroring infrastructure based on Mirrorbits and replaced it with our CDN partner, CDN77
  11. We decoupled GIMP mirroring service from GNOME’s one, GIMP now hosts its tarballs (and associated rsync daemon) on top of a different master node, thanks OSUOSL for sponsoring the VM that makes this possible!

2.2. Minor achievements

  1. Retired multiple VMs: splunk, nsd0{1,2}, master, ceph-metrics, gitaly
  2. We started managing our DNS using an API and CI/CD jobs hosted in GitHub (this to avoid relying on GNOME’s GitLab which in case of unavailability would prevent us to update DNS entries)
  3. We migrated smtp.gnome.org to OSCI in order to not lose IP reputations and various whitelists we received throughout the years by multiple organizations
  4. We deprecated our former internal DNS authoritatives based on FreeIPA. We are now leveraging internal VPC resolvers and Route53 Private zones
  5. We deprecated all our OSUOSL GitLab runners due to particularly slow IO and high steal time and replaced them with a new Heztner EX44 instance, kindly sponsored by GIMP. OSUOSL is working on coming up with local storage on their Openstack platform. We are looking forward to test that and introduce new runners as soon as the solution will be made available
  6. Retired idm0{1,2} and redirected them to a new FreeIPA load balanced service at https://idm.gnome.org
  7. We retired services which weren’t relevant for the community anymore: surveys.gnome.org, roundcube (aka webmail.gnome.org)
  8. We migrated nmcheck.gnome.org to Fastly and are using Synthetic responses to handle HTTP responses to clients
  9. We upgraded to Ansible Automation Platform (AAP) 2.5
  10. As part of the migration to our new AWS based platform, we upgraded Openshift to release 4.17
  11. We received a 2k grant from Microsoft which we are using for an Azure ARM64 GitLab runner
  12. All of our GitLab runners fleet are now hourly kept in sync using AAP (Ansible roles were built to make this happen)
  13. We upgraded Cachet to 3.x series and fixed dynamic status.gnome.org updates (via a customized version of cachet-monitor)
  14. OS Currency: we upgraded all our systems to RHEL 9
  15. We converted all our Openshift images that were using a web server to Nginx for consistency/simplicity
  16. Replaced NRPE with Prometheus metrics based logging, checks such as IDM replication and status are now handled via the Node Exporter textfile plugin
  17. Migrated download.qemu.org (yes, we also host some components of QEMU’s Infrastructure) to use nginx-s3-gateway, downloads are then served via CDN77

2.3 Minor annoyances/bugs that were also fixed in 2024

  1. Invalid OCSP responses from CDN77, https://gitlab.gnome.org/Infrastructure/Infrastructure/-/issues/1511
  2. With the migration to USE_TINI for GitLab, no gpg zombie processes are being generated anymore

2.3. Our brand new and renewed partnerships

  1. From November 2024 and ongoing, AWS will provide sponsorship and funding to the GNOME Project to sustain the majority of its infrastructure needs
  2. Red Hat kindly sponsored subscriptions for RHEL, Openshift, AAP as well as hosting, bandwidth for the GNOME Infrastructure throughout 2024
  3. CDN77 provided unlimited bandwidth / traffic on their CDN offering
  4. Fastly renewed their unlimited bandwidth / traffic plan on their Delivery/Compute offerings
  5. and thanks to OSUOSL, Packet, DigitalOcean, Microsoft for the continued hosting and sponsorship of a set of GitLab runners, virtual machines and ARM builders!

Expressing my gratitude

As I’m used to do at the end of each calendar year, I want to express my gratitude to Bartłomiej Piotrowski for our continued cooperation and also to Stefan Peknik for his continued efforts in developing the GNOME Release Service. We started this journey together many months ago when Stefan was trying to find a topic to base his CS bachelor thesis on. With this in mind I went straight into the argument of replacing ftpadmin with a better technology also in light of what happened with the xz case. Stefan put all his enthusiasm and professionality into making this happen and with the service going into production on the 11th of December 2024 history was made.

That being said, we’re closing this year being extremely close to retire our presence from RAL3 which we expect to happen in January 2025. The GNOME Infrastructure will also send in a proposal to talk at GUADEC 2025, in Italy, to present and discuss all these changes with the community.

Layered Settings

Early on Builder had the concept of layered settings. You had an application default layer the user could control. You also had a project layer which allowed the user to change settings just for that project. But that was about the extent of it. Additionally, these settings were just stored in your normal GSettings data repository so there is no sharing of settings with other project collaborators. Boo!

With Foundry, I’d like to have a bit more flexibility and control. Specifically, I want three layers. One layer for the user’s preferences at the application level. Then project settings which can be bundled with the project by the maintainer for needs specific to the project. Lastly, a layer of user overrides which takes maximum preference.

Of course, it should still continue to use GSettings under the hood because that makes writing application UI rather easy. As mentioned previously, we’ll have a .foundry directory we place within the project with storage for both user and project data. That means we can use a GKeyFile back-end to GSettings and place the data there.

You can git commit your project settings if you’re the maintainer and ensure that your projects conventions are shared to your collaborators.

Of course, since this is all command-line based right now, there are tab-completable commands for this which again, makes unit testing this stuff easier.

# Reads the app.devsuite.foundry.project config-id gsetting
# taking into account all layers
$ foundry settings get project config-id

# Sets the config-id setting for just this user
$ foundry settings set project config-id "'org.example.app.json'"

# Sets the config-id for the project default which might
# be useful if you ship multiple flatpak manifest like GTK does
$ foundry settings set --project project config-id "'org.example.app.json'"

# Or maybe set a default for the app
$ foundry settings set --global project stop-signal SIGKILL

That code is now wired up to the FoundryContext via foundry_context_load_settings().

Next time I hope to cover the various sub-systems you might need in an IDE and how those services are broken down in Foundry.

CMYK me baby one more time!

Did you know that Jpeg supports images in the CMYK colorspace? And that people are actually using them in the wild? This being the case I needed to add support to them into CapyPDF. The development steps are quite simple, first you create a CMYK Jpeg file, then you create a test document that embeds it and finally look at the result in a PDF renderer.

Off to a painter application then. This is what the test image looks like.

Then we update the Jpeg parsing code to detect cmyk images and write the corresponding metadata to the output PDF. What does then end result look like then?

Aaaaand now we have a problem. Specifically one of an arbitrary color remapping. It might seem this is just a case of inverted colors. It's not (I checked), something weirder is going on. For reference Acrobat Reader's output looks identical.

At this point rather than poke things at random and hoping for the best, a good strategy is to get more test data. Since Scribus is pretty much a gold standard on print quality PDF production I went about recreating the test document in it.

Which failed immediately on loading the image.

Here we have Gwenview and Scribus presenting their interpretations of the exact same image. If you use Scribus to generate a PDF, it will convert the Jpeg into some three channel (i.e. RGB) ICC profile.

Take-home exercise

Where is the bug (or a hole in the spec) in this case:

  • The original CMYK jpeg is correct, but Scribus and PDF renderers read it in incorrectly?
  • The original image is incorrect and Gwenview has a separate inverse bug that cancel each other out?
  • The image is correct but the metadata written in the file by CapyPDF is incorrect?
  • The PDF spec has a big chunk of UB here and the final result can be anything?
  • Aliens?
I don't know the correct answer. If someone out there does, do let me know.

Status update, 13/12/24

Its been an interesting and cold month so far. I made a successful trip to the UK, one of the first times I’ve been back in winter and avoided being exposed to COVID19 since the pandemic, so that’s a step forwards.

I’ve been thinking a lot about documentation recently in a few different places where I work or contribute as a volunteer. One such place is within openQA and the GNOME QA initiative, so here’s what’s been happening there recently.

The monthly Linux QA call is one of my 2024 success stories. The goal of the call is to foster collaboration between distros and upstreams, so that we share testing effort rather than duplicating it, and we get issue reports upstream as soon as things break. Through this call I’ve met many of the key people who are do automated testing of GNOME downstream, and we are starting to share ideas for the future.

What I want for GNOME is to be able to run QA tests for any open merge request, so we can spot regressions before they even land. As part of the STF+GNOME+Codethink collaboration we got a working prototype of upstream QA for GNOME Shell, but to move beyond a prototype, we need to build a more solid foundation. The current GNOME Shell prototype has about 100 lines of copy-pasted openQA code to set up the VM, and this would need to be copied into every other GNOME module where we might run QA tests. I very much do not want so many copies of one piece of code.

Screenshot of openQA web UI showing GNOME Tour

I mentioned this in the QA call and Oli Kurz, who is the openQA product owner at openSUSE, proposed that we put the setup logic directly into os-autoinst, which is openQA’s test runner. The os-autoinst code has a bare ‘basetest‘ module which must be customed for the OS under test. Each distro maintains their own infrastructure on top of that to wait for the desktop to start, log in as a user, and so on.

Since most of us test Linux, we can reasonably add a more specific base class specific to Linux, and some further helpers for systemd-based OSes. I love this idea as we could now share improvements between all the different QA teams.

So the base test class can be extended, but how do we document its capabilities? I find openQA’s existing documentation pretty overwhelming as a single 50,000 word document. It’s not feasible for me to totally rework the documentation, but if we’re going to collaborate upstream then we need to have some way to document the new base classes.

Of course I also wrote some GNOME specific documentation for QA; but hidden docs like this are doomed to become obsolete. I began adding a section on testing to the GNOME developer guide, but I’ve had no feedback at all on the merge request, so this effort seems like a dead end.

So what should we do to make the QA infrastructure easier to understand? Let me know your ideas below.

Swans on a canal at sunset

Looking at the problem from another angle, we still lack a collective understanding of what what openQA is and why you might use it. As a small step towards making this clearer, I wrote a comparison of four testing tools which you can read here. And at Oli’s suggestion I proposed a new Wikipedia page for openQA.

Screenshot of Draft:OpenQA page from Wikipedia

Please suggest changes here or in the openQA matrix channel. If you’re reading this and are a Wikipedia reviewer, then I would greatly appreciate a review so we can publish the new page. We could then also add openQA to the Wikipedia “Comparison of GUI testing tools”. Through small efforts like this we can hopefully reduce how much documentation is needed on the GNOME side, as we won’t need to start at “what even is openQA”.

I have a lot more to say about documentation but that will have to wait for next month. Enjoy the festive season and I hope your 2025 gets off to a good start!

#178 Fuzz Testing

Update on what happened across the GNOME project in the week from December 06 to December 13.

GNOME Core Apps and Libraries

TinySPARQL

A filesystem indexer, metadata storage system and search tool.

Sam Thursfield reports

TinySPARQL is the database library that powers GNOME’s desktop search. Thanks to work by Carlos Garnacho, it’s now enrolled for fuzz testing in the OSS Fuzz project. You can see the current set of fuzz tests here.

Maps

Maps gives you quick access to maps all across the world.

mlundblad reports

Maps now uses AdwSpinner widgets, and the icon for adding a place as a favorite has an animation effect when toggling on and off

GJS

Use the GNOME platform libraries in your JavaScript programs. GJS powers GNOME Shell, Polari, GNOME Documents, and many other apps.

ptomato says

In GJS we landed a patch set from Marco Trevisan that gives a big performance boost to accessing GObject properties, like button.iconName or label.useMarkup. Soon, expect further improvements speeding this up even more!

GNOME Development Tools

Sam Thursfield announces

gnome-build-meta now has automatic ref updates, thanks to Jordan Petridis and Abderrahim Kitouni. The updates were previously done manually by release team members. This means that continuous integration of GNOME modules happens more efficiently than ever.

An “update refs” merge request is generated twice daily, by the gnome-build-meta-bot. The CI tests that this builds across 3 architectures, and then one of the gnome-build-meta maintainers simply lets Marge Bot land the update.

We depend on module developers to help keep GNOME building. If you make changes in a module that could break the build, such as adding dependencies or changing how the build system works, please check the updates, and help the release team to fix any issues that come up. Thanks!

Emmanuele Bassi reports

Maintainers of GNOME modules now have access to a new service, integrated to CI pipelines, for releasing new versions of their projects, courtesy of Stefan Peknik and the Infrastructure team. Instead of creating release archives locally, uploading them to a server with scp, and running a script, we now have a service that takes the release archives built on the GNOME infrastructure using CI. The old system is going to be retired by the end of the week, so make sure to update your CI pipeline before the deadline for the GNOME 48.alpha release on January 4, 2025. More details are available on Discourse.

Third Party Projects

slaclau says

I’ve been working on some reusable calendar widgets based on Gnome Calendar and have put them together as a library. I’ve tagged an initial release as 0.1.0 (https://github.com/slaclau/gtkcal/releases/tag/0.1.0) so I can use them in another project but there are no published binaries (yet). The current working name is GtkCal.

Jan-Michael Brummer reports

Saldo 0.8.0 has been released. Saldo, an easy way to access your online banking via FinTS, has now an improved user interface and offers support for Quick Unlock and fingerprint unlocking. In addiion the official bank list has been updated alongside bug fixes.

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 12, 2024

When should we require that firmware be free?

The distinction between hardware and software has historically been relatively easy to understand - hardware is the physical object that software runs on. This is made more complicated by the existence of programmable logic like FPGAs, but by and large things tend to fall into fairly neat categories if we're drawing that distinction.

Conversations usually become more complicated when we introduce firmware, but should they? According to Wikipedia, Firmware is software that provides low-level control of computing device hardware, and basically anything that's generally described as firmware certainly fits into the "software" side of the above hardware/software binary. From a software freedom perspective, this seems like something where the obvious answer to "Should this be free" is "yes", but it's worth thinking about why the answer is yes - the goal of free software isn't freedom for freedom's sake, but because the freedoms embodied in the Free Software Definition (and by proxy the DFSG) are grounded in real world practicalities.

How do these line up for firmware? Firmware can fit into two main classes - it can be something that's responsible for initialisation of the hardware (such as, historically, BIOS, which is involved in initialisation and boot and then largely irrelevant for runtime[1]) or it can be something that makes the hardware work at runtime (wifi card firmware being an obvious example). The role of free software in the latter case feels fairly intuitive, since the interface and functionality the hardware offers to the operating system is frequently largely defined by the firmware running on it. Your wifi chipset is, these days, largely a software defined radio, and what you can do with it is determined by what the firmware it's running allows you to do. Sometimes those restrictions may be required by law, but other times they're simply because the people writing the firmware aren't interested in supporting a feature - they may see no reason to allow raw radio packets to be provided to the OS, for instance. We also shouldn't ignore the fact that sufficiently complicated firmware exposed to untrusted input (as is the case in most wifi scenarios) may contain exploitable vulnerabilities allowing attackers to gain arbitrary code execution on the wifi chipset - and potentially use that as a way to gain control of the host OS (see this writeup for an example). Vendors being in a unique position to update that firmware means users may never receive security updates, leaving them with a choice between discarding hardware that otherwise works perfectly or leaving themselves vulnerable to known security issues.

But even the cases where firmware does nothing other than initialise the hardware cause problems. A lot of hardware has functionality controlled by registers that can be locked during the boot process. Vendor firmware may choose to disable (or, rather, never to enable) functionality that may be beneficial to a user, and then lock out the ability to reconfigure the hardware later. Without any ability to modify that firmware, the user lacks the freedom to choose what functionality their hardware makes available to them. Again, the ability to inspect this firmware and modify it has a distinct benefit to the user.

So, from a practical perspective, I think there's a strong argument that users would benefit from most (if not all) firmware being free software, and I don't think that's an especially controversial argument. So I think this is less of a philosophical discussion, and more of a strategic one - is spending time focused on ensuring firmware is free worthwhile, and if so what's an appropriate way of achieving this?

I think there's two consistent ways to view this. One is to view free firmware as desirable but not necessary. This approach basically argues that code that's running on hardware that isn't the main CPU would benefit from being free, in the same way that code running on a remote network service would benefit from being free, but that this is much less important than ensuring that all the code running in the context of the OS on the primary CPU is free. The maximalist position is not to compromise at all - all software on a system, whether it's running at boot or during runtime, and whether it's running on the primary CPU or any other component on the board, should be free.

Personally, I lean towards the former and think there's a reasonably coherent argument here. I think users would benefit from the ability to modify the code running on hardware that their OS talks to, in the same way that I think users would benefit from the ability to modify the code running on hardware the other side of a network link that their browser talks to. I also think that there's enough that remains to be done in terms of what's running on the host CPU that it's not worth having that fight yet. But I think the latter is absolutely intellectually consistent, and while I don't agree with it from a pragmatic perspective I think things would undeniably be better if we lived in that world.

This feels like a thing you'd expect the Free Software Foundation to have opinions on, and it does! There are two primarily relevant things - the Respects your Freedoms campaign focused on ensuring that certified hardware meets certain requirements (including around firmware), and the Free System Distribution Guidelines, which define a baseline for an OS to be considered free by the FSF (including requirements around firmware).

RYF requires that all software on a piece of hardware be free other than under one specific set of circumstances. If software runs on (a) a secondary processor and (b) within which software installation is not intended after the user obtains the product, then the software does not need to be free. (b) effectively means that the firmware has to be in ROM, since any runtime interface that allows the firmware to be loaded or updated is intended to allow software installation after the user obtains the product.

The Free System Distribution Guidelines require that all non-free firmware be removed from the OS before it can be considered free. The recommended mechanism to achieve this is via linux-libre, a project that produces tooling to remove anything that looks plausibly like a non-free firmware blob from the Linux source code, along with any incitement to the user to load firmware - including even removing suggestions to update CPU microcode in order to mitigate CPU vulnerabilities.

For hardware that requires non-free firmware to be loaded at runtime in order to work, linux-libre doesn't do anything to work around this - the hardware will simply not work. In this respect, linux-libre reduces the amount of non-free firmware running on a system in the same way that removing the hardware would. This presumably encourages users to purchase RYF compliant hardware.

But does that actually improve things? RYF doesn't require that a piece of hardware have no non-free firmware, it simply requires that any non-free firmware be hidden from the user. CPU microcode is an instructive example here. At the time of writing, every laptop listed here has an Intel CPU. Every Intel CPU has microcode in ROM, typically an early revision that is known to have many bugs. The expectation is that this microcode is updated in the field by either the firmware or the OS at boot time - the updated version is loaded into RAM on the CPU, and vanishes if power is cut. The combination of RYF and linux-libre doesn't reduce the amount of non-free code running inside the CPU, it just means that the user (a) is more likely to hit since-fixed bugs (including security ones!), and (b) has less guidance on how to avoid them.

As long as RYF permits hardware that makes use of non-free firmware I think it hurts more than it helps. In many cases users aren't guided away from non-free firmware - instead it's hidden away from them, leaving them less aware that their freedom is constrained. Linux-libre goes further, refusing to even inform the user that the non-free firmware that their hardware depends on can be upgraded to improve their security.

Out of sight shouldn't mean out of mind. If non-free firmware is a threat to user freedom then allowing it to exist in ROM doesn't do anything to solve that problem. And if it isn't a threat to user freedom, then what's the point of requiring linux-libre for a Linux distribution to be considered free by the FSF? We seem to have ended up in the worst case scenario, where nothing is being done to actually replace any of the non-free firmware running on people's systems and where users may even end up with a reduced awareness that the non-free firmware even exists.

[1] Yes yes SMM

comment count unavailable comments

IPU6 camera support is broken in kernel 6.11.11 / 6.12.2-6.12.4

Unfortunately an incomplete backport of IPU6 DMA handling changes has landed in kernel 6.11.11.

This not only causes IPU6 cameras to not work, this causes the kernel to (often?) crash on boot on systems where the IPU6 is in use and thus enabled by the BIOS.

Kernels 6.12.2 - 6.12.4 are also affected by this. A fix for this is pending for the upcoming 6.12.5 release.

6.11.11 is the last stable release in the 6.11.y series, so there will be no new stable 6.11.y release with a fix.

As a workaround users affected by this can stay with 6.11.10 or 6.12.1 until 6.12.5 is available in your distributions updates(-testing) repository.



comment count unavailable comments

Android privacy improvements break key attestation

Sometimes you want to restrict access to something to a specific set of devices - for instance, you might want your corporate VPN to only be reachable from devices owned by your company. You can't really trust a device that self attests to its identity, for instance by reporting its MAC address or serial number, for a couple of reasons:
  • These aren't fixed - MAC addresses are trivially reprogrammable, and serial numbers are typically stored in reprogrammable flash at their most protected
  • A malicious device could simply lie about them
If we want a high degree of confidence that the device we're talking to really is the device it claims to be, we need something that's much harder to spoof. For devices with a TPM this is the TPM itself. Every TPM has an Endorsement Key (EK) that's associated with a certificate that chains back to the TPM manufacturer. By verifying that certificate path and having the TPM prove that it's in posession of the private half of the EK, we know that we're communicating with a genuine TPM[1].

Android has a broadly equivalent thing called ID Attestation. Android devices can generate a signed attestation that they have certain characteristics and identifiers, and this can be chained back to the manufacturer. Obviously providing signed proof of the device identifier is kind of problematic from a privacy perspective, so the short version[2] is that only apps installed using a corporate account rather than a normal user account are able to do this.

But that's still not ideal - the device identifiers involved included the IMEI and serial number of the device, and those could potentially be used to correlate devices across privacy boundaries since they're static[3] identifiers that are the same both inside a corporate work profile and in the normal user profile, and also remains static if you move between different employers and use the same phone[4]. So, since Android 12, ID Attestation includes an "Enterprise Specific ID" or ESID. The ESID is based on a hash of device-specific data plus the enterprise that the corporate work profile is associated with. If a device is enrolled with the same enterprise then this ID will remain static, if it's enrolled with a different enterprise it'll change, and it just doesn't exist outside the work profile at all. The other device identifiers are no longer exposed.

But device ID verification isn't enough to solve the underlying problem here. When we receive a device ID attestation we know that someone at the far end has posession of a device with that ID, but we don't know that that device is where the packets are originating. If our VPN simply has an API that asks for an attestation from a trusted device before routing packets, we could pass that on to said trusted device and then simply forward the attestation to the VPN server[5]. We need some way to prove that the the device trying to authenticate is actually that device.

The answer to this is key provenance attestation. If we can prove that an encryption key was generated on a trusted device, and that the private half of that key is stored in hardware and can't be exported, then using that key to establish a connection proves that we're actually communicating with a trusted device. TPMs are able to do this using the attestation keys generated in the Credential Activation process, giving us proof that a specific keypair was generated on a TPM that we've previously established is trusted.

Android again has an equivalent called Key Attestation. This doesn't quite work the same way as the TPM process - rather than being tied back to the same unique cryptographic identity, Android key attestation chains back through a separate cryptographic certificate chain but contains a statement about the device identity - including the IMEI and serial number. By comparing those to the values in the device ID attestation we know that the key is associated with a trusted device and we can now establish trust in that key.

"But Matthew", those of you who've been paying close attention may be saying, "Didn't Android 12 remove the IMEI and serial number from the device ID attestation?" And, well, congratulations, you were apparently paying more attention than Google. The key attestation no longer contains enough information to tie back to the device ID attestation, making it impossible to prove that a hardware-backed key is associated with a specific device ID attestation and its enterprise enrollment.

I don't think this was any sort of deliberate breakage, and it's probably more an example of shipping the org chart - my understanding is that device ID attestation and key attestation are implemented by different parts of the Android organisation and the impact of the ESID change (something that appears to be a legitimate improvement in privacy!) on key attestation was probably just not realised. But it's still a pain.

[1] Those of you paying attention may realise that what we're doing here is proving the identity of the TPM, not the identity of device it's associated with. Typically the TPM identity won't vary over the lifetime of the device, so having a one-time binding of those two identities (such as when a device is initially being provisioned) is sufficient. There's actually a spec for distributing Platform Certificates that allows device manufacturers to bind these together during manufacturing, but I last worked on those a few years back and don't know what the current state of the art there is

[2] Android has a bewildering array of different profile mechanisms, some of which are apparently deprecated, and I can never remember how any of this works, so you're not getting the long version

[3] Nominally, anyway. Cough.

[4] I wholeheartedly encourage people not to put work accounts on their personal phones, but I am a filthy hypocrite here

[5] Obviously if we have the ability to ask for attestation from a trusted device, we have access to a trusted device. Why not simply use the trusted device? The answer there may be that we've compromised one and want to do as little as possible on it in order to reduce the probability of triggering any sort of endpoint detection agent, or it may be because we want to run on a device with different security properties than those enforced on the trusted device.

comment count unavailable comments

December 11, 2024

GNOME Asia India 2024

Namaste Everyone!

Hi everyone, it was that time of the year again when we had our beloved GNOME Asia happening.

Last year GNOME Asia happened in Kathmandu Nepal from December 1 - 3 and this time it happened in my country in Bengaluru from 6th to 8th.

Btw, a disclaimer - I was there on behalf of Ubuntu but the opinions over here are my own :)

Also, this one might not be that interesting due to well... reasons.

Day 0 (Because indexing starts with 0 ;))

Before departing from India... oh, I forgot this one was in India only haha.

This GNOME Asia had a lot of drama, with the local team requiring an NDA to sign which we got to know only hours before the event and we also got to know we couldn't host an Ubuntu release party there even when it was agreed to months and again a few weeks ago and even on the same day as well in advance... So yeah... it was no less than an India Daily soap episode, which is quite ironic lol.

But, in the end, I believe the GNOME team would have not known about it as well, and felt like local team problems.

Enough with the rant, it was not all bad, I got to meet some of my GNOMEies and Ubunties (is that even a word?) friends upon arriving, and man did we had a blast.

We hijacked a cafe and sat there till around 1 A.M. and laughed so hard we might have been termed Psychopaths by the watchers.

But what do we care, we were there for the sole purpose of having as much fun as we could.

After returning, I let my inner urge win and dived into the swimming pool on the hotel rooftop, at 2 A.M. in winter. Talk about the will to do anything ;)

Day 1

Upon proceeding to the venue we were asked for corporate ID cards as the event was in the Red Hat office inside a corporate park. We didn't know this and thus had to travel 2 more K.M. to the main entrance and get a visitor pass. Had to give an extra tip to the cab so that he wouldn't give me the look haha.

Upon entering the tech park, I got to witness why Bengaluru is often termed India's Silicon Valley. It was just filled with companies of every type and size so that was a sight to behold.

The talk I loved that day was "Build A GNOME Community? Yes You Can." by Aaditya Singh, full of insights and fun, we term each other as Bhai (Hindi for Brother) so it was fun to attend his talk.

This time I wasn't able to attend many of the talks as I now had the responsibility to explore a new venue for our release party.

Later I and my friends took a detour to find the new venue, and we did it quite quickly about 400 metres away from the office.

This venue had everything we needed, a great environment, the right "vibe", and tons of freedom, which we FOSS lovers of course love and cherish.

It also gave us the freedom to no longer be restricted to event end, but to shift it up to the Lunch break.

At night me, Fenris and Syazwan went to "The Rameshwaram Cafe" which is very famous in Bengaluru, and rightly so, the taste was really good and for the fame not that expensive either.

Fenris didn't eat much as he still has to sober up to Indian dishes xD.

Day 2

The first talk was by Syazwan and boy did I have to rush to the venue to attend it.

Waking up early is not easy for me hehe but his talks are always so funny, engaging and insightful that you just can't miss attending it live.

After a few talks came my time to present on the topic “Linux in India: A perspective of how it is and what we can do to improve it.”

Where we discussed all the challenges faced by us in boosting the market share of Linux and open source in India and what measures we could take to improve the situation.

We also glimpsed over the state of Ubuntu India LoCo and the actions we are taking to reboot it, with multiple events like the one we just conducted.

My talk can be viewed at - YouTube - Linux in India: A perspective of how it is and what we can do to improve it.

And that was quite fun, I loved the awesome feedback I got and it is just amazing to see people loving your content. We then quickly rushed to the venue of the party, track 1 was already there and with us, we took track 2 peeps as well.

To celebrate we cut cake and gave out some Ubuntu flavours stickers, Ubuntu 24.10 Oracular Oriole stickers and UbuCon Asia 2024 stickers followed by a delicious mix of vegetarian and non-vegetarian pizzas.

Despite the short duration of just one hour during lunch, the event created a warm and welcoming space for attendees, encapsulating Ubuntu’s philosophy: “Making technology human” and “Linux for human beings.”

The event was then again followed by GNOME Asia proceedings.

At night we all Ubunties and GNOMEies and Debian grouped for Biryani dinner. We first hijacked the Biryani place and then moved on to hijacking another Cafe. The best thing was that none of them kicked us out, I seriously believed they would considering our activities lol. I for the first time played Jenga and we had a lot of jokes which I can't say in public for good reasons.

At that place, the GNOME CoC wasn't considered haha.

Day 3

Day 3 was a social visit, the UbuCon Asia 2025 organising team members conducted our own day trip, exploring the Technology Museum, Beautiful Cubbon Park, and the magnificent Vidhana Soudha of Karnataka.

I met my friend Aman for the first time since GNOME Asia Malaysia which was Awesome! And I also met my Outreachy mentee in person, which was just beautiful.

The 3-day event was made extremely joyful due to meeting old friends and colleagues. It reminded me of why we have such events so that we can group the community more than ever and celebrate the very ethos of FOSS.

As many of us got tired and some had flights, the day trip didn't last long, but it was nice.

At night I had one of my best coffees ever and tried "Plain Dosa with Mushroom curry" a weird but incredibly tasty combo.

End

Special thanks to Canonical for their CDA funding, which made it possible for me to attend in person and handle all arrangements on very short notice. :smiley:

Looking forward to meeting many of them again at GUADEC or GNOME Asia 2025 :D

Publish Your Godot Engine Game to Flathub

If you follow me on the fediverse (@cassidy@blaede.family), you may have seen me recently gushing about ROTA, a video game I recently discovered. Besides the absolutely charming design and ridiculously satisfying gameplay, the game itself is open source, meaning the developer has published the game’s underlying code out to the world for anyone to see, learn from, and adapt.

Screenshot of ROTA, a colorful 2D platformer

As someone passionate about the Linux desktop ecosystem broadly and Flathub as an app store specifically, I was excited by the possibility of helping to get ROTA onto Flathub so more people could play it—plus, such a high-quality game being on Flathub helps the reputation and image of Flathub itself. So I kicked off a personal project (with the support of my employer¹) to get it onto Flathub—and I learned a lot—especially what steps were confusing or unclear.

As a result, here’s how I recommend publishing your Godot Engine game to Flathub. Oh, and don’t be too scared; despite the monumental size of this blog post, I promise it’s actually pretty easy! 😇

Overview

Let’s take a look at what we’re going to achieve at a high level. This post assumes you have source code for a game built with a relatively recent version of Godot Engine (e.g. Godot Engine 3 or 4), access to a Linux computer or VM for testing, and a GitHub account. If you’re missing one of those, get that sorted before continuing! You can also check the list of definitions at the bottom of this page for reference if you need to better understand something, and be sure to check out the Flathub documentation for a lot more details on Flatpak publishing in general.

Illustration with the Godot Engine logo, then an arrow pointing to the Flathub logo

To build a Flatpak of a Godot Engine game, we only need three things:

  1. Exported PCK file
  2. Desktop Entry, icon, and MetaInfo files
  3. Flatpak manifest to put it all together

The trick is knowing how and where to provide each of these for the best experience publishing your game (and especially updates) to Flathub. There are a bunch of ways you can do it, but I strongly recommend:

  1. Upload your PCK file to a public, versioned URL, e.g. as a source code release artifact.

  2. Include the Desktop Entry, icon, and MetaInfo files in the repo with your game’s source code if it’s open source, or provide them via a dedicated repo, versioned URL, or source code release artifact.

    You can alternatively upload these directly to the Flatpak Manifest repository created by Flathub, but it’s better to keep them with your game’s other files if possible.

  3. Your manifest will live in a dedicated GitHub repo owned by the Flathub org. It’s nice (but not required) to also include a version of your manifest with your game’s source code for easier development and testing.

Before we get into each of those steps in more detail, you will need to pick an app ID for your game. This is a unique machine-oriented (not intended for humans to need to know) ID used across the Linux desktop and throughout the Flatpak process. It must be in valid reverse domain name notation (RDNN) format for a domain or code hosting account associated with the game; for example, if your website is example.com, the ID should begin with com.example. I strongly recommend using your own domain name rather than an io.itch. or io.github. prefix here, but ultimately it is up to you. Note that as of writing, Itch.io-based IDs cannot be verified on Flathub.

1. Handling Your PCK File

When you export a Godot Engine game for PC, you’re actually creating a platform-agnostic PCK file that contains all of your game’s code and assets, plus any plugins and libraries. The export also provides a copy of the platform-specific binary for your game which—despite its name—is actually just the Godot Engine runtime. The runtime simply looks for a PCK file of the same name sitting on disk next to it, and runs it. If you’re familiar with emulating retro games, you can think of the binary file as the Godot “emulator”, and the PCK file as your game’s “ROM.”

To publish to Flathub, we’ll first need your game’s exported PCK file accessible somewhere on the web via a public, versioned URL. We’ll include that URL in the Flatpak manifest later so Flatpak Builder knows where to get the PCK file to bundle it with the Godot Engine binary into a Flatpak. Technically any publicly-accessible URL works here, but if your game is open source, I highly recommend you attach the PCK file as a release artifact wherever your source code is hosted (e.g. GitHub). This is the most similar to how open source software is typically released and distributed, and will be the most familiar to Flathub reviewers as well as potential contributors to your game.

No matter where you publish your PCK file, the URL needs to be public, versioned, and stable: Flatpak Builder should always get the exact same file when hitting that URL for that release, and if you make a new release of your game, that version’s PCK file needs to be accessible at a new URL. I highly recommend semantic versioning for this, but it at least needs to be incrementally versioned so it’s always obvious to Flathub reviewers which version is newest, and so it matches to the version in the MetaInfo (more on that later). Match your game’s regular versioning scheme if possible.

Bonus Points: Export in CI

Since Godot Engine is open source and has command-line tools that run on Linux, you can use a source code platform’s continuous integration (CI) feature to automatically export and upload your PCK file. This differs a bit depending on your source code hosting platform and Godot Engine version, but triggered by a release, you run a job to:

  1. Grab the correct version of the Godot Engine tools binary from their GitHub release
  2. Export the PCK file from the command line (Godot Docs)
  3. Upload that PCK file to the release itself

This is advantageous because it ensures the PCK file attached to the release is exported from the exact code from in the release, increasing transparency and reducing the possibility of human error. Here is one example of such a CI workflow.

About That Binary…

Since the exported binary file is specific to the platform and Godot Engine version but not to your game, you do not need to provide it when publishing to Flathub; instead, Flathub builds Godot Engine runtime binaries from the Godot Engine source code for each supported version and processor architecture automatically. This means you just provide the PCK file and specify the Godot Engine version; Flathub will build and publish your Flatpak for 64-bit Intel/AMD PCs, 64-bit ARM computers, and any supported architectures in the future.

2. Desktop Entry, Icon, and MetaInfo Files

Desktop Entry and MetaInfo are FreeDesktop.org specifications that ensure Linux-based OSes interoperate; for our purposes, you just need to know that a Desktop Entry is what makes your game integrate on Linux (e.g. show in the dock, app menus, etc.), while MetaInfo provides everything needed to represent an app or game in an app store, like Flathub.

Writing them is simple enough, especially given an example to start with. FreeDesktop.org has a MetaInfo Creator web app that can even generate a starting point for you for both, but note that for Flathub:

  • The icon name given must match the app ID, which the site lists as a “Unique Software Identifier”

  • The “Executable Name” will be godot-runner for Godot Engine games

If included in your source code repository, I recommend storing these files in the project root (or in a linux/ folder) as YOUR.APP.ID.desktop, YOUR.APP.ID.metainfo.xml, and, if it doesn’t exist in a suitable format somewhere else in the repo, YOUR.APP.ID.png.

If your game is not open source or these files are not to be stored in the source code repository, I recommend storing and serving these files from the same versioned web location as your game’s PCK file.

Here are some specifics and simple examples from the game ROTA to give you a better idea:

Desktop Entry

You’ll only ever need to set Name, Comment, Categories, and Icon. See the Additional Categories spec for what you can include in addition to the Game category. Note the trailing semicolon!

[Desktop Entry]
Name=ROTA
Comment=Gravity bends beneath your feet
Categories=Game;KidsGame;
Icon=net.hhoney.rota
Exec=godot-runner
Type=Application
Terminal=false
net.hhoney.rota.desktop

Icon

This is pretty straightforward; you need an icon for your game! This is used to represent your game both for app stores like Flathub.org and the native app store clients on players’ computers, plus as the launcher icon e.g. on the player’s desktop or dock.

Screenshot of ROTA, a colorful 2D platformer

ROTA's icon in the GNOME Dash

If your game is open source, it’s easy enough to point to the same icon you use for other platform exports. If you must provide a unique icon for Flathub (e.g. for size or style reasons), you can include that version in the same place as your Desktop Entry and MetaInfo files. The icon must be a square aspect ratio as an SVG or 256×256 pixel (or larger) PNG.

MetaInfo

I won’t cover absolutely everything here (see the Flathub docs covering MetaInfo Guidelines for that), you should understand a few things about MetaInfo for your game.

The top-most id is your game’s app ID, and must be in valid RDNN format as described above. You should also use the same prefix for the developer id to ensure all of your apps/games are associated with one another.

Screenshots should be at stable URLs; e.g. if pointing to a source code hosting service, make sure you’re using a tag (like 1.0.0) or commit (like 6c7dafea0993700258f77a2412eef7fca5fa559c) in the URL rather than a branch name (like main). This way the right screenshots will be included for the right versions, and won’t get incorrectly cached with an old version.

You can provide various URLs to link people from your game’s app store listing to your website, an issue tracker, a donation link, etc. In the case of the donation link, the Flathub website displays this prominently as a button next to the download button.

Branding colors and screenshots are some of your post powerful branding elements! Choose colors that compliment (but aren’t too close to) your game’s icon. For screenshots, include a caption related to the image to be shown below it, but do not include marketing copy or other graphics in the screenshots themselves as they may be rejected.

Releases must be present, and are required to have a version number; this must be an incrementing version number as Flatpak Builder will use the latest version here to tag the build. I strongly recommend the simple Semantic Versioning format, but you may prefer to use a date-based 2024.12.10 format. These release notes show on your game’s listing in app stores and when players get updates, so be descriptive—and fun!

Content ratings are developer-submitted, but may be reviewed by Flathub for accuracy—so please, be honest with them. Flathub uses the Open Age Ratings Service for the relevant metadata; it’s a free, open source, and straightforward survey that spits out the proper markup at the end.

This example is pretty verbose, taking advantage of most features available:

<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
  <id>net.hhoney.rota</id>
  
  <name>ROTA</name>
  <summary>Gravity bends beneath your feet</summary>

  <developer id="net.hhoney">
    <name translatable="no">HHoney Software</name>
  </developer>

  <description>
    <p>Move blocks and twist gravity to solve puzzles. Collect all 50 gems and explore 8 vibrant worlds.</p>
  </description>

  <content_rating type="oars-1.1">
    <content_attribute id="violence-cartoon">mild</content_attribute>
  </content_rating>
  
  <url type="homepage">https://hhoney.net</url>
  <url type="bugtracker">https://github.com/HarmonyHoney/ROTA/issues</url>
  <url type="donation">https://ko-fi.com/hhoney</url>

  <branding>
    <color type="primary" scheme_preference="light">#ff99ff</color>
    <color type="primary" scheme_preference="dark">#850087</color>
  </branding>

  <screenshots>
    <screenshot type="default">
      <image>https://raw.githubusercontent.com/HarmonyHoney/ROTA/6c7dafea0993700258f77a2412eef7fca5fa559c/media/image/assets/screens/1.png</image>
      <caption>Rotate gravity as you walk over the edge!</caption>
    </screenshot>
    <screenshot>
      <image>https://raw.githubusercontent.com/HarmonyHoney/ROTA/6c7dafea0993700258f77a2412eef7fca5fa559c/media/image/assets/screens/2.png</image>
      <caption>Push, pull and rotate gravity-blocks to traverse the stage and solve puzzles</caption>
    </screenshot>
    <screenshot>
      <image>https://raw.githubusercontent.com/HarmonyHoney/ROTA/6c7dafea0993700258f77a2412eef7fca5fa559c/media/image/assets/screens/3.png</image>
      <caption>Collect all 50 gems to unlock doors and explore 8 vibrant worlds!</caption>
    </screenshot>
  </screenshots>

  <releases>
    <release version="1.0" date="2022-05-07T22:18:44Z">
      <description>
        <p>Launch Day!!</p>
      </description>
    </release>
  </releases>

  <launchable type="desktop-id">net.hhoney.rota.desktop</launchable>
  <metadata_license>CC0-1.0</metadata_license>
  <project_license>Unlicense</project_license>
</component>
net.hhoney.rota.metainfo.xml

Bonus Points: Flathub Quality Guidelines

Beyond Flathub’s base requirements for publishing games are their Quality Guidelines. These are slightly more opinionated human-judged guidelines that, if met, make your game eligible to be featured in the banners on the Flathub.org home page, as a daily-featured app, and in other places like in some native app store clients. You should strive to meet these guidelines if at all possible!

Screenshot of Flathub.org with a large featured banner for Crosswords

Crosswords, a featured game on Flathub, meets the quality guidelines

One common snag is the icon: generally Flathub reviewers are more lenient with games, but if you need help meeting the guidelines for your Flathub listing, be sure to reach out on the Flathub Matrix chat or Discourse forum.

3. Flatpak manifest

Finally, the piece that puts it all together: your manifest! This can be a JSON or YAML file, but is named the same as your game’s app ID.

The important bits that you’ll need to set here are the id (again matching the app ID), base-version for the Godot Engine version, the sources for where to get your PCK, Desktop Entry, MetaInfo, and icon files (in the below example, a source code repository and a GitHub release artifact), and the specific build-commands that describe where in the Flatpak those files get installed.

In the build-commands, be sure to reference the correct location for each file. You can also use these commands to rename any files, if needed; in the below example, the Desktop Entry and MetaInfo files are in a linux/ folder in the project source code, while the icon is reused (and renamed) from a path that was already present in the repo. You can also use ${FLATPAK_ID} in file paths to avoid writing the ID over and over.

For the supported Godot Engine versions, check the available branches of the Godot Engine BaseApp.

For git sources, be sure to point to a specific commit hash; I also prefer to point to the release tag as well (e.g. with tag: v1.2.3) for clarity, but it’s not strictly necessary. For file sources, be sure to include a hash of the file itself, e.g. sha256: a89741f…). For a file called export.pck, you can generate this on Linux with sha256sum export.pck; on Windows with CertUtil -hashfile export.pck sha256.

id: net.hhoney.rota
runtime: org.freedesktop.Platform
runtime-version: '24.08'
base: org.godotengine.godot.BaseApp
base-version: '3.6'
sdk: org.freedesktop.Sdk
command: godot-runner

finish-args:
  - --share=ipc
  - --socket=x11
  - --socket=pulseaudio
  - --device=all

modules:
  - name: rota
    buildsystem: simple

    sources:
      - type: git
        url: https://github.com/HarmonyHoney/ROTA.git
        commit: be542fa2444774fe952ecb22d5056a048399bc25

      - type: file
        url: https://github.com/HarmonyHoney/ROTA/releases/download/something/ROTA.pck
        sha256: a89741f56eb6282d703f81f907617f6cb86caf66a78fce94d48fb5ddfd65305c

    build-commands:
      - install -Dm644 ROTA.pck ${FLATPAK_DEST}/bin/godot-runner.pck
      - install -Dm644 linux/${FLATPAK_ID}.desktop ${FLATPAK_DEST}/share/applications/${FLATPAK_ID}.desktop
      - install -Dm644 linux/${FLATPAK_ID}.metainfo.xml ${FLATPAK_DEST}/share/metainfo/${FLATPAK_ID}.metainfo.xml
      - install -Dm644 media/image/icon/icon256.png ${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/${FLATPAK_ID}.png

net.hhoney.rota.yml

Once you have your manifest file, you’re ready to test it and submit your game to Flathub. To test it, follow the instructions at that link on a Linux computer (or VM); you should be able to point Flatpak Builder to your manifest file for it to grab everything and build a Flatpak of your game.

The Flathub Submission PR process is a bit confusing; you’re just opening a pull request against a specific new-pr branch on GitHub that adds your manifest file; Flathub will then human-review it and run automated tests on it to make sure it all looks good. They’ll provide feedback on the PR if needed, and then if it’s accepted, a bot will create a new repo on the Flathub org just for your game’s manifest. You’ll automatically have the correct permissions on this repo to be able to propose PRs to update the manifest, and merge them once they pass automated testing.

Please be sure to test your manifest before submitting so you don’t end up wasting reviewers’ time. 🙏

You Did It!

You published your game to Flathub! Or at least you made it this far in the blog post; either way, that’s a win.

I know this was quite the slog to read through; my hope is that it can serve as a reference for game developers out there. I’m also interested in adapting it into documentation for Flatpak, Flathub, and/or Godot Engine—but I wasn’t sure where it would fit and in what format. If you’d like to adapt any of this post into proper documentation, please feel free to do so!

If you spot something wrong or just want to reach out, hit me up using any of the links in the footer.

Bonus Points: Publishing Updates

When I wrapped this blog post up, I realized I missed mentioning how to handle publishing updates to your game on Flathub. While I won’t go into great detail here, the gist is:

  1. Update your MetaInfo file with the new release version number, timestamp, and release notes; publish this either in your source code repo or alongside the PCK file; if you have new screenshots, be sure to update those URLs in the MetaInfo file, too!

  2. Export a new PCK file of your release, uploading it to a public, stable URL containing the new version number (e.g. a GitHub release)

  3. Submit a pull request against your Flatpak manifest’s GitHub repo, pointing the manifest at new versioned locations of your files; be sure to update the file hashes as well!

After passing automated tests, a bot will comment on the PR with command to test your Flatpak. Do this as the resulting Flatpak is what will be published to players after the PR is merged. If it all looks good, merge it, and you’re set! If not, repeat the above steps until everything is as expected. :)



Definitions

There are a lot of terms and technologies involved on both the Godot Engine and Flathub side, so here are some brief definitions. Don’t worry if you don’t fully understand each of these, and you can always use this as a cheat sheet to refer back to.

Godot Engine

Open source game engine that includes the editor (the actual app you use to create a game), tools (command-line tools for exporting a game), and runtime (platform-specific binary distributed with your game which actually runs it)

Export

Prepare your game for distribution; Godot Engine’s export workflow packages up your game’s code, assets, libraries, etc. and turns it into a playable game.

PCK File

The platform-agnostic result of a Godot Engine export to use along with the platform-specific runtime. Contains all of your game’s code, assets, etc. packed up with a .pck extension.

Flatpak

App/game packaging format for Linux that works across nearly every different Linux distribution. An important design of Flatpak is that it is sandboxed, which keeps each app or game from interfering with one another and helps protect players’ privacy.

Flathub

The de facto Linux app store with thousands of apps and games, millions of active users, and a helpful community of open source people like me! It uses Flatpak and other open standards to build, distribute, and update apps and games.

Flatpak Manifest

A structured file (in JSON or YAML format) that tells Flatpak how to package your game, including where to get the game itself from. Flathub hosts the manifest files for apps and games on their GitHub organization, regardless of where your game is developed or hosted.

Flatpak Builder

Command-line tool that takes a Flatpak manifest and uses it to create an actual Flatpak. Used for local testing, CI workflows, and Flathub itself.

Flatpak BaseApp

Shared base for building a Flatpak; i.e. all Godot 3.6 games can use the same BaseApp to simplify the game’s manifest, and Flatpak Builder will take care of the common Godot 3.6-specific bits.

Desktop Entry

A simple INI-like file that determines how your game shows up on Linux, i.e. its name, icon, and categories.

MetaInfo

Open standard for describing apps and games to be displayed in app stores; used by Flathub and Linux app store clients to build your game’s listing page.

App ID

A unique ID for your game in reverse domain name notation (RDNN), based on a valid web domain or source code hosting account you control. Required by Flatpak and validated by Flathub to ensure an app or game is what it claims to be.

Flathub Verification

Optional (but highly recommended!) process to verify that your game on Flathub is published by you. Uses your game’s app ID to verify ownership of your domain or source code hosting account.

December 09, 2024

Introducing Your Favorite Neighborhood Software Engineer (GNOME Outreachy Intern)…Anointing

My Journey to Becoming a GNOME Outreachy Intern

Hello everyone! You might be curious about how my personal blog found its way onto the renowned GNOME blog site. Before I share that story, let me introduce myself and my journey.

About myself

My name is Adetoye Anointing, and I’m a Computer Science graduate with a passion for technology, history, and creativity. I’m a former Google Developer Student Club Lead  now called GDG On Campus, hobbyist photographer, anime enthusiast, and lover of superhero movies.

I’ve been a software engineer for over three years. Like many, my journey started with the ever-popular “Hello, World!” in HTML. Initially, I aspired to become a security engineer, but without proper guidance or reliable internet, it was challenging. However, I discovered Python during this time, which opened the door to backend engineering and eventually software engineering

Later, After gaining foundational skills in Python, I realized I wanted to explore more efficient and modern languages. That’s when I discovered Go (Golang) through Google and roadmap.sh. I created a plan, stuck to it, and that marked the start of a fulfilling tech career. Along the way, I’ve contributed to various open-source projects and built meaningful connections in tech communities and subsequent picked up Rust.

My long-term aspirations include becoming a Site Reliability Engineer at Google, owning an Aston Martin Vantage, and contributing to complex infrastructure and blockchain projects.

Core Value

As much as I will like to give in-depth views on my core value, I will keep it simple, my core values are:

  • COMMUNITY : I owe much of my growth to tech communities. Joining the Google Developer Community was a turning point in my career, providing support, guidance, and opportunities. I also discovered Outreachy through Open Source Community Africa (OSCAFEST). I always encourage newcomers to join a community—it’s a powerful catalyst for growth.
  • OPENNESS: I believe in lifelong learning and the power of feedback.
    This mindset drives me to learn from my mistakes, seek feedback, and absorb knowledge from those around me.
  • DETERMINATION: Setting clear, concrete goals is vital. Determination fuels progress, keeps you going through tough times, and ensures results. It’s this value that motivated me to persist with my Outreachy applications until I was finally accepted.

If not for these core values, I wouldn’t have persisted with my Outreachy applications, let alone been accepted into this incredible program.

So, how did I end up with my name on the GNOME blog site? It started with applying to Outreachy multiple times, finally locking in on the project “Implement the SVG2 Text Layout Algorithm in librsvg.” With the guidance of my amazing mentor, Federico Mena Quintero, and support from Felipe Borges, I was accepted as an Outreachy Intern!

Now, here I am, on day one, with my first blog post published on the GNOME blog site.

I’m thrilled to begin this journey as an Outreachy Intern for GNOME! Over the next few months, I’ll be blogging about my progress, challenges, and achievements. I hope you’ll join me for the ride.

Looking forward to sharing more with you soon!

See you in the next chapter—cheers!

 

December 02, 2024

2024-12-02 Monday

  • Mail chew, 1:1's with Miklos & Lily, lunch. Set off to Paris via the Eurostar.

Announcement: GNOME will have an Outreachy intern working on librsvg

We are excited to announce that the GNOME Foundation is sponsoring an Outreachy internship for the December-March round!

The intern will work with mentor Federico Mena Quintero on the project, “Implement the SVG2 text layout algorithm in librsvg.”

The intern’s blog will soon be added to Planet GNOME, where you can follow their project updates and learn more about them. Stay tuned!

December 01, 2024

2024-12-01 Sunday

  • All Saints, family service + Baptism in the morning, caught up with wider church family; home for Pizza lunch with E.
  • Put up Christmas decorations left & right. Slugged variously, watched Night Action some Fallout - gratuitous gore, but interesting effects & characters.

November 27, 2024

Outreachy Internship Series: Files Usability Test Report

During my Outreachy internship with GNOME, Tamnjong Larry Tabeh and I conducted user research exercises under the inspiring mentorship of Allan Day and Aryan Kaushik.

In this blog post, I’ll discuss the usability test we conducted for GNOME’s Files, also known as Nautilus.

This blog post will introduce the study, outline our methodology, and present our key findings from the usability test. I’ve also attached a downloadable report at the end of this blogpost that discusses (in detail) our observations and recommendation(s) for each task performed in the usability test.

Without further ado, let’s jump right in!

1.  Introduction

Files is the default file manager of the GNOME desktop. It provides a simple and integrated way of managing files when running a Linux-based OS by supporting all the basic functions of a file manager and more.

With recent GNOME releases introducing significant changes to the Files user experience, and more improvements planned for subsequent releases, the design team wanted to assess the effectiveness of these updates and learn more about other aspects of the user experience.

To support these efforts, we executed a user research project to identify areas for improvement, and gather actionable insights from observed user behaviours that can inform design decisions when addressing identified issues.

1.1.  Research Goals

Our research goals were to:

    • Assess the effectiveness of the new menu structure and the discoverability of the following menu items:
      1. Icon Size editors
      2. Properties
      3. Select All
      4. Undo/Redo
      5. Sort
      6. Open Item Location
      7. Show Hidden Files
      8. Add To Bookmark
    • Evaluate the ease of use of Files’s Search feature, and the intuitiveness of its Search Filters.
    • Investigate the extent to which any difficulty experienced when right-clicking an empty space in List View impacts the user experience when accessing a folder context-menu.

1.2.  Research Questions

Upon completion of the study, we wanted to be able to answer the following questions:

    • Menu Structure
      1. Is the current organization of the menus effective?
      2. Can people find the buttons they need for basic tasks when they need them?
    • Search Experience
      1. Do people understand how to search in Files?
      2. Do people understand the search filters and how to use them?
      3. Are the search filters effective for their context of use?
    • List View Layout
      1. Is it challenging for people to access the folder context menu in list view when they have a lot of files?
      2. Does the current design meet user expectations when accessing folder context menu in list view?

2.  Study Design

2.1.  Approach

To answer our research questions, we opted for a moderated task-based usability test. This approach meant that we could simulate typical usage conditions and observe participants interact with Files. This made it easy for us to identify pain-points and gaps in the specific aspects of the Files user experience that we were interested in, and allowed us to engage participants in discussions that deepened our understanding of the challenges they experienced with Files.

To plan the study, we started by defining the ideal participant for our research goals. Next, we established an optimal sequence for the tasks we wanted participants to perform, then crafted a scenario for each, after which we designed the testing environment. Then concluded preparations with a pilot test to identify weaknesses in the study plan and implement revisions where necessary before testing with recruited participants.

2.2.  Recruitment Criteria

To generate the data we needed, we had to observe individuals who were unfamiliar with the Files menu structure. This requirement was crucial, as previous use of Files could influence a participant’s interactions, which would have made it difficult for us to discern valid usability issues from their interactions.

We also needed participants to be able to perform basic computing tasks independently: tasks like navigating software and managing files on their computer. This proficiency was important to ensuring that any challenges observed during the study were specifically related to the Files user experience, rather than stemming from a lack of general computer skills.

Therefore, we defined our recruitment criteria as follows:

    1. Has never used GNOME prior to their usability test session.
    2. Is able to use a computer moderately well.

2.3.  Testing Environment

During testing, participants interacted with development versions of Files, specifically, versions 47.rc-7925df1ba and 47.rc-3faeec25e. Both versions were the latest available at the time of testing and had identical implementations of the features we were targeting.

To elicit natural interactions from the participants, we enhanced the testing environment with a selection of files and folders that were strategically organized, named, and hidden, to create states in Files that encouraged and facilitated the tasks we planned to observe.

3.  Participant Overview

We recruited and tested with six first-time GNOME users, aged twenty-one to forty-seven, from diverse backgrounds, with varying levels of computer expertise. This diversity in the sample helped us keep our findings inclusive by ensuring that we considered a broad range of experiences in the usability test.

Although the majority of the participants reported current use of Windows 11 as shown below, a few also reported previous use of macOS and earlier versions of Windows OS.

4.  Methodology

For this usability test:

    • We conducted in-person usability tests with six computer users who met our selection criteria.
    • The moderating researcher followed a test script and concluded each session with a brief, semi-structured interview.
    • Participants attempted eleven tasks in the following order:
      1. Change the icon size
      2. Find the size of a folder with Properties
      3. Select all files in a folder with “Select All”
      4. Undo an action with the “Undo” button
      5. Change the sort order
      6. Change Files display from grid view to list view
      7. Create a new folder while in list view
      8. Find a file using the search feature, with filters
      9. Go to a file’s location from search results with “Open Item Location”
      10. Reveal hidden items in a folder with “Show Hidden Files”
      11. Add a folder to the sidebar with “Add to Bookmarks”
    • Participants were encouraged to continuously think aloud while the performing tasks and each session lasted at least 40 minutes.
    • All sessions were recorded with participant consent and were later transcribed for analysis.

5.  Usability Test Result

Applying Jim Hall’s Heat Map technique we summarized the observed experience for all tasks performed in the usability test. The heatmap below shows the completion rate for each task and the level of difficulty experienced by participants when performing them.

The tasks are in rows and participants are represented in columns. The cell where a row (Task) intersects with a column (Participant) captures the task outcome and relative difficulty experienced by a participant during their attempt.

A cell is green if the participant completed the task without any difficulty, yellow if the participant completed the task with very little difficulty, orange if the participant completed the task with moderate difficulty, red if the participant completed the task with severe difficulty, black if the participant was unable to complete the task, and gray if the participant’s approach was outside the scope of the study.

6.  Key Insights

1.  Menu structure

    • The menu structure was generally easy for participants to navigate. Despite using GNOME and Files for the first time during their testing sessions, they adapted quickly and were able to locate most of the buttons and menu items required to complete the tasks.
    • The best performing tasks were “Change the sort order” and “Reveal hidden items in a folder”, and the worst performing tasks were “Change the icon size” and “Add a folder to Bookmark”.
    • Overall, the participants easily found the following menu items when needed:
      1. Sort
      2. Show Hidden Files
      3. Properties
      4. Open Item Location
    1. But struggled to find these menu items when needed
      1. Icon size editors
      2. Select All
      3. Undo/Redo
      4. Add To Bookmark
    • In situations where participants were familiar with a shortcut or gesture for performing a task, they almost never considered checking the designated menus for a button.
    • We observed this behavior in every participant, particularly when they performed the following tasks:

    • Nonetheless, Files excelled in this area with its remarkable support for widely used shortcuts and cross-platform conventions.
    • We also observed that when these actions worked as expected it had the following effects on the user’s experience:
      1. It reduced feelings of apprehension in participants and encouraged them to engage more confidently with the software.
      2. It made it possible for the participants to discover Files’s menu structure without sacrificing their efficiency.

2.  Search

The “Search Current Folder” task flow was very intuitive for all participants. The search filters were also very easy to use and they effectively supported participants during the file search.

However, we found that the clarity of some filter labels could be reasonably improved by tailoring them to the context of a file search.

3.  List View Layout

The current List View layout did not effectively support typical user behavior when accessing the folder context menu.

4.  General Observation

When the participants engaged in active discovery of Files, we observed behaviour patterns that are linked to the following aspects of the design:

    • Familiarity:
    • We observed that when participants attempted familiar tasks, they looked for familiar cues in the UI. We noticed that when a UI component looked familiar to participants, they interacted without hesitation and with the expectation that this interaction would lead to the same outcomes that they’re accustomed to from their prior experience with similar software. Whereas, when a UI component was unfamiliar, participants were more restrained and cautious when they interacted with it.
    • For example, we noticed participants interact differently with the “Search Current Folder” button compared to the “List/Grid View” and “View Options” buttons.
    • With the “Search Current Folder” button, participants took longer to identify the icon, and half of the sample checked the tooltip for confirmation before clicking the button, because the icon was unfamiliar.
    • In contrast, participants reacted a lot quicker during the first task, as they instinctively clicked on the “List/Grid View” or “View Options” icons without checking the tool tip. Some even did so while assuming the two buttons were part of a single control and interacted with them as if they were combined, because they were familiar with the icons and the design pattern.
    • Tool tips
    • With a lot of icon buttons in the Files UI, we observed participants relying heavily on tooltips to discover the UI. Mostly as a way to validate their assumptions about the functionality of an icon button as highlighted above.
    • Clear and effective labels:
    • We observed that, the more abstract or vague a label was, the more participants struggled to interpret it correctly.
    • In the “Open Item Location” tasks, we guided the participants who were unable to find the menu item to the file’s context menu, then asked them if they thought there was a button that could have helped them complete the task. Both participants who gave up on this task instantly chose the correct option.
    • Whereas, in the “Add To Bookmarks” tasks, almost everyone independently found the menu item but the majority of them were hesitant to click on it because of the word “Bookmarks” in the label.
    • Layout of Files
    • By the end of most of the sessions, participants had concluded that controls in the white (child) section of the layout affected elements within that section, while controls in the sidebar were relevant to just the elements in the sidebar, even though this wasn’t always the case with how the Files menu structure is actually organized.
    • Therefore, when participants needed to perform an action they believed would affect elements in the child section of the layout, most of them instinctively checked the same section for an appropriate control.

7.  Conclusion, Reflections and Next Steps

If you’d like to learn about our findings and the identified usability issues for each task, here is a detailed report that discusses our how the participants interacted alongside our recommendations: Detailed Report for Files Usability Test

Overall, the usability test effectively supported our research goals and provided qualitative insights that directly addressed our research questions.

Beyond these insights, we also noted that users have preferences for performing certain tasks. Future research efforts can build on this insight by exploring the usage patterns of Files users to inform decisions around the most effective ways to support them.

Reflecting on the study’s limitations, a key aspect that may have influenced our result was the participant sample. We tested with a sample that was predominantly composed of Windows 11 users, although unintended. Ideally, a more diverse group that included current users of different operating systems could have further enriched our findings by providing a broader range of experiences to consider. However, we mitigated this limitation by recognizing that the participants who had previous experience with more operating systems brought their knowledge from those interactions into their use of Files, which likely influenced their behaviors and expectations during the test.

8.  Acknowledgements

I gained a lot of valuable skills from my internship with GNOME; I significantly improved my communications skills, learned practical skills for designing and executing user research projects using different qualitative and quantitative user research methods, and developed a sense for the more nuanced but critical considerations necessary for ensuring reliability and validity of research findings through the various phases of a study and how to mitigate them in research planning and execution.

So, I’d like to conclude by expressing my profound gratitude to everyone who made this experience so impactful.

I’d like to appreciate my mentors (Allan day and Aryan Kaushik) for their guidance, insightful feedback, and encouragement, throughout and beyond the internship; the GNOME community, for the warm welcome and support; and Outreachy, for making it possible for me to even have this experience.

I greatly enjoyed working on this project and I expect to make more user research contributions to GNOME.

Thank you!

 

 

GNOME Settings 47 Retrospective

While cutting the 47.2 release earlier today, I couldn’t help but reflect on everything we’ve accomplished this cycle. But instead of just listing code changes, I want to use this opportunity to give credit where it’s due, because to me, software is about people!

Much of what we have achieved this cycle is thanks to the dedication of passionate volunteer contributors such as Matthijs Velsink, Automeris Naranja, Hari Rana, Alice Mikhaylenko, Andy Holmes, Adrian Vovk, Corey Berla, Joan Torres, Joshua, Adrien Plazas, Jamie Murphy, and many others. I’m also deeply grateful to the translation teams for making GNOME accessible in so many different languages.

The GNOME Design team has been invaluable throughout this cycle. A big thank you to Allan Day, Jakub Steiner, Sam Hewitt, and Jamie Gravendeel, for their essential contributions.

Special thanks to Matthijs Velsink for taking on the challenging role of co-maintaining Settings with me. I couldn’t manage it without Matthijs’ outstanding contributions to fixes, features, and reviews. We’re lucky to have him as part of the project.

Release 47 holds extra significance for me. Wearing my downstream hat, I can share (it’s no secret) that the upcoming RHEL 10 Workstation will primarily feature GNOME 47 components. Building a solid upstream foundation for this version has been one of my top priorities, and I’m happy with the results.

Thanks to the evolution of libadwaita, we’ve been able to port many of our custom widgets to modern libadwaita ones. This transition enhances consistency across the desktop, improves accessibility, and ensures better responsiveness on screens of various sizes. A big shoutout to the incredible folks working on libadwaita for making this possible!

With Libadwaita we added Accent Color settings, allowing customizing our default blue accent color throughout the GNOME app ecosystem. Personally, I’ve been rocking the purple accent color on my desktop. 🙂

We also revisited the interface for adding local and enterprise user accounts, improving it with libadwaita widgets, a new password and username feedback widget, and addressing some technical debt along the way. Speaking of interface modernization, we’ve also revamped several UIs in the Printing settings.

Over time, some of our UIs have evolved at different paces, often leaving us with interfaces in transitional states and UX inconsistencies. A common example was nested dialogs, where a button within a dialog could open yet another dialog. To address this, many top-level dialogs have been converted into subpages using libadwaita’s AdwNavigationView, resulting in a smoother browsing experience.

We continually refine the settings texts and descriptions to align more closely with the GNOME Human Interface Guidelines. Many settings have also been reworded to improve clarity and discoverability too.

There’s so much more that happened this cycle, including a lot of performance improvements, bug fixes, and various tweaks. You can find more changes listed on the ‘Version History’ dialog in GNOME Software.

We’re always looking for contributors, and there are many ways you can help improve GNOME Settings. Visit apps.gnome.org/Settings to learn how to get started.

Cambalache 0.94 Released!

Hello, I am pleased to announce a new Cambalache stable release.

Version 0.94.0 – Accessibility Release!

    • Gtk 4 and Gtk 3 accessibility support
    • Support property subclass override defaults
    • AdwDialog placeholder support
    • Improved object description in hierarchy
    • Lots of bug fixes and minor UI improvements

How it started?

A couple of months ago I decided to make a poll on Mastodon about which feature people would like to see next.

Which feature should be added next in Cambalache? Results: - 28% GtkExpression support - 28% GResource - 36% Accessibility - 8% In App polls

To my surprise GtkExpression did not come up first and GResources where not the last one.

Data Model

First things firsts, how to store a11y data in the project”

So what are we trying to sotre? from Gtk documentation:

GtkWidget allows defining accessibility information, such as properties, relations, and states, using the custom <accessibility> element:

<object class="GtkButton" id="button1">
  <accessibility>
    <property name="label">Download</property>
    <relation name="labelled-by">label1</relation>
  </accessibility>
</object>

These looks a lot like regular properties so my first idea was to store them as properties in the data model.

So I decided to create one custom/fake interface class for each type of a11y data CmbAccessibleProperty, CmbAccessibleRelation and CmbAccessibleState.

These are hardcoded in cmb-catalog-gen tool and look like this

# Property name: (type, default value, since version)
self.__a11y_add_ifaces_from_enum([
  (
    "Property",
    "GtkAccessibleProperty",
    {
      "autocomplete": ["GtkAccessibleAutocomplete", "none", None],
      "description": ["gchararray", None, None],
      ...
    }
  ),
  (
    "Relation",
    "GtkAccessibleRelation",
    {
      "active-descendant": ["GtkAccessible", None, None],
      "controls": ["CmbAccessibleList", None, None],  # Reference List
      "described-by": ["CmbAccessibleList", None, None],  # Reference List
      ...
    }
  ),
  (
    "State",
    "GtkAccessibleState",
    {
      "busy": ["gboolean", "False", None],
      "checked": ["CmbAccessibleTristateUndefined", "undefined", None],
      "disabled": ["gboolean", "False", None],
      "expanded": ["CmbBooleanUndefined", "undefined", None],
      ...
    }
  )
])

This function will create the custom interface with all the properties and make sure all values in the GtkEnumeration are covered.

One fundamental difference with properties is that some a11y relations can be used more than once to specify multiple values.

To cover this I created a new value type called CmbAccessibleList which is simply a coma separated list of values.

This way the import and export code can handle loading and exporting a11y data into Cambalache data model.

Editing a11y data in the UI

Now since these interfaces are not real, no actual widget implements them, they wont show up automatically in the UI.

This can be easily solved by adding a new tab “a11y” to the object editor which only shows a11y interface properties.Cambalache screenshot showing A11y tab with all propertiesNow at this point it is possible to create and edit accessibility metadata for any UI but as Emmanuelle pointed out not every a11y property and relation is valid for every role.

@xjuan @GTK make sure you're not setting accessible properties/relations that do not match the roles that define them; GTK will use the role to read attributes, but we're missing a strong validation suite

To know what is valid or not you need to read WAI-ARIA specs or write a script that pulls all the metadata from it.

With this metadata handy is it easy to filter properties and relations depending on the a11y role.Cambalache screenshot showin a11y tab with properties filtered by accessible roleBTW keep in mind that accessible-role property should not be changed under normal circumstances.

Where to get it?

From Flathub

flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo

flatpak install flathub ar.xjuan.Cambalache

or directly from gitlab

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

Matrix channel

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

Mastodon

Follow me in Mastodon @xjuan to get news related to Cambalache development.

Happy coding!

November 22, 2024

Hackweek 24

It's the time for a new Hack Week. The Hack Week 24 was from November 18th to November 22th, and I've decided to join the New openSUSE-welcome project this time.

The idea of this project is to revisit the existing openSUSE welcome app, and I've been trying to help here, specifically for the GNOME desktop installation.

openSUSE-welcome

Right now after installing any openSUSE distribution with a graphical desktop, the user is welcomed on first login with a custom welcome app.

This custom application is a Qt/QML with some basic information and useful links.

The same generic application is used for all desktops, and for popular desktops right now exists upstream applications for this purpose, so we were talking on Monday morning about it and decided to use specific apps for desktops.

So for GNOME, we can use the GNOME Tour application.

gnome-tour

GNOME Tour is a simple rust/gtk4 application with some fancy images in a slideshow.

This application is generic and just shows information about GNOME desktop, so I created a fork for openSUSE to do some openSUSE specific customization and use this application as openSUSE welcome in GNOME desktop for Tumbleweed and Leap.

Desktop patterns, the welcome workflow

After some testing and investigation about the current workflow for the welcome app:

  1. x11_enhanced pattern recommends opensuse-welcome app.
  2. We can add a Recommends: gnome-tour to the gnome pattern
  3. The application run using xdg autostart, so gnome-tour package should put the file in /etc/xdg/autostart and set to hidden on close.
  4. In the case of having a system with multiple desktops, we can choose the specific welcome app using the OnlyShowIn/NotShowIn config in desktop file

So I've created a draft PR to do not show the openSUSE-welcome app in GNOME, and I've also the gnome-tour fork in my home OBS project.

I've been testing this configuration in Tumbleweed with GNOME, KDE and XFCE installed and it works as expected. The openSUSE-welcome is shown in KDE and XFCE and the gnome-tour app is only shown in GNOME.

Next steps

The next steps to have the GNOME Tour app as default welcome for openSUSE GNOME installation are:

  1. Send forked gnome-tour package to GNOME:Next project in OBS.
  2. Add the Recommends: gnome-tour to patterns-gnome to GNOME:Next project in OBS.
  3. Make sure that any other welcome application is not shown in GNOME.
  4. Review openQA tests that expect opensuse-welcome and adapt for the new application.

November 21, 2024

Status update, 21/11/2024

A month of low energy here. My work day is spent on a corporate project which I can’t talk about due to NDAs, although I can say it’s largely grunt work at the moment.

I’m not much of a gamer but sometimes you need a dose of solid fun. I finally started playing through Age of Empires II: The Conquerers, which has aged 24 years at this point, like a fine whisky. I played the original AoE when it came out, and I loved the graphics and the scenarios but got burned out by how dumb the units would be. All that was greatly improved in the second edition; although your guys will still sometimes wander off to chip away single-handedly at an enemy castle with their tiny sword, the new keyboard shortcuts make it less frustrating to micro-manage an army. I guess this is old news for everyone except me but, what a game.

Screenshot of Age of Empires II

I’m preparing some QA related talk submissions for FOSDEM 2025. I haven’t had time or energy to work on QA testing in GNOME, but I still have a clear idea of how we can move forwards, and I’ll keep talking about it a little longer to see if we can really go somewhere. There is still a small community joining our monthly call which gives a certain momentum to the project.

In terms of search, unfortunately I don’t feel much momentum around this at the moment. Besides the heroic contributions from Carlos, we did get a new IDE from Demigod’s and Rachel’s summer of code project. Somehow that hasn’t even made its way into Fedora 41, despite being part of the latest GNOME 47 release, so it’s still tricky to use it in demos. I looked at submitting some desktop search related talk to FOSDEM but there’s not a single dev room I can see where a proposal would even fit. There we are.

One final thought. This was a pretty engaging 20 minute talk by Cabel Sasser on the topic of a bizarre mural he saw at a McDonalds burger restaurant in Washington, USA. I recommend watching it if you haven’t, but you can also jump straight to the website about the mural’s artist, Wes Cook.

Photo of Wes Cook mural in McDonalds, Centralia

Something jumped out at me in the middle of the talk when he said “We all want to be seen.” Most folk want some recognition of the work we do and some understanding. In the software industry it’s very difficult because what we do is so specialised. But we’re now at a point where graphical desktops have been mainstream for nearly 30 years. Everyone uses one in their job. Smartphones are 15 years old and the tech isn’t hugely evolving.

A lot of this stuff is based on open source projects with 15+ year histories, and the people who can tell the stories of how they were made and how they work are all still around and still active.

It could be worth spending some effort recognising what we have, and talking about it, and the people who make it happen.

(If only we could have a desktop room at FOSDEM again…)

November 20, 2024

Capitole du Libre et discriminations

Le weekend du 16 et 17 novembre 2024, j’ai eu le plaisir d’aller au Capitole du Libre (CdL), une chouette conférence tenue tous les ans à Toulouse, et j’ai envie de revenir dessus. Le CdL rassemble la communauté libriste française, avec une représentation notable du milieu associatif. On y trouve un village associatif rassemblant un large pan du milieu libriste français au delà du logiciel, des présentations techniques accessibles à tous les niveaux de connaissance, et des présentations plus politiques qui proposent de réfléchir et faire évoluer le mouvement libriste. Ça en fait une conférence très joviale et conviviale où l’on peut venir en famille.

J’ai déjà participé au CdL par le passé, y tenant des stands pour parler de GNOME sur smartphones en 2018, 2019 et 2022. De plus en 2019 j’y ai donné une présentation sur mes travaux pour porter GNOME sur smartphones, et en 2022 j’ai eu le plaisir d’interviewer David Revoy dans les couloirs de la conférence. C’est une conférence que j’apprécie et à laquelle j’aime participer, et 2024 est la première édition où j’y suis allé en visiteur.

Des présentations marquantes

Une fois n’est pas coutume, je suis venu au CdL pour assister à des présentations, et quelques unes m’ont agréablement marqué. Voici un bref récapitulatif par ordre chronologique de celles qui ont constitué les points hauts de ma visite.

Le samedi , Valentin Deniaud a donné une présentation piquante et très drôle sur la lutte de l’éditeur de logiciels libres Entr’ouvert contre Orange, narrant comment le géant des télécoms a été condamné après des décennies de lutte pour non respect d’une licence libre. La présentation pleine d’anecdotes et d’humour dresse un parcours laborieux dans divers types de droits et dans la justice française.

Le même après-midi , Armony Altinier et Jean-Philippe Mengual nous ont fait une démonstration des limitation de l’accessibilité de la plate-forme d’apprentissage Moodle aux personnes non-voyantes. La présentation explique surtout comment les personnes utilisant cette plate-forme pour proposer du matériel éducatif peuvent adapter le contenu pédagogique et les méthodes d’évaluation pour une plus grande inclusivité.

Le dimanche , un intervenant représentant l’association Skeptikón a dressé les liens entre logiciels libres, scepticisme et politique. La présentation nous invite à faire face aux temps sombres que profile la montée globale du fascisme, présentant divers moyens d’y faire face comme le scepticisme, le librisme et le syndicalisme, le point d’orgue étant mis sur la nécessité de combattre le sentiment d’inanité et le fatalisme en créant du nous.

Elle a été suivie par une présentation d’Isabella Vanni décrivant le fonctionnement de l’April et son cheminement pour mieux inclure la diversité de genres. Partant des origines de l’informatique dévalorisée et féminisée pour aller jusqu’à sa valorisation et sa réappropriation par les hommes dans les années 1980, elle présente les mécanismes qui freinent la ré-inclusion des femmes dans le secteur et des moyens de lutter contre.

La conférence reprend par une présentation de Khrys, nous offrant une plongée dans les origines féminines de l’informatique, tissant des liens avec l’intelligence artificielle et le luddisme. Par le prisme du mythe de Prométhée et de ses diverses réinterprétations en science-fiction, elle confronte les visions patriarcales et féminines des innovations techniques, nous invitant à être technocritiques envers les intelligences artificielles via une approche féministe.

Des intentions d’inclusion sans application

Le CdL est doté d’un code de conduite que chaque participant·e se doit de respecter, qu’ils et elles soient visiteurs·euses, invités·es ou organisateurs·ices. Le code de conduite déclare que les organisateurs·ices souhaitent éviter tout type de discrimination, que le non respect de ces règles de bienséance pourra entraîner l’exclusion de l’évènement et nous invite à signaler toute discrimination dont on est victime ou témoin.

Tout cela est louable mais sa mise en application me pose quelques problèmes. Comment faire un retour quand c’est l’organisation de l’évènement dans sa globalité qui est discriminante, empêchant des pans entiers de la population d’y accéder ? Comment faire un retour quand les discriminations sont causées sur la scène principale par des intervenants·es pendant des présentations ou la table-ronde, sous les yeux de l’organisation qui laisse faire sans répondre ? Car de la discrimination au CdL il y en a, il y en a beaucoup même, mais elle n’est pas forcément où l’organisation s’y attend.

Si ce n’est pas ma première participation au CdL, c’est ma première en tant que visiteur et confronter ces deux expérience me faire prendre conscience des œillères qu’on peut avoir vis-à-vis du déroulement de l’évènement quand on est affairé·e à son animation, qu’elles soient par volonté de ne pas faire de vagues ou parce qu’on a la tête dans le guidon. Je suis donc convaincu de l’honnêteté des intentions de l’organisation du CdL, tout autant que je suis convaincu que les problèmes sont de fond, et sont communs aux milieux du libre et à de trop larges pans des milieux socialistes. Allez dans n’importe quelle conférence et vous trouverez une partie de ces problèmes, et probablement d’autres encore.

Pour ces raisons, j’ai décidé de faire un retour sur les problèmes dont j’ai été témoin non pas à l’organisation du CdL directement, mais par cet article pour appeler la communauté libriste toute entière à se remettre en question. Dans la suite de cet article, je vais tenter d’expliquer ce qui constitue à mes yeux des problèmes de l’évènement et d’offrir des pistes pour y remédier.

Invisibilisation des luttes des travailleurs·euses du libre

Le samedi s’est clôturé par une table-ronde sur les modèles de gouvernance des projets libres. Si les échanges étaient intéressants, on a pu entendre plusieurs fois qu’il n’y a pas de licenciements dans les logiciels libres. Je ne comprends pas d’où peut venir une telle affirmation, sinon peut-être d’une vision très limitée de ce qu’il se passe dans nos milieux.

Je connais beaucoup trop de personnes licenciées qui travaillaient pour des multinationales du libre, mais également des organisations à but non-lucratif, des coopératives ou encore de petites associations. Les vagues de licenciements chez Red Hat et Mozilla de ces dernières années devraient suffire de vous convaincre, pour ne citer que les exemples les plus médiatisés. Et au delà des licenciements, les travailleurs·euses du libre sont aussi victimes de harcèlements et des mises au placard.

Et ça c’est sans parler de la précarité du milieu, supérieure à celles des autres milieux de l’informatique. Contrats précaires, salariat déguisé, freelance, exploitation du travail passion, travail bénévole, alternance entre embauche et non-emploi, le tout sans nécessairement de chômage entre temps. Tout ça est très fréquent. Je me suis énormément retrouvé dans ma lecture de Te plains pas, c’est pas l’usine, quand bien même je n’ai jamais travaillé dans le milieu associatif, il y a une exploitation très similaire dans les milieux libristes, exploitation fondée sur un sentiment de devoir pour le bien commun et des injonctions à l’abnégation et au don de soi. Alors qu’il s’agît certes de luttes, mais avant tout de relations de travail dans une économie capitaliste.

On parle tout le temps des licences libres, mais trop peu des licenciés·es du libre, et ce genre de discours déconnectés de la réalité dans nos milieux participent à l’invisibilisation de leurs luttes. Par solidarité on devrait s’y intéresser. Peut-être que cet écueil ne serait pas arrivé si la table était réellement ronde et incluait l’auditoire au lieu d’être une discussion descendante entre quatre grands noms du milieu.

Incommodation de personnes handicapées

Pour plein de raisons que ce soit, on n’a pas toustes assez d’énergie pour tenir une journée entière, d’autant plus une journée de conférence. Les rares lieux de repos sont la cour intérieure et des bancs de béton dans le bruyant, passant et illuminé hall principal. Les conférences peuvent être épuisantes pour moi, et lorsque j’ai dû à certains moments trouver un endroit calme où me reposer à l’abris du froid, le mieux que j’ai trouvé était par terre dans un couloir passant, ce qui vous vous en doutez n’est pas idéal.

Il y a plein de choses à faire pour améliorer ça qui ne coûtent pas grand chose. Une salle de repos un peu isolée, avec des chaises, calme, dans la pénombre et clairement indiquée serait plus que bienvenue. En complément ou à minima, avoir quelques chaises disposées çà et là permettrait un repos de meilleure qualité et plus fréquent. En complément, avoir plus de tables de bar près de la buvette permettrait aux personnes de manger leur crêpe et de boire leur café sans occuper une des rares places assises simplement pour répondre à leur besoin de libérer leurs mains.

Je dois louer l’organisation du CdL pour fournir un son clair et audible, ce qu’en tant que personne malentendante j’apprécie. Cela dit le son était parfois beaucoup trop fort, notamment lors de projections de vidéos promotionnelles auxquelles le son n’apportait rien de pertinent. Étant également hypersensible auditif, je dois avouer que ces rares moments étaient particulièrement pénibles et venaient contribuer à ma fatigue. Je n’ai pas eu le temps de me ruer sur mes bouchons d’oreille, le son était tellement fort et incommodant que je n’ai eu d’autre choix que de me boucher les oreilles avec les doigts en attendant que ça passe. Faire plus attention au niveau sonore serait bienvenu.

Stigmatisation des personnes psychiatrisées

Lors d’une présentation, une slide déclare que « le progrès technique est comme une hache qu’on aurait mise dans les mains d’un psychopathe », soulignée d’une image d’Elon Musk éclatant une porte avec une hache, faisant référence au film Shining. La personne présentant affirmant que c’est une citation d’Albert Einstein, comme pour appuyer la spiritualité du propos. Un peu plus tard dans la présentation, et à moins que ma mémoire ne me fasse défaut, le terme est réutilisé pour qualifier les personnes qui emploient des termes misogynes.

Psychopathe est une insulte saniste qui stigmatise les personnes psychiatrisées. Il disqualifie une personne en lui associant une tare psychologique infamante, méritant au mieux le mépris et le rejet, au pire l’enfermement ou la mort. Le simple fait d’utiliser ce terme participe à légitimer le système saniste dont souffrent les personnes psychiatrisées.

Ce terme médicalise les comportements perçus comme déviants, l’appliquer à Elon Musk pour qualifier ses actes revient à expliquer son fascisme par une tare mentale. Ses comportements s’expliquent pourtant très bien par son status social, et chercher à l’en extraire pour les expliquer par d’autres moyens dépolitise la situation. Elon Musk a de tels comportements parce que c’est un milliardaire fasciste, un influenceur libertarien, un colon blanc, un transphobe. Il en va de même pour les misogynes, je pense que n’importe quelle féministe sera d’accord pour dire que le patriarcat n’est pas une question de pathologie, et je suis convaincu que les féministes psychiatrisées n’apprécient pas d’être associées à des misogynes. Cette psychiatrisation du politique prend également forme dans l’injonction à voir un·e psy.

Pourtant en entretenant le sanisme, on entretien un système qui vise en grande partie à enfermer les personnes en lutte pour leur émancipation. Les esclaves luttant pour leur libération étaient psychiatrisés·es, les femmes luttant contre le patriarcat étaient psychiatrisées, les personnes homosexuelles étaient psychiatrisées, les opposants politiques étaient ou sont toujours psychiatrisés·es, les personnes trans sont toujours très activement psychiatrisées. Pour maintenir les hiérarchies on médicalise, psychiatrise, enferme, médicamente, camisole et ôte de toute agentivité les personnes en révolte contre les dominations qu’elles subissent. Voilà ce qui se cache derrière le terme psychopathe. Jamais un fasciste n’a été enfermé pour ses idées, jamais un homme pour sa misogynie.

Quand après sa présentation, je suis allé brièvement demander à la personne de ne plus utiliser ce terme, elle a justifié que c’est une citation d’Einstein. La comparaison des personnes psychiatrisée à des fascistes et des misogynes, ça n’est pas d’Einstein, pas plus que c’est Einstein qui a inclus ce terme dans la présentation. Einstein a dit plein de choses, pourquoi d’entre toutes retenir celle là ? Et si le but est d’avoir une citation à propos, pourquoi en choisir une saniste datant de 1917, ignorant plus d’un siècle de luttes ?

Il aurait été possible de choisir n’importe quelle autre citation, voire de se passer de citation, mais c’est celle là qui a été retenue. Il aurait même été possible d’utiliser la citation mais en la commentant, soulignant qu’elle est problématique et pourquoi, mais à ce compte autant ne pas l’utiliser puisque c’est hors-propos de la présentation. Mais surtout, ll aurait été possible de ne pas réemployer ce terme plus tard, hors de toute citation servant d’excuse à son utilisation. Les personnes psychiatrisées ne sont pas des punchlines.

Lors d’une autre présentation on apprend que lors du procès de Nuremberg, le nazi Hermann Göring a été jugé contre toute attente parfaitement sain par les psychologues. La personne présentant tentait de démontrer que les idées politiques ne sont pas une question de santé mentale, mais l’a fait sans démonter l’idée même de santé mentale, laissant penser que le fait que ces personnes aient été jugées saines serait une anomalie. Il me semble donc important de compléter en démontant l’idée même de santé mentale, qui comme j’ai tenté de l’expliquer plus haut est avant tout un outil d’oppression. Pour aller plus loin, je vous recommande de lire l’article L’abolition carcérale doit inclure la psychiatrie. Je précise que lutter contre la psychiatrie ne revient pas à nier les difficultés neurologiques ou psychologiques que peuvent rencontrer des personnes, ni le fait que le système psychiatrique peut parfois les aider. Mais si le système psychiatrique peut les aider, c’est parce que c’est l’unique moyen alors à notre disposition pour faire du soin mental et ce principalement pour des raisons de légalité, ce qui ne doit pas servir à nier que le système psychiatrique est avant tout un système de contrôle des corps et des esprits et une extension du système carcéral. Le soin doit se faire malgré la psychiatrie, pas grâce à elle. Le fait que les nazis aient été trouvés sains par les psychologues du procès de Nuremberg complète et illustre ce que je disais plus haut sur le rôle de la psychiatrie comme outil de domination.

On apprend dans le même temps que les psychologues ont donné à Hermann Göring un quotient intellectuel de 138, soulignant avec surprise que les nazis ne sont pas nécessairement idiots. Au delà du fait que la notion d’intelligence est en elle même très discutable, le QI est intrinsèquement un outil de hiérarchisation conçu par des bourgeois blancs pour se dresser au dessus des autres, réduisant les personnes à un unique nombre masquant sa méthode de calcul et les biais qui la constitue, mais offrant une illusion de scientificité. Le QI a principalement été utilisé en soutien au racisme, hiérarchisant l’intelligence des races pour justifier le colonialisme, et il suffit de regarder une carte mondial des QIs pour s’en convaincre. Rien d’étonnant donc qu’un bourgeois blanc ai un haut QI, l’outil fonctionne comme prévu. Et au delà du QI, ramener le fascisme à une notion d’intelligence dépolitise là encore le sujet et stigmatise les personnes qui en sont en réalité victimes.

Je tiens à présenter mes excuses à la première personne citée dans cette section et à qui je suis allé brièvement parler en aparté après un présentation autrement louable, j’espère ne pas avoir contribué au stress de l’évènement, mais par antivalidisme je ne pouvais pas laisser passer l’utilisation d’un tel terme. De même, je tiens à présenter mes excuses à la seconde personne et à son audience pour avoir monopolisé la parole pendant le court temps alloué aux questions, après là encore une excellente présentation.

Stigmatisation des personnes racisées

Lors de la table-ronde du samedi soir, une personne évoque la récente faille de sécurité injectée au logiciel xz suite à une longue infiltration. Elle semble avant tout avoir retenu une chose de cet épisode, à savoir la nationalité chinoise de la personne infiltrée puisqu’elle a cru pertinent de commenter en feignant une gêne que, puisqu’on n’est qu’entre nous cette personne peut l’avouer, elle a peur quand elle voit des contributions aux logiciels libres qu’elle maintient venant de personnes de l’est, de Russie, d’Asie du sud. Cette personne savait pertinemment que la table-ronde était filmée et allait être publiée, et elle a pu dire ça sans la moindre réaction ni des autres personnes sur scène, ni de l’organisation de l’évènement. Le public quant-à lui n’a jamais eu la parole de toute la table-ronde, empêchant toute réponse tierce dans le cadre de la conférence.

Erratum du  : il y a bel et bien eu un tour de questions que j’avais fini par oublier, et ce malgré une intervention que j’avais trouvée salutaire répondant à une vision très libérale de l’inclusion partagée sur scène.

Virtuellement tous les pays, tous les états pratiquent l’infiltration, l’injection de backdoors, les attaques virales, y compris les états occidentaux, y compris la France. Je serais tenté de dire que c’est probablement avant tout les états occidentaux qui en sont la source, il n’y a qu’à voir l’étendue du virus étasunien Stuxnet pour s’en convaincre. Pourtant ce n’est pas des logiciels développés par la CIA ou encore l’armée française que cette personne a remis en question, comme si l’informatique devait rester avant tout une préoccupation d’occidentaux. Le problème, c’est les sud asiatiques. Disons-le clairement, ce à quoi on assisté durant cette table-ronde n’est rien de plus que de la xénophobie éhontée, du racisme.

Le pire étant que ces immondices racistes ont été dites en réponse au fait qu’une autre personne de la table-ronde ai loué les contributions des personnes venant de régions en guerre au Moyen-Orient. Des tas de nos camarades libristes viennent de Russie ou de Chine, d’autres y vivent et subissent au quotidien le fascisme de ces états. Et que dire des camarades libristes des pays réprimés par les états occidentaux et les USA plus particulièrement ? Des mainteneurs du noyau Linux ont très récemment été virés du projet car russes, mais il n’y a pas de licenciements dans le libre nous a-t-on annoncé dans cette même table-ronde. Ni de racisme, manifestement, puisque l’organisation du CdL n’a pas réagi.

Plus tard, cette même personne nous annonce fièrement tutorer pour le Google Summer of Code. J’ai été tuteur pour cet évènement à deux reprises, et je sais qu’il y a une représentation notable des personnes d’Asie du sud parmi les candidats·es stagiaires. Ça m’inquiète pour la sélection des candidats·es que cette personne peut opérer, de même que pour la qualité de l’encadrement et le traitement des stagiaires.

Exclusion des personnes sourdes

Au delà d’être très intéressante, la présentation d’Armony Altinier et Jean-Philippe Mengual était lunaire et ce pour une raison toute simple : des personnes sourdes étaient venues assister à l’unique présentation de toute la conférence sur l’accessibilité et absolument rien n’a été mis en place par le CdL pour les inclure. Armony et Jean-Philippe se sont retrouvés·es à pallier le manque en ouvrant un éditeur de texte et en s’échangeant le clavier à tour de rôle pour retranscrire tant bien que mal ce que l’autre disait. Même si elle a trouvé ses limites lors des démonstrations où l’éditeur de texte a dû être masqué et où le clavier était sollicité, leur démarche et adaptivité a été plus que louable pour pallier les manquements de l’organisation de la conférence.

Imaginez la scène, deux personnes avec différents handicaps qui se retrouvent à devoir bricoler pour compenser l’accessibilité de la conférence à des personne ayant encore une autre catégorie de handicap ! Et tout ça, de nouveau, pendant l’unique présentation de toute la conférence ayant rapport avec le handicap et plus exactement avec le manque d’accessibilité. Pourtant des solutions existent. Idéalement, avoir des interprètes en langue des signes française pour inclure les personnes sourdes et avoir des personnes pour faire la transcription en sous-titres pour inclure les personnes mal-entendantes.

Ces solutions peuvent certes coûter cher en main d’œuvre, mais même sans moyens il est possible de bricoler des choses. Des logiciels libres de transcription existent comme Live Captions, et même si ces logiciels sont imparfaits, les avoir sur un écran dédié déporté ou sur la machine des présentateurs·ices permettrait de limiter l’exclusion. Et si on considère que ces logiciels libres ne sont pas suffisants, il ne faut pas hésiter à passer par des logiciels propriétaires, l’inclusion doit passer avant le purisme.

De plus, écrire les sous-titres en direct et sur place permettrait de compenser des soucis de captation audio et permettrait de plus rapidement publier les captations vidéo avec leurs sous-titres, pour toujours mieux inclure les personnes sourdes et mal entendantes. Enfin ce ne sont pas les seules personnes handicapées à bénéficier de sous-titres et de nombreuses personnes souffrant de troubles de l’attention arrivent mieux à suivre quand il y a à la fois de l’audio et des sous-titres, avoir des sous-titres en direct faciliterait leur participation et limiterait leur fatigue.

Addendum du  : on m’a fait remarquer que des sous-titres français permettent de mieux inclure les personnes dont le français n’est pas la première langue que l’audio français seul. Je suis pourtant bien placé pour le savoir, ayant réussi début octobre à suivre un documentaire grâce à ses sous-titres en italien alors que je ne connais pas la langue. De la même manière, on m’a fait remarquer que l’interprétation en langue des signes française permet de mieux inclure les personnes dont le français n’est pas la première langue que des sous-titres français.

Exclusion des personnes craignant pour leur santé et propagation des épidémies

Hé, regardez sous le tapis, c’est le covid, il n’est jamais parti, on l’y a glissé et on fait comme s’il n’existait plus. Pourtant c’est toujours une cause de mortalité majeure, et le covid long continue d’handicaper un grand nombre de personnes. J’ai des amis·es et camarades libristes qui ont acquis des handicaps parfois très sévère suite à de « petites grippes » ou du covid, et ce n’étaient pas des personnes dites « à risque ». Je parle de perte d’odorat définitif, de grande fatigue chronique ou de grande réduction de la mobilité. Et c’est sans mentionner les autres maladies comme la coqueluche, ni sans parler des morts. On continue de faire comme si de rien n’était, on n’a rien appris du début de la pandémie du covid et on redevient eugénistes pour un confort fantasmé.

Je peux porter un FFP2 tant que je veux pendant la conférence, il ne fait que vous protéger des virus que je pourrais diffuser, il ne me protège pas de ceux que vous diffusez. Pourtant éviter la propagation de maladies aéroportées, les gênes qu’elles occasionnent, les handicaps et les morts ne demande pas grand chose. Aérer les endroits clos tant que possible et se masquer dans les endroits de passage et confinés tels que les transports en commun, les supermarchés ou les conférences suffiraient à grandement réduire le nombre d’infections. Mais pour que ça fonctionne, encore faut-il qu’on se protège les uns·es les autres. Refuser de se masquer est eugéniste, c’est considérer que la maladie c’est pour les autres, qu’on est fort·e et que les handicaps et les morts sont acceptables. Il ne faut surtout pas attendre d’avoir des symptômes pour se masquer, on peut être porteur·se asymptomatique et participer à la diffusion de maladies, qu’on finisse par les développer ou non. De plus lorsqu’on développe une maladie telle que le covid ou la grippe, on a déjà participé à sa propagation pendant plusieurs jours. Porter un masque quand on le peut et quand c’est pertinent est devenu un acte radical de soin communautaire, c’est déprimant.

L’organisation du CdL contribue à cette situation, je n’ai vu aucune recommandation à se masquer, aucun système de filtration, aucune aération, pas même des fenêtres ouvertes qui ne coûtent pourtant littéralement rien. Ce n’est pourtant pas faute de sensibilisation, de documentation et d’actions de la part de l’Association pour la Réduction des Risques Aéroportés. Cabrioles ou Autodéfense Sanitaire fournissent également des ressources à ce sujet. L’autodéfense ne peut pas être individuelle, et sans actes collectifs tout le monde est vulnérable, sans prise en compte sérieuse des risques sanitaires par l’organisation de l’évènement personne n’est protégé.

Au delà de ça, en rassemblant un nombre conséquent de participants·es de tout le pays dans des salles bondées sans la moindre mesure de prévention, le CdL participe activement à la propagation des épidémies.

Erratum du  : les masques FFP2 protègent bel et bien leur porteurs·ses, mais ils ne sont réellement efficaces une journée que si tout le monde joue le jeu.

Addendum du  : toutes les personnes qui souhaiteraient se masquer ne peuvent pas le faire, c’est pourquoi il faut que toutes les personnes qui le peuvent se masquent pour les protéger. Le but n’est pas de faire les choses parfaitement mais de les faire au mieux de nos moyens, et à l’heure actuelle nous sommes collectivement lamentables. L’organisation de l’évènement a le pouvoir de participer à reverser la donne, de conscientiser nos milieux, de protéger et inclure nos camarades.

Une conférence de mecs blancs

Les conférences que j’ai citées comme marquantes pourraient faire croire à une parité de genre des intervenants·es, mais il n’en est rien. Les militant·es antipatriarcales doivent malheureusement faire un énorme travail pour leur inclusion et l’organisation du CdL s’est déjà faite remonter les bretelles il y a quelques années pour avoir refusé des présentations de femmes quand dans le même temps elle en accordait plusieurs à des hommes.

Lors de sa keynote, le présentateur nous expliquait que la mode est aux IAs, que c’est là que sont les financements en ce moment et que par conséquent et pour leur propre bien, les projets logiciels libres se doivent de suivre l’exemple de VLC et inclure des fonctionnalités en IA. La démonstration m’a laissé peu convaincu. Le lendemain, dans la même salle et au même créneau horaire, Khrys donnait une présentation nous invitant à être technocritiques des IAs via une angle féministe, soulignant la nécessité du libre. La présentation de Khrys était pertinente, percutante, intéressante, stimulante et salvatrice en nous invitant à aller contre le capitalisme et le patriarcat, et non pas à s’en accommoder comme la keynote de la veille. Sujet similaire, angle différent, la seconde présentation était à mon sens bien meilleure, mais c’est à une homme plutôt qu’à une femme que l’organisation a choisi de donner le créneau de keynote, créneau sans autres présentations pour lui faire concurrence. Khrys qui quant-à-elle a dû partager l’audience avec les nombreuses autres présentations du créneau a malgré tout réussi à faire salle comble.

De la même manière, si la présentation d’Isabella Vanni sur l’inclusion des femmes et des minorités de genre à l’April s’est vue allouée l’amphithéâtre, elle a été mise en concurrence avec une présentation sur la censure d’internet en France qui a fait salle comble, face à un amphi presque désert pour Isabella. Si la présentation sur la censure d’internet a été annulée au dernier moment, ce manquement de programmation a été relevé et critiqué.

La conférence se clôt sur une slide nous annonçant 1 200 participants à cette édition. On ne saura pas combien de participantes. Probablement que les personnes ayant réalisé ces slides n’ont pas assisté à la présentation d’Isabella Vanni qui nous expliquait pourtant bien combien le masculin neutre participe activement à l’absence des femmes dans les milieux de l’informatique et du libre.

Un autre point tristement notable est la blanchité des intervenants·es. La conférence est un véritable entre-soi blanc, pas étonnant que des propos racistes puissent être proférés pendant la table ronde sans soulever la moindre réaction, et il y a fort à parier que ça participe du fait que les personnes racisées n’y participent pas plus.

J’ai cru comprendre que certaines conférences vont activement rechercher des personnes pour présenter, mettant réellement la diversité du milieu en avant et aidant de ce fait à la rétablir en normalisant la présence, la visibilité et les paroles des personnes minorisées. J’ai entendu du bien de MiXiT et de Paris Web du point de vue de l’inclusivité, peut-être y-aurait-il à creuser dans la façon dont elles s’organisent ? Je ne dis pas que l’organisation du CdL ne se soucie pas de la diversité des intervenants·es, mais je suis convaincu que d’autres parviennent beaucoup mieux à la réaliser et que ces conférences devraient servir de points de référence.

Le CdL a beaucoup de tracks en parallèle mais je me demande si cette quantité ne se fait pas au détriment de la qualité de la conférence, et ce malgré la diversité des sujets abordés. Peut-être vaudrait-il mieux avoir moins des tracks mais des salles plus pleines, notamment l’amphithéâtre qui héberge la track principale ? Je peux entendre que réduire le nombre de tracks augmenterait l’occupation des salles de cours déjà bondées, ce qui serait effectivement un problème, mais peut-être y’a-t-il d’autres amphis à utiliser ? J’imagine que si l’organisation du CdL pouvait en avoir d’autres, elle ne les aurait pas boudés, et que donc elle ne peut en avoir qu’un seul.

Vous noterez que si les présentations qui m’ont marquées sont pour moitié présentées par des présentatrices et ce malgré une très vaste majorité de présentateurs, cela veut dire que j’ai trouvé en moyennes les présentations données par des femmes de meilleure qualité. Je serais taquin, je suggèrerais que réduire le nombre de présentations en donnant la priorité aux non-mecs et non-blancs augmenterait la qualité de la conférence. Allez, soyons taquins, je le suggère. Mais qu’on s’entende, je ne dis pas que la parité et l’inclusivité doivent être atteintes pour avoir une meilleure conférence, je note juste qu’une meilleure conférence serait un effet de bord bénéfique de leur atteinte.

Conclusion

J’ai volontairement omis de détailler les personnes qui ont commis ces impairs parce que je ne souhaite pas m’en prendre à elles mais aux problèmes. On vit dans des sociétés patriarcales, racistes, sanistes, validistes, et le milieu du libre n’y échappe pas. Je ne souhaite pas lutter contre des personnes mais contre des systèmes et les discours qui les soutiennent. J’espère que les personnes qui se reconnaîtraient dans cet article ne prendront pas mes remarques comme des attaques mais comme un appel à faire plus attention. Il y a certainement des tas d’autres problèmes que je n’ai pas vus, soit parce que je n’en ai pas eu conscience, soit parce que je n’en ai pas été témoin, soit parce que je n’ai pas le recul ou le vécu nécessaire. Je n’ai par exemple aucune idée de combien la conférence est accessible en fauteuil roulant. Mon but n’est de toute façon pas de faire une liste exhaustive mais de faire un retour sur mon vécu de la conférence, pointant du doigt des choses que je trouve graves et qui je pense devraient être sérieusement prises en compte. De plus, je tiens à présenter mes excuses de ne pas avoir plus sourcé et référencé mes propos, cet article a été écrit dans l’urgence et sa rédaction m’a fatigué, je n’ai plus l’énergie pour plus de recherches.

Je crois sincèrement aux volontés d’inclusion du CdL, tout autant que je sais qu’on vit dans des sociétés où les oppressions sont tellement banalisées qu’elles sont invisibles à la majorité. J’appelle néanmoins l’organisation du CdL à se remettre en question, les intentions d’inclusivité ne doivent pas rester des mots sur une page web et doivent être activement mises en pratique. Je ne souhaite pas spécifiquement jeter la pierre à son organisation, le CdL est une conférence que j’aime sincèrement et ce genre de problèmes sont malheureusement extrêmement répandus, non seulement dans la société mais également dans les milieux du libres. En disant ça, je souhaite pointer du doigt l’entièreté des mouvements des logiciels libres comme de la culture libre.

Conférence majeure du libre, le FOSDEM accueille des milliers de personnes et probablement plus de 10 000 dans un espace incroyablement sous-dimensionné. Évènement hautement international, les participants·es viennent de partout autour du monde. Le FOSDEM est un véritable lieu d’échange international d’épidémies où l’on blague à demi-mots que l’on tu n’as pas pleinement vécu la conférence si l’on re rentre pas avec une grippe du FOSDEM. L’organisation du FOSDEM ferme volontairement les yeux sur le problème et n’a absolument aucune politique sanitaire, la rendant activement complice de la propagation des épidémies et pandémies. À cette complicité doit s’ajouter celles des entreprises du libre qui incitent sinon forcent leurs employés·es à participer à la conférence bruxelloise.

Bien qu’étant intimiste avec sa cinquantaine de participants·es, j’ai de nouveau attrapé le covid pendant le Berlin Mini GUADEC 2024. Les mesures de protection mises en place étaient là encore insuffisantes, et nous étions de mémoire seulement 4 à se masquer, tout en devant passer des journées entières dans le même espace mal aéré. Encore une fois, je participais à la protection de personnes qui refusaient de m’accorder la même en ne se masquant pas, et l’organisation est responsable de l’insuffisance des mesures mises en place.

Je ne demande pas à ce que les conférences soient parfaites, aucune ne le sera jamais, et je ne prétends surtout pas pouvoir faire aussi bien sinon mieux. Je tiens à saluer l’organisation du CdL pour faire avoir fait un évènement assez chouette pour qu’on ait envie de le voir aller de l’avant, quitte à devoir le secouer un peu pour qu’il devienne réellement inclusif. J’espère que l’équipe du CdL ne prendra pas les problèmes que je remonte comme des attaques, tout autant que j’espère que les autres conférences du libre sauront s’assurer de ne pas faire les mêmes erreurs. J’espère également que les pistes d’amélioration que j’ai données aideront, je ne prétends pas qu’elles sont toutes faciles à mettre en place mais je veux bien, à mon échelle et avec l’énergie que j’ai, me tenir disponible pour aider l’organisation du CdL ou d’une autre conférence à trouver comment arranger la situation.

November 19, 2024

hidreport and hut: two crates for handling HID Report Descriptors and HID Reports

A while ago I was looking at Rust-based parsing of HID reports but, surprisingly, outside of C wrappers and the usual cratesquatting I couldn't find anything ready to use. So I figured, why not write my own, NIH style. Yay! Gave me a good excuse to learn API design for Rust and whatnot. Anyway, the result of this effort is the hidutils collection of repositories which includes commandline tools like hid-recorder and hid-replay but, more importantly, the hidreport (documentation) and hut (documentation) crates. Let's have a look at the latter two.

Both crates were intentionally written with minimal dependencies, they currently only depend on thiserror and arguably even that dependency can be removed.

HID Usage Tables (HUT)

As you know, HID Fields have a so-called "Usage" which is divided into a Usage Page (like a chapter) and a Usage ID. The HID Usage tells us what a sequence of bits in a HID Report represents, e.g. "this is the X axis" or "this is button number 5". These usages are specified in the HID Usage Tables (HUT) (currently at version 1.5 (PDF)). The hut crate is generated from the official HUT json file and contains all current HID Usages together with the various conversions you will need to get from a numeric value in a report descriptor to the named usage and vice versa. Which means you can do things like this:

  let gd_x = GenericDesktop::X;
  let usage_page = gd_x.usage_page();
  assert!(matches!(usage_page, UsagePage::GenericDesktop));
  
Or the more likely need: convert from a numeric page/id tuple to a named usage.
  let usage = Usage::new_from_page_and_id(0x1, 0x30); // GenericDesktop / X
  println!("Usage is {}", usage.name());
  
90% of this crate are the various conversions from a named usage to the numeric value and vice versa. It's a huge crate in that there are lots of enum values but the actual functionality is relatively simple.

hidreport - Report Descriptor parsing

The hidreport crate is the one that can take a set of HID Report Descriptor bytes obtained from a device and parse the contents. Or extract the value of a HID Field from a HID Report, given the HID Report Descriptor. So let's assume we have a bunch of bytes that are HID report descriptor read from the device (or sysfs) we can do this:

  let rdesc: ReportDescriptor = ReportDescriptor::try_from(bytes).unwrap();
  
I'm not going to copy/paste the code to run through this report descriptor but suffice to day it will give us access to the input, output and feature reports on the device together with every field inside those reports. Now let's read from the device and parse the data for whatever the first field is in the report (this is obviously device-specific, could be a button, a coordinate, anything):
   let input_report_bytes = read_from_device();
   let report = rdesc.find_input_report(&input_report_bytes).unwrap();
   let field = report.fields().first().unwrap();
   match field {
       Field::Variable(var) => {
          let val: u32 = var.extract(&input_report_bytes).unwrap().into();
          println!("Field {:?} is of value {}", field, val);
       },
       _ => {}
   }
  
The full documentation is of course on docs.rs and I'd be happy to take suggestions on how to improve the API and/or add features not currently present.

hid-recorder

The hidreport and hut crates are still quite new but we have an existing test bed that we use regularly. The venerable hid-recorder tool has been rewritten twice already. Benjamin Tissoires' first version was in C, then a Python version of it became part of hid-tools and now we have the third version written in Rust. Which has a few nice features over the Python version and we're using it heavily for e.g. udev-hid-bpf debugging and development. An examle output of that is below and it shows that you can get all the information out of the device via the hidreport and hut crates.

$ sudo hid-recorder /dev/hidraw1
# Microsoft Microsoft® 2.4GHz Transceiver v9.0
# Report descriptor length: 223 bytes
# 0x05, 0x01,                    // Usage Page (Generic Desktop)              0
# 0x09, 0x02,                    // Usage (Mouse)                             2
# 0xa1, 0x01,                    // Collection (Application)                  4
# 0x05, 0x01,                    //   Usage Page (Generic Desktop)            6
# 0x09, 0x02,                    //   Usage (Mouse)                           8
# 0xa1, 0x02,                    //   Collection (Logical)                    10
# 0x85, 0x1a,                    //     Report ID (26)                        12
# 0x09, 0x01,                    //     Usage (Pointer)                       14
# 0xa1, 0x00,                    //     Collection (Physical)                 16
# 0x05, 0x09,                    //       Usage Page (Button)                 18
# 0x19, 0x01,                    //       UsageMinimum (1)                    20
# 0x29, 0x05,                    //       UsageMaximum (5)                    22
# 0x95, 0x05,                    //       Report Count (5)                    24
# 0x75, 0x01,                    //       Report Size (1)                     26
... omitted for brevity
# 0x75, 0x01,                    //     Report Size (1)                       213
# 0xb1, 0x02,                    //     Feature (Data,Var,Abs)                215
# 0x75, 0x03,                    //     Report Size (3)                       217
# 0xb1, 0x01,                    //     Feature (Cnst,Arr,Abs)                219
# 0xc0,                          //   End Collection                          221
# 0xc0,                          // End Collection                            222
R: 223 05 01 09 02 a1 01 05 01 09 02 a1 02 85 1a 09 ... omitted for previty
N: Microsoft Microsoft® 2.4GHz Transceiver v9.0
I: 3 45e 7a5
# Report descriptor:
# ------- Input Report -------
# Report ID: 26
#    Report size: 80 bits
#  |   Bit:    8       | Usage: 0009/0001: Button / Button 1                          | Logical Range:     0..=1     |
#  |   Bit:    9       | Usage: 0009/0002: Button / Button 2                          | Logical Range:     0..=1     |
#  |   Bit:   10       | Usage: 0009/0003: Button / Button 3                          | Logical Range:     0..=1     |
#  |   Bit:   11       | Usage: 0009/0004: Button / Button 4                          | Logical Range:     0..=1     |
#  |   Bit:   12       | Usage: 0009/0005: Button / Button 5                          | Logical Range:     0..=1     |
#  |   Bits:  13..=15  | ######### Padding                                            |
#  |   Bits:  16..=31  | Usage: 0001/0030: Generic Desktop / X                        | Logical Range: -32767..=32767 |
#  |   Bits:  32..=47  | Usage: 0001/0031: Generic Desktop / Y                        | Logical Range: -32767..=32767 |
#  |   Bits:  48..=63  | Usage: 0001/0038: Generic Desktop / Wheel                    | Logical Range: -32767..=32767 | Physical Range:     0..=0     |
#  |   Bits:  64..=79  | Usage: 000c/0238: Consumer / AC Pan                          | Logical Range: -32767..=32767 | Physical Range:     0..=0     |
# ------- Input Report -------
# Report ID: 31
#    Report size: 24 bits
#  |   Bits:   8..=23  | Usage: 000c/0238: Consumer / AC Pan                          | Logical Range: -32767..=32767 | Physical Range:     0..=0     |
# ------- Feature Report -------
# Report ID: 18
#    Report size: 16 bits
#  |   Bits:   8..=9   | Usage: 0001/0048: Generic Desktop / Resolution Multiplier    | Logical Range:     0..=1     | Physical Range:     1..=12    |
#  |   Bits:  10..=11  | Usage: 0001/0048: Generic Desktop / Resolution Multiplier    | Logical Range:     0..=1     | Physical Range:     1..=12    |
#  |   Bits:  12..=15  | ######### Padding                                            |
# ------- Feature Report -------
# Report ID: 23
#    Report size: 16 bits
#  |   Bits:   8..=9   | Usage: ff00/ff06: Vendor Defined Page 0xFF00 / Vendor Usage 0xff06 | Logical Range:     0..=1     | Physical Range:     1..=12    |
#  |   Bits:  10..=11  | Usage: ff00/ff0f: Vendor Defined Page 0xFF00 / Vendor Usage 0xff0f | Logical Range:     0..=1     | Physical Range:     1..=12    |
#  |   Bit:   12       | Usage: ff00/ff04: Vendor Defined Page 0xFF00 / Vendor Usage 0xff04 | Logical Range:     0..=1     | Physical Range:     0..=0     |
#  |   Bits:  13..=15  | ######### Padding                                            |
##############################################################################
# Recorded events below in format:
# E: .  [bytes ...]
#
# Current time: 11:31:20
# Report ID: 26 /
#                Button 1:     0 | Button 2:     0 | Button 3:     0 | Button 4:     0 | Button 5:     0 | X:     5 | Y:     0 |
#                Wheel:     0 |
#                AC Pan:     0 |
E: 000000.000124 10 1a 00 05 00 00 00 00 00 00 00
  

November 14, 2024

Firmware SBOMs for open source projects

You might be surprised to hear that closed source firmware typically contains open source dependencies. In the case of EDK II (probably the BIOS of your x64 machine you’re using now) it’s about 20 different projects, and in the case of coreboot (hopefully the firmware of the machine you’ll own in the future) it’s about another 10 — some overlapping with EDK II. Examples here would be things like libjpeg (for the OEM splash image) or libssl (for crypto, but only the good kind).

It makes no sense for each person building firmware to write the same SBOM for the OSS code. Moving the SBOM upstream means it can be kept up to date by the same team writing the open source code. It’s very similar to what we encouraged desktop application developers to do with AppStream metadata a decade or so ago. That was wildly successful, so maybe we can do the same trick again here.

My proposal would to submit a sbom.cdx.json to each upstream project in CycloneDX format, stored in a location amenable to the project — e.g. in ./contrib, ./data/sbom or even in the root project folder. The location isn’t important, only the file suffix needs to be predictable.

Notice the CycloneDX word there not SPDX — the latter is great for open source license compliance, but I was only able to encode 43% of our “example firmware SBOM” into SPDX format, even with a lot of ugly hacks. I spent a long time trying to jam a round peg in a square hole and came to the conclusion it’s not going to work very well. SPDX works great as an export format to ensure license compliance (and the uswid CLI can already do that now…) but SPDX doesn’t work very well as a data source. CycloneDX is just a better designed format for a SBOM, sorry ISO.

Let’s assume we check in a new file to ~30 projects. With my upstream-maintainer hat on, nobody likes to manually edit yet-another-file when tagging releases, so I’m encouraging projects shipping a CycloneDX sbom.cdx.json to use some of the auto-substituted tokens, e.g.

  • @VCS_TAG@git describe --tags --abbrev=0 e.g. 1.2.3
  • @VCS_VERSION@git describe --tags e.g. 1.2.3-250-gfa2371946
  • @VCS_BRANCH@git rev-parse --abbrev-ref HEAD e.g. staging
  • @VCS_COMMIT@git rev-parse HEAD e.g. 3090e61ee3452c0478860747de057c0269bfb7b6
  • @VCS_SBOM_AUTHORS@git shortlog -n -s -- sbom.cdx.json e.g. Example User, Another User
  • @VCS_SBOM_AUTHOR@@VCS_SBOM_AUTHORS@[0] e.g. Example User
  • @VCS_AUTHORS@git shortlog -n -s e.g. Example User, Another User
  • @VCS_AUTHOR@@VCS_AUTHORS@[0] e.g. Example User

Using git in this way during the built process allows us to also “fixup” SBOM files with either missing details, or when the downstream ODM patches the project to do something upstream wouldn’t be happy with shipping upstream.

For fwupd (which I’m using as a cute example, it’s not built into firmware…) the sbom.cdx.json file would be something like this:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "version": 1,
  "metadata": {
    "authors": [
      {
        "name": "@VCS_SBOM_AUTHORS@"
      }
    ]
  },
  "components": [
    {
      "type": "library",
      "bom-ref": "pkg:github/fwupd/fwupd@@VCS_TAG@",
      "cpe": "cpe:2.3:a:fwupd:fwupd:@VCS_TAG@:*:*:*:*:*:*:*",
      "name": "fwupd",
      "version": "@VCS_VERSION@",
      "description": "Firmware update daemon",
      "supplier": {
        "name": "fwupd developers",
        "url": [
          "https://github.com/fwupd/fwupd/blob/main/MAINTAINERS"
        ]
      },
      "licenses": [
        {
          "license": {
            "id": "LGPL-2.1-or-later"
          }
        }
      ],
      "externalReferences": [
        {
          "type": "website",
          "url": "https://fwupd.org/"
        },
        {
          "type": "vcs",
          "url": "https://github.com/fwupd/fwupd"
        }
      ]
    }
  ]
}

Putting it all together means we can do some pretty clever things assuming we have a recursive git checkout using either git modules, sub-modules or sub-projects:

$ uswid --find ~/Code/fwupd --fixup --save sbom.cdx.json --verbose
Found:
 - ~/Code/fwupd/contrib/sbom.cdx.json
 - ~/Code/fwupd/venv/build/contrib/sbom.cdx.json
 - ~/Code/fwupd/subprojects/libjcat/contrib/spdx.json
Substitution required in ~/Code/fwupd/contrib/sbom.cdx.json:
 - @VCS_TAG@ → 2.0.1
 - @VCS_VERSION@ → 2.0.1-253-gd27804fbb
Fixup required in ~/Code/fwupd/subprojects/libjcat/spdx.json:
 - Add VCS commit → db8822a01af89aa65a8d29c7110cc86d78a5d2b3
Additional dependencies added:
 - pkg:github/hughsie/libjcat@0.2.1 → pkg:github/hughsie/libxmlb@0.2.1
 - pkg:github/fwupd/fwupd@2.0.1 → pkg:github/hughsie/libjcat@0.2.1
~/Code/fwupd/venv/build/contrib/sbom.cdx.json was merged into existing component pkg:github/fwupd/fwupd@2.0.1

And then we have a sbom.cdx.json that we can use as an input file used for building the firmware blob. If we can convince EDK2 to merge the additional sbom.cdx.json for each built module then it all works like magic, and we can build the 100% accurate external SBOM into the firmware binary itself with no additional work. Comments most welcome.

November 08, 2024

Learning web components and PatternFly Elements

Today at Red Hat is day of learning again! I used the occasion to brush up my knowledge about web components and taking a look at PatternFly Elements. I’ve leered at that for a long time already – using “regular” PatternFly requires React, and thus all the npm, bundler, build system etc. baggage around it. In Cockpit we support writing your own plugins with a simple static .html and .

November 07, 2024

We’re More Offline at Conferences, and That’s Probably a Good Thing

I’ve just been to two traditional Czech open source conferences – LinuxDays and OpenAlt – and I’ve noticed one interesting shift: the communication on social media during the conferences has disappeared.

After 2010, we suddenly all had a device in our pocket that we could easily use to share experiences and observations from anywhere. And at least at IT events, people started doing this a lot. Under the hashtag of the given conference, there was a stream of messages from participants about which talks they liked, where they could find a good place to eat in the area, what caught their attention among the booths. The event organizers used this to inform visitors, and the booth staff to attract people to their booth. I remember writing about what we had interesting at our booth, and people actually came to have a look based on that.

At the peak of this trend, the popular so-called Twitter walls were in use. These were typically web applications that displayed the latest messages under a given hashtag, and they ran on screens in the corridors or were projected directly in the lecture rooms, so that even those who weren’t following it on their mobile phones could keep track.

And today, all of this has practically disappeared. When I counted it after LinuxDays, there were a total of 14 messages with the hashtag on Mastodon during the conference, and only 8 on Twitter. During OpenAlt, there were 20 messages with the hashtag on Mastodon and 8 on Twitter. I also checked if it was running on Bluesky. There were a few messages with the hashtags of both conferences there, but except for one, they were all bridged from Mastodon.

In any case, these are absolutely negligible numbers compared to what we used to see ten years ago. Where did it all go? I thought about it and came up with four reasons:

  1. Microblogging is much more fragmented today than it was ten years ago. Back then, we were all on Twitter. That is now in decline. The open-source community has largely moved to Mastodon, but not entirely. Some are still on LinkedIn, some on Bluesky, etc. When there is no single place where everyone is, the effect of a universal communication channel disappears.
  2. Conference communication has partly shifted to instant messaging. This trend started 8-9 years ago. A group (typically on Telegram) was created for conference attendees, and it served for conference communication. Compared to a microblogging platform, this has the advantage that it is not entirely open communication. What happens at the conference, stays at the conference. It doesn’t take the form of publicly searchable messages. For some, this is a safer space than a social network. It’s also faster, with features like location sharing, etc. However, this mode of communication has also declined a lot. During OpenAlt, there were only 20 messages in its Telegram group.
  3. People are much more passive on social media today. Rather than sharing their own posts from the conference, they’d rather leave it to some influencer who will make a cool video from there, which everyone will then watch and like. All the major social networks have shifted towards a small group creating content for a passive majority. New platforms like TikTok have been functioning this way from the start.
  4. After Covid, people simply don’t have the same need to share their conference experiences online. They are somewhat saturated with it after the Covid years, and when they go somewhere, they don’t want to tap messages into their phone about how they’re doing there.

Overall, I don’t see it as a bad thing. Yes, it had its charm, and it was easier during the conference to draw attention to your booth or talk, but in today’s digital age, any shift towards offline is welcome. After all, conferences are there for people to meet in person. Otherwise, we could just watch the streams from home and write about them on social media. We’ve been there before, and it wasn’t quite right. 🙂

How do you see it? Do you also notice that you share less online from conferences?

November 06, 2024

GStreamer Conference 2024

All of us at Asymptotic are back home from the exciting week at GStreamer Conference 2024 in Montréal, Canada last month. It was great to hang out with the community and see all the great work going on in the GStreamer ecosystem.

Montréal sunsets are 😍

There were some visa-related adventures leading up to the conference, but thanks to the organising team (shoutout to Mark Filion and Tim-Philipp Müller), everything was sorted out in time and Sanchayan and Taruntej were able to make it.

This conference was also special because this year marks the 25th anniversary of the GStreamer project!

Happy birthday to us! 🎉

Talks

We had 4 talks at the conference this year.

GStreamer & QUIC (video)

Sancyahan speaking about GStreamer and QUIC

Sanchayan spoke about his work with the various QUIC elements in GStreamer. We already have the quinnquicsrc and quinquicsink upstream, with a couple of plugins to allow (de)multiplexing of raw streams as well as an implementation or RTP-over-QUIC (RoQ). We’ve also started work on Media-over-QUIC (MoQ) elements.

This has been a fun challenge for us, as we’re looking to build out a general-purpose toolkit for building QUIC application-layer protocols in GStreamer. Watch this space for more updates as we build out more functionality, especially around MoQ.

Clock Rate Matching in GStreamer & PipeWire (video)

Arun speaking about PipeWire delay-locked loops
Photo credit: Francisco

My talk was about an interesting corner of GStreamer, namely clock rate matching. This is a part of live pipelines that is often taken for granted, so I wanted to give folks a peek under the hood.

The idea of doing this talk was was born out of some recent work we did to allow splitting up the graph clock in PipeWire from the PTP clock when sending AES67 streams on the network. I found the contrast between the PipeWire and GStreamer approaches thought-provoking, and wanted to share that with the community.

GStreamer for Real-Time Audio on Windows (video)

Next, Taruntej dove into how we optimised our usage of GStreamer in a real-time audio application on Windows. We had some pretty tight performance requirements for this project, and Taruntej spent a lot of time profiling and tuning the pipeline to meet them. He shared some of the lessons learned and the tools he used to get there.

Simplifying HLS playlist generation in GStreamer (video)

Sanchayan also walked us through the work he’s been doing to simplify HLS (HTTP Live Streaming) multivariant playlist generation. This should be a nice feature to round out GStreamer’s already strong support for generating HLS streams. We are also exploring the possibility of reusing the same code for generating DASH (Dynamic Adaptive Streaming over HTTP) manifests.

Hackfest

As usual, the conference was followed by a two-day hackfest. We worked on a few interesting problems:

  • Sanchayan addressed some feedback on the QUIC muxer elements, and then investigated extending the HLS elements for SCTE-35 marker insertion and DASH support

  • Taruntej worked on improvements to the threadshare elements, specifically to bring some ts-udpsrc element features in line with udpsrc

  • I spent some time reviewing a long-pending merge request to add soft-seeking support to the AWS S3 sink (so that it might be possible to upload seekable MP4s, for example, directly to S3). I also had a very productive conversation with George Kiagiadakis about how we should improve the PipeWire GStreamer elements (more on this soon!)

All in all, it was a great time, and I’m looking forward to the spring hackfest and conference in the the latter part next year!

November 04, 2024

JJ-FZF - a TUI for Jujutsu

JJ-FZF is a TUI (Terminal-based User Interface) for Jujutsu, built on top of fzf. It centers around the jj log view, providing key bindings for common operations on JJ/Git repositories. About six months ago, I revisited JJ, drawn in by its promise of Automatic rebase and conflict resolution. I have…

November 03, 2024

Igalia and WebKit: status update and plans (2024)

It’s been more than 2 years since the last time I wrote something here, and in that time a lot of things happened. Among those, one of the main highlights was me moving back to Igalia‘s WebKit team, but this time I moved as part of Igalia’s support infrastructure to help with other types of tasks such as general coordination, team facilitation and project management, among other things.

On top of those things, I’ve been also presenting our work around WebKit in different venues, such as in the Embedded Open Source Summit or in the Embedded Recipes conference, for instance. Of course, that included presenting our work in the WebKit community as part of the WebKit Contributors Meeting, a small and technically focused event that happens every year, normally around the Bay Area (California). That’s often a pretty dense presentation where, over the course of 30-40 minutes, we go through all the main areas that we at Igalia contribute to in WebKit, trying to summarize our main contributions in the previous 12 months. This includes work not just from the WebKit team, but also from other ones such as our Web Platform, Compilers or Multimedia teams.

So far I did that a couple of times only, both last year on October 24rth as well as this year, just a couple of weeks ago in the latest instance of the WebKit Contributors meeting. I believe the session was interesting and informative, but unfortunately it does not get recorded so this time I thought I’d write a blog post to make it more widely accessible to people not attending that event.

This is a long read, so maybe grab a cup of your favorite beverage first…

Igalia and WebKit

So first of all, what is the relationship between Igalia and the WebKit project?

Igalia logoWebKit logo

In a nutshell, we are the lead developers and the maintainers of the two Linux-based WebKit ports, known as WebKitGTK and WPE. These ports share a common baseline (e.g. GLib, GStreamer, libsoup) and also some goals (e.g. performance, security), but other than that their purpose is different, with WebKitGTK being aimed at the Linux desktop, while WPE is mainly focused on embedded devices.

WPE logo

This means that, while WebKitGTK is the go-to solution to embed Web content in GTK applications (e.g. GNOME Web/Epiphany, Evolution), and therefore integrates well with that graphical toolkit, WPE does not even provide a graphical toolkit since its main goal is to be able to run well on embedded devices that often don’t even have a lot of memory or processing power, or not even the usual mechanisms for I/O that we are used to in desktop computers. This is why WPE’s architecture is designed with flexibility in mind with a backends-based architecture, why it aims for using as few resources as possible, and why it tries to depend on as few libraries as possible, so you can integrate it virtually in any kind of embedded Linux platform.

Besides that port-specific work, which is what our WebKit and Multimedia teams focus a lot of their effort on, we also contribute at a different level in the port-agnostic parts of WebKit, mostly around the area of Web standards (e.g. contributing to Web specifications and to implement them) and the Javascript engine. This work is carried out by our Web Platform and Compilers team, which tirelessly contribute to the different parts of WebCore and JavaScriptCore that affect not just the WebKitGTK and WPE ports, but also the rest of them to a bigger or smaller degree.

Last but not least, we also devote a considerable amount of our time to other topics such as accessibility, performance, bug fixing, QA... and also to make sure WebKit works well on 32-bit devices, which is an important thing for a lot of WPE users out there.

Who are our users?

At Igalia we distinguish 4 main types of users of the WebKitGTK and WPE ports of WebKit:

Port users: this category would include anyone that writes a product directly against the port’s API, that is, apps such as a desktop Web browser or embedded systems that rely on a fullscreen Web view to render its Web-based content (e.g. digital signage systems).

Platform providers: in this category we would have developers that build frameworks with one of the Linux ports at its core, so that people relying on such frameworks can leverage the power of the Web without having to directly interface with the port’s API. RDK could be a good example of this use case, with WPE at the core of the so-called Thunder plugin (previously known as WPEFramework).

Web developers: of course, Web developers willing to develop and test their applications against our ports need to be considered here too, as they come with a different set of needs that need to be fulfilled, beyond rendering their Web content (e.g. using the Web Inspector).

End users: And finally, the end user is the last piece of the puzzle we need to pay attention to, as that’s what makes all this effort a task worth undertaking, even if most of them most likely don’t need what WebKit is, which is perfectly fine :-)

We like to make this distinction of 4 possible types of users explicit because we think it’s important to understand the complexity of the amount of use cases and the diversity of potential users and customers we need to provide service for, which is behind our decisions and the way we prioritize our work.

Strategic goals

Our main goal is that our product, the WebKit web engine, is useful for more and more people in different situations. Because of this, it is important that the platform is homogeneous and that it can be used reliably with all the engines available nowadays, and this is why compatibility and interoperability is a must, and why we work with the the standards bodies to help with the design and implementation of several Web specifications.

With WPE, it is very important to be able to run the engine in small embedded devices, and that requires good performance and being efficient in multiple hardware architectures, as well as great flexibility for specific hardware, which is why we provided WPE with a backend-based architecture, and reduced dependencies to a minimum.

Then, it is also important that the QA Infrastructure is good enough to keep the releases working and with good quality, which is why I regularly maintain, evolve and keep an eye on the EWS and post-commit bots that keep WebKitGTK and WPE building, running and passing the tens of thousands of tests that we need to check continuously, to ensure we don’t regress (or that we catch issues soon enough, when there’s a problem). Then of course it’s also important to keep doing security releases, making sure that we release stable versions with fixes to the different CVEs reported as soon as possible.

Finally, we also make sure that we keep evolving our tooling as much as possible (see for instance the release of the new SDK earlier this year), as well as improving the documentation for both ports.

Last, all this effort would not be possible if not because we also consider a goal of us to maintain an efficient collaboration with the rest of the WebKit community in different ways, from making sure we re-use and contribute to other ports as much code as possible, to making sure we communicate well in all the forums available (e.g. Slack, mailing list, annual meeting).

Contributions to WebKit in numbers

Well, first of all the usual disclaimer: number of commits is for sure not the best possible metric,  and therefore should be taken with a grain of salt. However, the point here is not to focus too much on the actual numbers but on the more general conclusions that can be extracted from them, and from that point of view I believe it’s interesting to take a look at this data at least once a year.

Igalia contributions to WebKit (2024)

With that out of the way, it’s interesting to confirm that once again we are still the 2nd biggest contributor to WebKit after Apple, with ~13% of the commits landed in this past 12-month period. More specifically, we landed 2027 patches out of the 15617 ones that took place during the past year, only surpassed by Apple and their 12456 commits. The remaining 1134 patches were landed mostly by Sony, followed by RedHat and several other contributors.

Igalia contributions to WebKit (2024)Now, if we remove Apple from the picture, we can observe how this year our contributions represented ~64% of all the non-Apple commits, a figure that grew about ~11% compared to the past year. This confirms once again our commitment to WebKit, a project we started contributing about 14 years ago already, and where we have been systematically being the 2nd top contributor for a while now.

Main areas of work

The 10 main areas we have contributed to in WebKit in the past 12 months are the following ones:

  • Web platform
  • Graphics
  • Multimedia
  • JavaScriptCore
  • New WPE API
  • WebKit on Android
  • Quality assurance
  • Security
  • Tooling
  • Documentation

In the next sections I’ll talk a bit about what we’ve done and what we’re planning to do next for each of them.

Web Platform

content-visibility:auto

This feature allows skipping painting and rendering of off-screen sections, particularly useful to avoid the browser spending time rendering parts in large pages, as content outside of the view doesn’t get rendered until it gets visible.

We completed the implementation and it’s now enabled by default.

Navigation API

This is a new API to manage browser navigation actions and examine history, which we started working on in the past cycle. There’s been a lot of work happening here and, while it’s not finished yet, the current plan is that Apple will continue working on that in the next months.

hasUAVisualTransition

This is an attribute of the NavigateEvent interface, which is meant to be True if the User Agent has performed a visual transition before a navigation event. It was something that we have also finished implementing and is now also enabled by default.

Secure Curves in the Web Cryptography API

In this case, we worked on fixing several Web Interop related issues, as well as on increasing test coverage within the Web Platform Tests (WPT) test suites.

On top of that we also moved the X25519 feature to the “prepare to ship” stage.

Trusted Types

This work is related to reducing DOM-based XSS attacks. Here we finished the implementation and this is now pending to be enabled by default.

MathML

We continued working on the MathML specification by working on the support for padding, border and margin, as well as by increasing the WPT score by ~5%.

The plan for next year is to continue working on core features and improve the interaction with CSS.

Cross-root ARIA

Web components have accessibility-related issues with native Shadow DOM as you cannot reference elements with ARIA attributes across boundaries. We haven’t worked on this in this period, but the plan is to work in the next months on implementing the Reference Target proposal to solve those issues.

Canvas Formatted Text

Canvas has not a solution to add formatted and multi-line text, so we would like to also work on exploring and prototyping the Canvas Place Element proposal in WebKit, which allows better text in canvas and more extended features.

Graphics

Completed migration from Cairo to Skia for the Linux ports

If you have followed the latest developments, you probably already know that the Linux WebKit ports (i.e. WebKitGTK and WPE) have moved from Cairo to Skia for their 2D rendering library, which was a pretty big and important decision taken after a long time trying different approaches and experiments (including developing our own HW-accelerated 2D rendering library!), as well as running several tests and measuring results in different benchmarks.

Skia logoThe results in the end were pretty overwhelming and we decided to give Skia a go, and we are happy to say that, as of today, the migration has been completed: we covered all the use cases in Cairo, achieving feature parity, and we are now working on implementing new features and improvements built on top of Skia (e.g. GPU-based 2D rendering).

On top of that, Skia is now the default backend for WebKitGTK and WPE since 2.46.0, released on September 17th, so if you’re building a recent version of those ports you’ll be already using Skia as their 2D rendering backend. Note that Skia is using its GPU-based backend only on desktop environments, on embedded devices the situation is trickier and for now the default is the CPU-based Skia backend, but we are actively working to narrow the gap and to enable GPU-based rendering also on embedded.

Architecture changes with buffer sharing APIs (DMABuf)

We did a lot of work here, such as a big refactoring of the fencing system to control the access to the buffers, or the continued work towards integrating with Apple’s DisplayLink infrastructure.

On top of that, we also enabled more efficient composition using damaging information, so that we don’t need to pass that much information to the compositor, which would slow the CPU down.

Enablement of the GPUProcess

On this front, we enabled by default the compilation for WebGL rendering using the GPU process, and we are currently working in performance review and enabling it for other types of rendering.

New SVG engine (LBSE: Layer-Based SVG Engine)

If you are not familiar with this, here the idea is to make sure that we reuse the graphics pipeline used for HTML and CSS rendering, and use it also for SVG, instead of having its own pipeline. This means, among other things, that SVG layers will be supported as a 1st-class citizen in the engine, enabling HW-accelerated animations, as well as support for 3D transformations for individual SVG elements.

LBSE logo

On this front, on this cycle we added support for the missing features in the LBSE, namely:

  • Implemented support for gradients & patterns (applicable to both fill and stroke)
  • Implemented support for clipping & masking (for all shapes/text)
  • Implemented support for markers
  • Helped review implementation of SVG filters (done by Apple)

Besides all this, we also improved the performance of the new layer-based engine by reducing repaints and re-layouts as much as possible (further optimizations still possible), narrowing the performance gap with the current engine for MotionMark. While we are still not at the same level of performance as the current SVG engine, we are confident that there are several key places where, with the right funding, we should be able to improve the performance to at least match the current engine, and therefore be able to push the new engine through the finish line.

General overhaul of the graphics pipeline, touching different areas (WIP):

On top of everything else commented above, we also worked on a general refactor and simplification of the graphics pipeline. For instance, we have been working on the removal of the Nicosia layer now that we are not planning to have multiple rendering implementations, among other things.

Multimedia

DMABuf-based sink for HW-accelerated video

We merged the DMABuf-based sink for HW-accelerated video in the GL-based GStreamer sink.

WebCodecs backend

We completed the implementation of  audio/video encoding and decoding, and this is now enabled by default in 2.46. As for the next steps, we plan to keep working on the integration of WebCodecs with WebGL and WebAudio.

GStreamer-based WebRTC backends

We continued working on GstWebRTC, bringing it to a point where it can be used in production in some specific use cases, and we will still be working on this in the next months.

Other

Besides the points above, we also added an optional text-to-speech backend based on libspiel to the development branch, and worked on general maintenance around the support for Media Source Extensions (MSE) and Encrypted Media Extensions (EME), which are crucial for the use case of WPE running in set-top-boxes, and is a permanent task we will continue to work on in the next months.

JavaScriptCore

ARMv7/32-bit support:

A lot of work happened around 32-bit support in JavaScriptCore, especially around WebAssembly (WASM): we ported the WASM BBQJIT and ported/enabled concurrent JIT support, and we also completed 80% of the implementation for the OMG optimization level of WASM, which we plan to finish in the next months. If you are unfamiliar with what the OMG and BBQ optimization tiers in WASM are, I’d recommend you to take a look at this article in webkit.org: Assembling WebAssembly.

WASM logoWe also contributed to the JIT-less WASM, which is very useful for embedded systems that can’t support JIT for security or memory related constraints, and also did some work on the In-Place Interpreter (IPInt), which is a new version of the WASM Low-level interpreter (LLInt) that uses less memory and executes WASM bytecode directly without translating it to LLInt bytecode  (and should therefore be faster to execute).

Last, we also contributed most of the implementation for the WASM GC, with the exception of some Kotlin tests.

As for the next few months, we plan to investigate and optimize heap/JIT memory usage in 32-bit, as well as to finish several other improvements on ARMv7 (e.g. IPInt).

New WPE API

The new WPE API is a new API that aims at making it easier to use WPE in embedded devices, by removing the hassle of having to handle several libraries in tandem (i.e. WPEWebKit, libWPE and WPEBackend-FDO, for instance), available from WPE’s releases page, and providing a more modern API in general, better aimed at the most common use cases of WPE.

A lot of effort happened this year along these lines, including the fact that we finally upstreamed and shipped its initial implementation with WPE 2.44, back in the first half of the year. Now, while we recommend users to give it a try and report feedback as much as possible, this new API is still not set in stone, with regular development still ongoing, so if you have the chance to try it out and share your experience, comments are welcome!

Besides shipping its initial implementation, we also added support for external platforms, so that other ones can be loaded beyond the Wayland, DRM and “headless” ones, which are the default platforms already included with WPE itself. This means for instance that a GTK4 platform, or another one for RDK could be easily used with WPE.

Then of course a lot of API additions were included in the new API in the latest months:

  • Screens management APIAPI to handle different screens, ask the display for the list of screens with their device scale factor, refresh rate, geometry…
  • Top level management API: This API allows a greater degree of control, for instance by allowing more than one WebView for the same top level, as well as allowing to retrieve properties such as size, scale or state (i.e. full screen, maximized…).
  • Maximized and minimized windows API: API to maximize/minimize a top level and monitor its state. mainly used by WebDriver.
  • Preferred DMA-BUF formats API: enables asking the platform (compositor or DRM) for the list of preferred formats and their intended use (scanout/rendering).
  • Input methods APIallows platforms to provide an implementation to handle input events (e.g. virtual keyboard, autocompletion, auto correction…).
  • Gestures API: API to handle gestures (e.g. tap, drag).
  • Buffer damaging: WebKit generates information about the areas of the buffer that actually changed and we pass that to DRM or the compositor to optimize painting.
  • Pointer lock API: allows the WebView to lock the pointer so that the movement of the pointing device (e.g. mouse) can be used for a different purpose (e.g. first-person shooters).

Last, we also added support for testing automation, and we can support WebDriver now in the new API.

With all this done so far, the plan now is to complete the new WPE API, with a focus on the Settings API and accessibility support, write API tests and documentation, and then also add an external platform to support GTK4. This is done on a best-effort basis, so there’s no specific release date.

WebKit on Android

This year was also a good year for WebKit on Android, also known as WPE Android, as this is a project that sits on top of WPE and its public API (instead of developing a fully-fledged WebKit port).

Android logoIn case you’re not familiar with this, the idea here is to provide a WebKit-based alternative to the Chromium-based Web view on Android devices, in a way that leverages HW acceleration when possible and that it integrates natively (and nicely) with the several Android subsystems, and of course with Android’s native mainloop. Note that this is an experimental project for now, so don’t expect production-ready quality quite yet, but hopefully something that can be used to start experimenting with selected use cases.

If you’re adventurous enough, you can already try the APKs yourself from the releases page in GitHub at https://github.com/Igalia/wpe-android/releases.

Anyway, as for the changes that happened in the past 12 months, here is a summary:

  • Updated WPE Android to WPE 2.46 and NDK 27 LTS
  • Added support for WebDriver and included WPT test suites
  • Added support for instrumentation tests, and integrated with the GitHub CI
  • Added support for the remote Web inspector, very useful for debugging
  • Enabled the Skia backend, bringing HW-accelerated 2D rendering to WebKit on Android
  • Implemented prompt delegates, allowing implementing things such as alert dialogs
  • Implemented WPEView client interfaces, allowing responding to things such as HTTP errors
  • Packaged a WPE-based Android WebView in its own library and published in Maven Central. This is a massive improvement as now apps can use WPE Android by simply referencing the library from the gradle files, no need to build everything on their own.
  • Other changes: enabled HTTP/2 support (via the migration to libsoup3), added support for the device scale factor, improved the virtual on-screen keyboard, general bug fixing…

On top of that, we published 3 different blog posts covering different topics, from a general intro to a more deep dive explanation of the internals, and showing some demos. You can check them out in Jani’s blog at https://blogs.igalia.com/jani

As for the future, we’ll focus on stabilization and regular maintenance for now, and then we’d like to work towards achieving production-ready quality for specific cases if possible.

Quality Assurance

On the QA front, we had a busy year but in general we could highlight the following topics.

  • Fixed a lot of API tests failures in the bots that were limiting our test coverage.
  • Fixed lots of assertions-related crashes in the bots, which were slowing down the bots as well as causing other types of issues, such as bots exiting early due too many failures.
  • Enabled assertions in the release bots, which will help prevent crashes in the future, as well as with making our debug bots healthier.
  • Moved all the WebKitGTK and WPE bots to building now with Skia instead of Cairo. This means that all the bots running tests are now using Skia, and there’s only one bot still using Cairo to make sure that the compilation is not broken, but that bot does not run tests.
  • Moved all the WebKitGTK bots to use GTK4 by default. As with the move to Skia, all the WebKit bots running tests now use GTK4 and the only one remaining building with GTK3 does not run tests, it only makes sure we don’t break the GTK3 compilation for now.
  • Working on moving all the bots to use the new SDK. This is still work in progress and will likely be completed during 2025 as it’s needed to implement several changes in the infrastructure that will take some time.
  • General gardening and bot maintenance

In the next months, our main focus would be a revamp of the QA infrastructure to make sure that we can get all the bots (including the debug ones) to a healthier state, finish the migration of all the bots to the new SDK and, ideally, be able to bring back the ready-to-use WPE images that we used to have available in wpewebkit.org.

Security

The current release cadence has been working well, so we continue issuing major releases every 6 months (March, September), and then minor and unstable development releases happening on-demand when needed.

As usual, we kept aligning releases for WebKitGTK and WPE, with both of them happening at the same time (see https://webkitgtk.org/releases and https://wpewebkit.org/release), and then also publishing WebKit Security Advisories (WSA) when necessary, both for WebKitGTK and for WPE.

Last, we also shortened the time before including security fixes in stable releases this year, and we have removed support for libsoup2 from WPE, as that library is no longer maintained.

Tooling & Documentation

On tooling, the main piece of news is that this year we released the initial version of the new SDK,  which is developed on top of OCI-based containers. This new SDK fixes the issues with the current existing approaches based on JHBuild and flatpak, where one of them was great for development but poor for testing and QA, and the other one was great for testing and QA, but not very convenient for development.

This new SDK is regularly maintained and currently runs on Ubuntu 24.04 LTS with GCC 14 & Clang 18. It has been made public on GitHub and announced to the public in May 2024 in Patrick’s blog, and is now the officially recommended way of building WebKitGTK and WPE.

As for documentation, we didn’t do as much as we would have liked here, but we still landed a few contributions in docs.webkit.org, mostly related to WebKitGTK (e.g. Releases and VersioningSecurity UpdatesMultimedia). We plan to do more on this regard in the next months, though, mostly by writing/publishing more documentation and perhaps also some tutorials.

Final thoughts

This has been a fairly long blog post but, as you can see, it’s been quite a year for WebKit here at Igalia, with many exciting changes happening at several fronts, and so there was quite a lot of stuff to comment on here. This said, you can always check the slides of the presentation in the WebKit Contributors Meeting here if you prefer a more concise version of the same content.

In any case, what’s clear it’s that the next months are probably going to be quite interesting as well with all the work that’s already going on in WebKit and its Linux ports, so it’s possible that in 12 months from now I might be writing an equally long essay. We’ll see.

Thanks for reading!

November 01, 2024

A million portals

Approximately four years ago, I published the first release of ASHPD, one of my first Rust libraries, with the simple goal of making it easy to use XDG portals from Rust.

Since then, the library has grown to support all available portals and even includes a demo application showcasing some of these features.

Let's look at an example: the org.freedesktop.portal.Account portal. From the client side, an API end-user can request user information with the following code:

use ashpd::desktop::account::UserInformation;

async fn run() -> ashpd::Result<()> {
    let response = UserInformation::request()
        .reason("App would like to access user information")
        .send()
        .await?
        .response()?;

    println!("Name: {}", response.name());
    println!("ID: {}", response.id());

    Ok(())
}

This code calls the org.freedesktop.portal.Account.GetUserInformation D-Bus method, which xdg-desktop-portal will "redirect" to any portal frontend implementing the org.freedesktop.impl.portal.Account D-Bus interface.

So, how can you provide an implementation of org.freedesktop.impl.portal.Account in Rust? That's exactly what Maximiliano and I have been working on, building on the solid foundations we established earlier. I’m thrilled to announce that we finally shipped this functionality in the 0.10 release!

The first step is to implement the D-Bus interface, which we hide from the API’s end-user using traits.

use ashpd::{
    async_trait,
    backend::{
        account::{AccountImpl, UserInformationOptions},
        request::RequestImpl,
        Result,
    },
    desktop::account::UserInformation,
    AppID, WindowIdentifierType,
};

pub struct Account;

#[async_trait]
impl RequestImpl for Account {
    async fn close(&self) {
        // Close the dialog
    }
}

#[async_trait]
impl AccountImpl for Account {
    async fn get_user_information(
        &self,
        _app_id: Option<AppID>,
        _window_identifier: Option<WindowIdentifierType>,
        _options: UserInformationOptions,
    ) -> Result<UserInformation> {
        Ok(UserInformation::new(
            "user",
            "User",
            url::Url::parse("file://user/icon").unwrap(),
        ))
    }
}

Pretty straightforward! With the D-Bus interface implemented using ASHPD wrapper types, the next step is to export it on the bus.

use futures_util::future::pending;

async fn main() -> ashpd::Result<()> {
    ashpd::backend::Builder::new("org.freedesktop.impl.portal.desktop.mycustomportal")?
        .account(Account)
        .build()
        .await?;

    loop {
        pending::<()>().await;
    }
}

And that’s it—you’ve implemented your first portal frontend!

Currently, the backend feature doesn't yet support session-based portals, but we hope to add that functionality in the near future.

With over 1 million downloads, ASHPD has come a long way, and it wouldn’t have been possible without the support and contributions from the community. A huge thank you to everyone who has helped make this library what it is today.

October 31, 2024

The Bargain-Finder-inator 5000: One programmer's quest for a new flat

 The Bargain-Finder-inator 5000: One programmer's quest for a new flat

Or how I managed to get a reasonably priced apartment offer despite estate agencies

I think every one of us had to go through the hell that's searching for a new place to live. The reasons may be of all kinds, starting with moving between jobs or random life events, ending with your landlord wanting to raise your rent for fixing his couch despite your 3 years of begging for him to do so. You can guess my reasoning from that totally not suspiciously specific example, one thing's for certain - many of us, not lucky enough to be on their own yet, have to go through that not very delightful experience.

One major problem when scraping those online market websites, is that you're not the only one desperately doing so. And if it was only for the fellow lost souls who are trying to make ends meet, oh no - many real estate agencies say hello there as well. So when a very good offer finally comes up, one that you've been dreaming your whole life kind of one, you grab that phone and call them not maybe, but may they please-oh-lord pick up. Despite you wasting no breath, chances are that when you enthusiastically call them (after correcting the typos in the phone number you made out of excitement), you're already too late. Even though you ended up manually checking the damn website every 20 minutes (yup, I set an alarm), and you called after only a quarter, you were still not fast enough and there are already four people in line before you. Which in case of a good offer means it's as good as doughnuts at work you heard they were giving out to buy your sympathy for the corporate - gone even faster than they have probably arrived. Yup, that's basically the housing market situation in Poland, yay \o/

But do not abandon all hope ye who enter here -  after having only a couple of mental break downs my friend sent me a link to a program on github, that was supposed to scrap our local market website and give instance notice about new offers. The web page did have a similar function, but it only worked in theory - the emails about the "latest" offers came only once a day, not to mention the fact that they were from the day before. Oh well, in that case saying goodbye to the 20 minute alarm sounded like a dream come true, so I tried to configure the program olx-scraper to my needs. However, it turned out to be pretty useless as well - it would repeatedly fetch a whole list of offers from only one page of search results, and compare its size between iterations. If the length of such list increased, it would theoretically mean that there are new offers, and the program would send a mail notification that contained the whole list. While this approach kinda worked for searches that returns only a few results, the whole idea fell apart when there were more than could fit in one page. In that case the number of offers would seem to remain constant, and new offers would be missed. Another room for improvement was in lack of ability to ignore certain kinds of offers, such as ads, and not so helpful emails, which could just give you what you're looking for - the newest offer, instead of the whole list.

Here comes the sun in the form of the Bargain-Finder-inator 5000 to the rescue! I quickly realized that a few patches was not enough to fix the old program for my (or frankly saying anyone's) use case and re-wrote the whole searching algorithm, eventually leading to a whole new program. The original name was "Wyszukiwator-Mieszkań 5000", inspired by Dr. Doofenschmirtz various schemes and inventions, and roughly translates to "Searcher-Of-Flats 5000". However, as the project grew beyond the real estate market, I needed a new name that would reflect that - it also needed to be slightly more accessible for foreigners than our oh how beautiful polish words. So I came up with the current one, with the best fitting abbreviation: bf5000. I think it's kind of neat :)

Totally accurate photograph of me giving birth to Bargain-Finder-inator 5000 circa 2024, colorized


What Bargain-Finder-inator 5000 dutifully does is monitor a link you serve to it, pointing to an online marketplace, be it for a real estate market or any other you can think of. The catch is that it needs to be supported, but writing a new backend shouldn't be too much of a hassle, and when it is you can simply copy paste the URL of your search with all the necessary filters specified, and  give it to bf5000. You also need to specify the delay between each check for new offers, which consists of fetching only the latest offer, and comparing it with the previous "latest". If they don't match, then we are in for some goodies - an email notification with the link to the latest offer will be sent, so you need to specify the email title, addresses and the whole provider too. For more information, check out the repository on gitlab.

So, don't wait no more for better days, and be part of the change now! We can take back what's rightfully ours from those money-hungry real estate agencies! When I say Bargain, you say Finder-inator 5000! You get the idea.


October 23, 2024

Steam Deck, HID, and libmanette adventures

Screenshot of gamepad preferences in Highscore, showing Steam Deck gamepad

Recently, I got a Steam Deck OLED. Obviously, one of the main reasons for that is to run a certain yet to be announced here emulation app on it, so I installed Bazzite instead of SteamOS, cleaned up the preinstalled junk and got a clean desktop along with the Steam session/gaming mode.

For the most part, it just works (in desktop mode, at least), but there was one problematic area: input.

Gamepad input

Gamepads in general are difficult. While you can write generic evdev code dealing with, say, keyboard input and be reasonably sure it will work with at least the majority of keyboards, that’s not the case for gamepads. Buttons will use random input codes. Gamepads will assign different input types for the same control. (for example, D-pad can be presented as 4 buttons, 2 hat axes or 2 absolute axes). Linux kernel includes specialized hid drivers for some gamepads which will work reasonably well out of the box, but in general all bets are off.

Projects like SDL have gamepad mapping databases – normalizing input for all gamepads into a standardized list of inputs.

However, even that doesn’t guarantee they will work. Gamepads will pretend to be other gamepads (for example, it’s very common to emulate an Xbox gamepad) and will use incorrect mapping as a result. Some gamepads will even use identical IDs and provide physically different sets of buttons, meaning there’s no way to map both at the same time.

As such, apps have to expect that gamepad may or may not work correctly and user may or may not need to remap their gamepad.

Steam controllers

Both the standalone Steam Controller and Steam Deck’s internal gamepad pose a unique challenge: in addition to being gamepads with every problem mentioned above, they also emulate keyboard and pointer input. To make things more complicated, Steam has a built-in userspace HID driver for these controllers, with subtly different behavior between it and the Linux kernel driver. SteamOS and Bazzite both autostart Steam in background in desktop mode.

If one tries to use evdev in a generic way, same as for other gamepads, the results will not be pretty:

In desktop mode Steam emulates a virtual XInput (Xbox) gamepad. This gamepad works fine, except it lacks access to Steam and QAM buttons, as well as the 4 back buttons (L4, L5, R4, R5). This works perfectly fine for most games, but fails for emulators where in addition to the in-game controls you need a button to exit the game/open menu.

It also provides 2 action sets: Desktop and Gamepad. In desktop action set none of the gamepad buttons will even act like gamepad buttons, and instead will emulate keyboard and mouse. D-pad will act as arrow keys, A button will be Enter, B button will be Esc and so on. This is called “lizard mode” for some reason, and on Steam Deck is toggled by holding the Menu (Start) button. Once you switch to gamepad action set, gamepad buttons will act as a gamepad, with the caveat mentioned above.

Gamepad action set also makes the left touchpad behave differently: instead of scrolling and performing a middle click on press, it does a right click on press while moving finger on it does nothing.

hid-steam

Linux kernel includes a driver for these controllers, called hid-steam, so you don’t have to be running Steam for it to work. While it does most of the same things Steam’s userspace driver does, it’s not identical.

Lizard mode is similar, the only difference is that haptic feedback on the right touchpad stops right after lifting finger instead of after the cursor stops, while left touchpad scrolls with a different speed and does nothing on press.

The gamepad device is different tho – it’s now called “Steam Deck” instead of “Microsoft X-Box 360 pad 0” and this time every button is available, in addition to touchpads – presented as a hat and a button each (tho there’s no feedback when pressing).

The catch? It disables touchpads’ pointer input.

The driver was based on Steam Deck HID code from SDL, and in SDL it made sense – it’s made for (usually fullscreen) games, if you’re playing it with a gamepad, you don’t need a pointer anyway. It makes less sense in emulators or otherwise desktop apps tho. It would be really nice if we could have gamepad input AND touchpads. Ideally automatically, without needing to toggle modes manually.

libmanette

libmanette is the GNOME gamepad library, originally split from gnome-games. It’s very simple and basically acts as a wrapper around evdev and SDL mappings database, and has API for mapping gamepads from apps.

So, I decided to add support for Steam deck properly. This essentially means writing our own HID driver.

Steam udev rules

First, hidraw access is currently blocked by default and you need an udev rule to allow it. This is what the well known Steam udev rules do for Valve devices as well as a bunch of other well known gamepads.

There are a few interesting developments in kernel, logind and xdg-desktop-portal, so we may have easier access to these devices in future, but for now we need udev rules. That said, it’s pretty safe to assume that if you have a Steam Controller or Steam Deck, you already have those rules installed.

Writing a HID driver

Finally, we get to the main part of the article, everything before this was introduction.

We need to do a few things:

1. Disable lizard mode on startup
2. Keep disabling it every now and then, so that it doesn’t get reenabled (this is unfortunately necessary and SDL does the same thing)
3. Handle input ourselves
4. Handle rumble

Both SDL and hid-steam will be excellent references for most of this, and we’ll be referring to them a lot.

For the actual HID calls, we’ll be using hidapi.

Before that, we need to find the device itself. Raw HID devices are exposed differently from evdev ones, as /dev/hidraw* instead of /dev/input/event*, so first libmanette needs to search for those (either using gudev, or monitoring /dev when in flatpak).

Since we’re doing this for a very specific gamepad, we don’t need to worry about filtering out other input devices – this is an allowlist, so we just don’t include those. So we just match by vendor ID and product ID. Steam Deck is 28DE:1205 (at least OLED, but as far as I can tell the PID is the same for LCD).

However, there are 3 devices like that: the gamepad itself, but also its emulated mouse and keyboard. Well, sort of. Only hid-steam uses those devices, Steam instead sends them via XTEST. Since that obviously doesn’t work on Wayland, there’s instead a uinput device provided by extest.

SDL code tells us that only the gamepad device can actually receive HID reports, so the right device is the one that allows to read from it.

Disabling lizard mode

Next, we need to disable lizard mode. SDL sends an ID_CLEAR_DIGITAL_MAPPINGS report to disable keyboard/mouse emulation, then changes a few settings: namely, disables touchpads. As mentioned above, hid-steam does the same thing – it was based on this code.

However, we don’t want to disable touchpads here.

What we want to do instead is to send a ID_LOAD_DEFAULT_SETTINGS feature report to reset settings changed by hid-steam, and then only disable scrolling for the left touchpad. We’ll make it right click instead, like Steam does.

This will keep the right touchpad moving pointer, but the previous ID_CLEAR_DIGITAL_MAPPINGS report had disabled touchpad clicking, so we also need to restore it. For that, we need to use the ID_SET_DIGITAL_MAPPINGS report. SDL does not have an existing struct for its payload (likely because of struct padding issues), so I had to figure it out myself. The structure is as follows, after the standard zero byte and the header:

  • 8 bytes: buttons bitmask
  • 1 byte: emulated device type
  • 1 byte: a mouse button for DEVICE_MOUSE, a keyboard key for DEVICE_KEYBOARD, etc. Note that the SDL MouseButtons struct starts from 0 while the IDs Steam Deck accepts start from 1, so MOUSE_BTN_LEFT should be 1, MOUSE_BTN_RIGHT should be 2 and so on.

Then the structure repeats, up to 6 times in the same report.

ID_GET_DIGITAL_MAPPINGS returns the same structure.

So, setting digital mappings for:

  • STEAM_DECK_LBUTTON_LEFT_PAD, DEVICE_MOUSE, MOUSE_BTN_RIGHT
  • STEAM_DECK_LBUTTON_RIGHT_PAD, DEVICE_MOUSE, MOUSE_BTN_LEFT

(with the mouse button enum fixed to start from 1 instead of 0)

reenables clicking. Now we have working touchpads even without Steam running, with the rest of gamepad working as a gamepad, automatically.

Keeping it disabled

We also need to periodically do this again to prevent hid-steam from reenabling it. SDL does it every 200 updates, so about every 800 ms (update rate is 4 ms), and the same rate works fine here. Note that SDL doesn’t reset the same settings as initially, but only SETTING_RIGHT_TRACKPAD_MODE. I don’t know why, and doing the same thing did not work for me, so I just use the same code as detailed above instead and it works fine. It does mean that clicks from touchpad presses are ended and immediately restarted every 800 ms, but it doesn’t seem to cause any issues in practice, even with e.g. drag-n-drop)

Handling gamepad input

This part was straightforward. Every 4 ms we poll the gamepad and receive the entire state in a single struct: buttons as a bitmask, stick coordinates, trigger values, but also touchpad coordinates, touchpad pressure, accelerometer and gyro.

Right now we only expose a subset of buttons, as well as stick coordinates. There are some very interesting values in the button mask though – for example whether sticks are currently being touched, and whether touchpads are currently being touched and/or pressed. We may expose that in future, e.g. having API to disable touchpads like SDL does and instead offer the raw coordinates and pressure. Or do things on touch and/or click. Or send haptic feedback. We’ll see.

libmanette event API is pretty clunky, but it wasn’t very difficult to wrap these values and send them out.

Rumble

For rumble we’re doing the same thing as SDL: sending an ID_TRIGGER_RUMBLE_CMD report. There are a few magic numbers involved, e.g. for the left and right gain values – originated presumably in SDL, copied into hid-steam and now into libmanette as well ^^

Skipping duplicate devices

The evdev device for Steam Deck is still there, as is the virtual gamepad if Steam is running. We want to skip both of them. Thankfully, that’s easily done via checking VID/PID: Steam virtual gamepad is 28DE:11FF, while the evdev device has the same PID as the hidraw one. So, now we only have the HID device.

Behavior

So, how does all of this work now?

When Steam is not running, libmanette will automatically switch to gamepad mode, and enable touchpads. Once the app exits, it will revert to how it was before.

When Steam is running, libmanette apps will see exactly the same gamepad instead of the emulated one. However, we cannot disable lizard mode automatically in this state, so you’ll have to hold Menu button, or you’ll get input from both the gamepad and keyboard. Since Steam doesn’t disable touchpads in gamepad mode, they will still work as expected, so the only caveat is needing to hold Menu button.

So, it’s not perfect, but it’s a big improvement from how it was before.

Mappings

Now that libmanette has bespoke code specifically for Steam Deck, there are a few more questions. This gamepad doesn’t use mappings, and apps can safely assume it has all the advertised controls and nothing else. They can also know exactly what it looks like. So, libmanette now has ManetteDeviceType enum, currently with 2 values: MANETTE_DEVICE_GENERIC for evdev devices, and MANETTE_DEVICE_STEAM_DECK, for Steam Deck. In future we’ll likely have more dedicated HID drivers and as such more device types. For now though, that’s it.


The code is here, though it’s not merged yet.

Big thanks to people who wrote SDL and the hid-steam driver – I would definitely not be able to do this without being able to reference them. ^^