call_end

    • Pl chevron_right

      Felipe Borges: RHEL 10 (GNOME 47) Accessibility Conformance Report

      news.movim.eu / PlanetGnome • 13 April 2026

    Red Hat just published the Accessibility Conformance Report (ACR) for Red Hat Enterprise Linux 10 .

    Accessibility Conformance Reports basically document how our software measures up against accessibility standards like WCAG and Section 508 . Since RHEL 10 is built on GNOME 47, this report is a good look at how our stack handles various accessibility things from screen readers to keyboard navigation.

    Getting a desktop environment to meet these requirements is a huge task and it’s only possible because of the work done by our community in projects like: Orca, GTK, Libadwaita, Mutter, GNOME Shell, core apps, etc…

    Kudos to everyone in the GNOME project that cares about improving accessibility . We all know there’s a long way to go before desktop computing is fully accessible to everyone, but we are surely working on that.

    If you’re curious about the state of accessibility in the 47 release or how these audits work, you can find the full PDF here .

    • Pl chevron_right

      Peter Hutterer: Huion devices in the desktop stack

      news.movim.eu / PlanetGnome • 13 April 2026 • 13 minutes

    This post attempts to explain how Huion tablet devices currently integrate into the desktop stack. I'll touch a bit on the Huion driver and the OpenTablet driver but primarily this explains the intended integration[1]. While I have access to some Huion devices and have seen reports from others, there are likely devices that are slightly different. Huion's vendor ID is also used by other devices (UCLogic and Gaomon) so this applies to those devices as well.

    This post was written without AI support, so any errors are organic artisian hand-crafted ones. Enjoy.

    The graphics tablet stack

    First, a short overview of the ideal graphics tablet stack in current desktops. At the bottom is the physical device which contains a significant amount of firmware. That device provides something resembling the HID protocol over the wire (or bluetooth) to the kernel. The kernel typically handles this via the generic HID drivers [2] and provides us with an /dev/input/event evdev node, ideally one for the pen (and any other tool) and one for the pad (the buttons/rings/wheels/dials on the physical tablet). libinput then interprets the data from these event nodes, passes them on to the compositor which then passes them via Wayland to the client. Here's a simplified illustration of this:

    Unlike the X11 api, libinput's API works both per-tablet and per-tool basis. In other words, when you plug in a tablet you get a libinput device that has a tablet tool capability and (optionally) a tablet pad capability. But the tool will only show up once you bring it into proximity. Wacom tools have sufficient identifiers that we can a) know what tool it is and b) get a unique serial number for that particular device. This means you can, if you wanted to, track your physical tool as it is used on multiple devices. No-one [3] does this but it's possible. More interesting is that because of this you can also configure the tools individually, different pressure curves, etc. This was possible with the xf86-input-wacom driver in X but only with some extra configuration, libinput provides/requires this as the default behaviour.

    The most prominent case for this is the eraser which is present on virtually all pen-like tools though some will have an eraser at the tail end and others (the numerically vast majority) will have it hardcoded on one of the buttons. Changing to eraser mode will create a new tool (the eraser) and bring it into proximity - that eraser tool is logically separate from the pen tool and can thus be configured differently. [4]

    Another effect of this per-tool behaviour is also that we know exactly what a tool can do. If you use two different styli with different capabilities (e.g. one with tilt and 2 buttons, one without tilt and 3 buttons), they will have the right bits set. This requires libwacom - a library that tells us, simply: any tool with id 0x1234 has N buttons and capabilities A, B and C. libwacom is just a bunch of static text files with a C library wrapped around those. Without libwacom, we cannot know what any individual tool can do - the firmware and kernel always expose the capability set of all tools that can be used on any particular tablet. For example: wacom's devices support an airbrush tool so any tablet plugged in will announce the capabilities for an airbrush even though >99% of users will never use an airbrush [5].

    The compositor then takes the libinput events, modifies them (e.g. pressure curve handling is done by the compositor) and passes them via the Wayland protocol to the client. That protocol is a pretty close mirror of the libinput API so it works mostly the same. From then on, the rest is up to the application/toolkit.

    Notably, libinput is a hardware abstraction layer and conversion of hardware events into others is generally left to the compositor. IOW if you want a button to generate a key event, that's done either in the compositor or in the application/toolkit. But the current versions of libinput and the Wayland protocol do support all hardware features we're currently aware of: the various stylus types (including Wacom's lens cursor and mouse-like "puck" devices) and buttons, rings, wheels/dials, and touchstrips on pads. We even support the rather once-off Dell Canvas Totem device.

    Huion devices

    Huion's devices are HID compatible which means they "work" out of the box but they come in two different modes, let's call them firmware mode and tablet mode. Each tablet device pretends to be three HID devices on the wire and depending on the mode some of those devices won't send events.

    Firmware mode

    This is the default mode after plugging the device in. Two of the HID devices exposed look like a tablet stylus and a keyboard. The tablet stylus is usually correct (enough) to work OOTB with the generic kernel drivers, it exports the buttons, pressure, tilt, etc. The buttons and strips/wheels/dials on the tablet are configured to send key events. For example, the Inspiroy 2S I have sends b/i/e/Ctrl+S/space/Ctrl+Alt+z for the buttons and the roller wheel sends Ctrl-/Ctrl= depending on direction. The latter are often interpreted as zoom in/out so hooray, things work OOTB. Other Huion devices have similar bindings, there is quite some overlap but not all devices have exactly the same key assignments for each button. It does of course get a lot more interesting when you want a button to do something different - you need to remap the key event (ideally without messing up your key map lest you need to type an 'e' later).

    The userspace part is effectively the same, so here's a simplified illustration of what happens in kernel land:

    Any vendor-specific data is discarded by the kernel (but in this mode that HID device doesn't send events anyway).

    Tablet mode

    If you read a special USB string descriptor from the English language ID, the device switches into tablet mode. Once in tablet mode, the HID tablet stylus and keyboard devices will stop sending events and instead all events from the device are sent via the third HID device which consists of a single vendor-specific report descriptor (read: 11 bytes of "here be magic"). Those bits represent the various features on the device, including the stylus features and all pad features as buttons/wheels/rings/strips (and not key events!). This mode is the one we want to handle the tablet properly. The kernel's hid-uclogic driver switches into tablet mode for supported devices, in userspace you can use e.g. huion-switcher . The device cannot be switched back to firmware mode but will return to firmware mode once unplugged.

    Once we have the device in tablet mode, we can get true tablet data and pass it on through our intended desktop stack. Alas, like ogres there are layers.

    hid-uclogic and udev-hid-bpf

    Historically and thanks in large parts to the now-discontinued digimend project , the hid-uclogic kernel driver did do the switching into tablet mode, followed by report descriptor mangling (inside the kernel) so that the resulting devices can be handled by the generic HID drivers. The more modern approach we are pushing for is to use udev-hid-bpf which is quite a bit easer to develop for. But both do effectively the same thing: they overlay the vendor-specific data with a normal HID report descriptor so that the incoming data can be handled by the generic HID kernel drivers. This will look like this:

    Notable here: the stylus and keyboard may still exist and get event nodes but never send events[6] but the uclogic/bpf-enabled device will be proper stylus/pad event nodes that can be handled by libinput (and thus the rest), with raw hardware data where buttons are buttons.

    Challenges

    Because in true manager speak we don't have problems, just challenges. And oh boy, we collect challenges as if we'd be organising the olypmics.

    hid-uclogic and libinput

    First and probably most embarrassing is that hid-uclogic has a different way of exposing event nodes than what libinput expects. This is largely my fault for having focused on Wacom devices and internalized their behaviour for long years. The hid-uclogic driver exports the wheels and strips on separate event nodes - libinput doesn't handle this correctly (or at all). That'd be fixable but the compositors also don't really expect this so there's a bit more work involved but the immediate effect is that those wheels/strips will likely be ignored and not work correctly. Buttons and pens work.

    udev-hid-bpf and huion-switcher

    hid-uclogic being a kernel driver has access to the underlying USB device. The HID-BPF hooks in the kernel currently do not, so we cannot switch the device into tablet mode from a BPF, we need it in tablet mode already. This means a userspace tool (read: huion-switcher) triggered via udev on plug-in and before the udev-hid-bpf udev rules trigger. Not a problem but it's one more moving piece that needs to be present (but boy, does this feel like the unix way...).

    Huion's precious product IDs

    By far the most annoying part about anything Huion is that until relatively recently (I don't have a date but maybe until 2 years ago) all of Huion's devices shared the same few USB product IDs. For most of these devices we worked around it by matching on device names but there were devices that had the same product id and device name. At some point libwacom and the kernel and huion-switcher had to implement firmware ID extraction and matching so we could differ between devices with the same 0256:006d usb IDs. Luckily this seems to be in the past now with modern devices now getting new PIDs for each individual device. But if you have an older device, expect difficulties and, worse, things to potentially break after firmware updates when/if the firmware identification string changes. udev-hid-bpf (and uclogic) rely on the firmware strings to identify the device correctly.

    edit: and of course less than 24h after posting this I process a bug report about two completely different new devices sharing one of the product IDs

    udev-hid-bpf and hid-uclogic

    Because we have a changeover from the hid-uclogic kernel driver to the udev-hid-bpf files there are rough edges on "where does this device go". The general rule is now: if it's not a shared product ID (see above) it should go into udev-hid-bpf and not the uclogic driver. Easier to maintain, much more fire-and-forget. Devices already supported by udev-hid-bpf will remain there, we won't implement BPFs for those (older) devices, doubly so because of the aforementioned libinput difficulties with some hid-uclogic features.

    Reverse engineering required

    The newer tablets are always slightly different so we basically need to reverse-engineer each tablet to get it working. That's common enough for any device but we do rely on volunteers to do this. Mind you, the udev-hid-bpf approach is much simpler than doing it in the kernel, much of it is now copy-paste and I've even had quite some success to get e.g. Claude Code to spit out a 90% correct BPF on its first try. At least the advantage of our approach to change the report descriptor means once it's done it's done forever, there is no maintenance required because it's a static array of bytes that doesn't ever change.

    Plumbing support into userspace

    Because we're abstracting the hardware, userspace needs to be fully plumbed. This was a problem last year for example when we (slowly) got support for relative wheels into libinput, then wayland, then the compositors, then the toolkits to make it available to the applications (of which I think none so far use the wheels). Depending on how fast your distribution moves, this may mean that support is months and years off even when everything has been implemented. On the plus side these new features tend to only appear once every few years. Nonetheless, it's not hard to see why the "just sent Ctrl=, that'll do" approach is preferred by many users over "probably everything will work in 2027, I'm sure".

    So, what stylus is this?

    A currently unsolved problem is the lack of tool IDs on all Huion tools. We cannot know if the tool used is the two-button + eraser PW600L or the three-button-one-is-an-eraser-button PW600S or the two-button PW550 (I don't know if it's really 2 buttons or 1 button + eraser button). We always had this problem with e.g. the now quite old Wacom Bamboo devices but those pens all had the same functionality so it just didn't matter. It would matter less if the various pens would only work on the device they ship with but it's apparently quite possible to use a 3 button pen on a tablet that shipped with a 2 button pen OOTB. This is not difficult to solve (pretend to support all possible buttons on all tools) but it's frustrating because it removes a bunch of UI niceties that we've had for years - such as the pen settings only showing buttons that actually existed. Anyway, a problem currently in the "how I wish there was time" basket.

    Summary

    Overall, we are in an ok state but not as good as we are for Wacom devices. The lack of tool IDs is the only thing not fixable without Huion changing the hardware[7]. The delay between a new device release and driver support is really just dependent on one motivated person reverse-engineering it (our BPFs can work across kernel versions and you can literally download them from a successful CI pipeline ). The hid-uclogic split should become less painful over time and the same as the devices with shared USB product IDs age into landfill and even more so if libinput gains support for the separate event nodes for wheels/strips/... (there is currently no plan and I'm somewhat questioning whether anyone really cares). But other than that our main feature gap is really the ability for much more flexible configuration of buttons/wheels/... in all compositors - having that would likely make the requirement for OpenTabletDriver and the Huion tablet disappear.

    OpenTabletDriver and Huion's own driver

    The final topic here: what about the existing non-kernel drivers?

    Both of these are userspace HID input drivers which all use the same approach: read from a /dev/hidraw node, create a uinput device and pass events back. On the plus side this means you can do literally anything that the input subsystem supports, at the cost of a context switch for every input event. Again, a diagram on how this looks like (mostly) below userspace:

    Note how the kernel's HID devices are not exercised here at all because we parse the vendor report, create our own custom (separate) uinput device(s) and then basically re-implement the HID to evdev event mapping. This allows for great flexibility (and control, hence the vendor drivers are shipped this way) because any remapping can be done before you hit uinput. I don't immediately know whether OpenTabletDriver switches to firmware mode or maps the tablet mode but architecturally it doesn't make much difference.

    From a security perspective: having a userspace driver means you either need to run that driver daemon as root or (in the case of OpenTabletDriver at least) you need to allow uaccess to /dev/uinput , usually via udev rules. Once those are installed , anything can create uinput devices, which is a risk but how much is up for interpretation.

    [1] As is so often the case, even the intended state does not necessarily spark joy
    [2] Again, we're talking about the intended case here...
    [3] fsvo "no-one"
    [4] The xf86-input-wacom driver always initialises a separate eraser tool even if you never press that button
    [5] For historical reasons those are also multiplexed so getting ABS_Z on a device has different meanings depending on the tool currently in proximity
    [6] In our udev-hid-bpf BPFs we hide those devices so you really only get the correct event nodes, I'm not immediately sure what hid-uclogic does
    [7] At which point Pandora will once again open the box because most of the stack is not yet ready for non-Wacom tool ids

    • Pl chevron_right

      Jakub Steiner: release.gnome.org refactor

      news.movim.eu / PlanetGnome • 13 April 2026 • 1 minute

    After successfully moving this blog to Zola , doubts got suppressed and I couldn't resist porting the GNOME Release Notes too.

    The Proof

    The blog port worked better than expected. Fighting CI github action was where most enthusiasm was lost. The real test though was whether Zola could handle a site way more important than my little blog — one hosting release notes for GNOME.

    What Changed

    The main work was porting the templates from Liquid to Tera, the same exercise as the blog. That included structural change to shift releases from Jekyll pages to proper Zola posts . This enabled two things that weren't possible before:

    • RSS feed — With releases as posts, generating a feed is native. Something I was planning to do in the Jekyll world … but there were roadblocks .
    • The archive — Old release notes going back to GNOME 2.x have been properly ported over. They're now part of the navigable archive instead of lost to the ages. I'm afraid it's quite a cringe town if you hold nostalgic ideas how amazing things were back in the day.

    The Payoff

    The site now has a working RSS feed — years of broken promises finally fulfilled. The full archive from GNOME 2.x through 50 is available. And perhaps best of all: zero dependency management and supporting people who "just want to write a bit of markdown". Just a single binary.

    I'd say it's another success story and if I were a Jekyll project in the websites team space , I'd start to worry.

    • Pl chevron_right

      Bilal Elmoussaoui: goblint: A Linter for GObject C Code

      news.movim.eu / PlanetGnome • 11 April 2026 • 2 minutes

    Over the past week, I’ve been building goblint , a linter specifically designed for GObject-based C codebases.

    If you know Rust’s clippy or Go’s go vet , think of goblint as the same thing for GObject/GLib.

    Why this exists

    A large part of the Linux desktop stack (GTK, Mutter, Pango, NetworkManager) is built on GObject. These projects have evolved over decades and carry a lot of patterns that predate newer GLib helpers, are easy to misuse, or encode subtle lifecycle invariants that nothing verifies.

    This leads to issues like missing dispose / finalize / constructed chain-ups (memory leaks or undefined behavior), incorrect property definitions, uninitialized GError* variables, or function declarations with no implementation.

    These aren’t theoretical. This GTK merge request recently fixed several missing chain-ups in example code.

    Despite this, the C ecosystem lacks a linter that understands GObject semantics. goblint exists to close that gap.

    What goblint checks

    goblint ships with 35 rules across different categories:

    • Correctness : Real bugs like non-canonical property names, uninitialized GError* , missing PROP_0
    • Suspicious : Likely mistakes like missing implementations or redundant NULL checks
    • Style : Idiomatic GLib usage ( g_strcmp0 , g_str_equal() )
    • Complexity : Suggests modern helpers ( g_autoptr , g_clear_* , g_set_str() )
    • Performance : Optimizations like G_PARAM_STATIC_STRINGS or g_object_notify_by_pspec()
    • Pedantic : Consistency checks (macro semicolons, matching declare/define pairs)

    23 out of 35 rules are auto-fixable. You should apply fixes one rule at a time to review the changes:

    goblint --fix --only use_g_strcmp0
    goblint --fix --only use_clear_functions
    

    CI/CD Integration

    goblint fits into existing pipelines.

    GitHub Actions

    - name: Run goblint
      run: goblint --format sarif > goblint.sarif
    
    - name: Upload SARIF results
      uses: github/codeql-action/upload-sarif@v3
      with:
        sarif_file: goblint.sarif
    

    Results show up in the Security tab under "Code scanning" and inline on pull requests.

    GitLab CI

    goblint:
      image: ghcr.io/bilelmoussaoui/goblint:latest
      script:
        - goblint --format sarif > goblint.sarif
      artifacts:
        reports:
          sast: goblint.sarif
    

    Results appear inline in merge requests.

    Configuration

    Rules default to warn , and can be tuned via goblint.toml :

    min_glib_version = "2.40"  # Auto-disable rules for newer versions
    
    [rules]
    g_param_spec_static_name_canonical = "error"  # Make critical
    use_g_strcmp0 = "warn"  # Keep as warning
    use_g_autoptr_inline_cleanup = "ignore"  # Disable
    
    # Per-rule ignore patterns
    missing_implementation = { level = "error", ignore = ["src/backends/**"] }
    

    You can adopt it gradually without fixing everything at once.

    Try it

    # Run via container
    podman run --rm -v "$PWD:/workspace:Z" ghcr.io/bilelmoussaoui/goblint:latest
    
    # Install locally
    cargo install --git https://github.com/bilelmoussaoui/goblint goblint
    
    # Usage
    goblint              # Lint current directory
    goblint --fix        # Apply automatic fixes
    goblint --list-rules # Inspect available rules
    

    The project is early, so feedback is especially valuable (false positives, missing checks, workflow issues, etc.).


    Note: The project was originally named "goblin" but was renamed to "goblint" to avoid conflicts with the existing goblin crate for parsing binary formats.

    • Pl chevron_right

      This Week in GNOME: #244 Recognizing Hieroglyphs

      news.movim.eu / PlanetGnome • 10 April 2026 • 4 minutes

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

    GNOME Core Apps and Libraries

    Blueprint

    A markup language for app developers to create GTK user interfaces.

    James Westman reports

    blueprint-compiler is now available on PyPI. You can install it with pip install blueprint-compiler .

    GNOME Circle Apps and Libraries

    Hieroglyphic

    Find LaTeX symbols

    FineFindus reports

    Hieroglyphic 2.3 is out now. Thanks to the exciting work done by Bnyro, Hieroglyphic can now also recognize Typst symbols (a modern alternative to LaTeX). Hardware-acceleration will now be preferred, when available, reducing power-consumption.

    Download the latest version from FlatHub .

    hieroglyphic_typst_symbols.wOxbuouY_Z2f6K8J.webp

    Amberol

    Plays music, and nothing else.

    Emmanuele Bassi says

    Amberol 2026.1 is out, using the GNOME 50 run time! This new release fixes a few issues when it comes to loading music, and has some small quality of life improvements in the UI, like: a more consistent visibility of the playlist panel when adding songs or searching; using the shortcuts dialog from libadwaita; and being able to open the file manager in the folder containing the current song. You can get Amberol on Flathub .

    amberol-2026-1.P7qMWOfZ_ZEOvUr.webp

    Third Party Projects

    Alexander Vanhee says

    A new version of Bazaar is out now. It features the ability to filter search results via a new popover and reworks the add-ons dialog to include a page that shows more information about a specific entry. If you try to open an add-on via the AppStream scheme, it will now display this page, which is useful when you want to redirect users to install an add-on from within your app.

    Also, please take a look at the statistics dialog — it now features a cool gradient.

    Check it out on Flathub

    bazaar_filter.BEY1Y2IA_Z2ct3wc.webp

    bazaar_addon.CpggJJ7h_1ucB0G.webp

    bazaar_gradient.Bo85-k8K_Z1FCB1D.webp

    dabrain34 reports

    GstPipelineStudio 0.5.1 is out now. It’s a great pleasure to announce this new version allowing to deal with DOT files directly. Check the project web page for more information or the following blog post for more details about the release.

    gps_screenshot.CLpepb66_Z1zRPBI.webp

    Anton Isaiev announces

    RustConn (connection manager for SSH, RDP, VNC, SPICE, Telnet, Serial, Kubernetes, MOSH, and Zero Trust protocols)

    Versions 0.10.9–0.10.14 landed with a solid round of usability, security, and performance work.

    Staying connected got easier. If an SSH session drops unexpectedly, RustConn now polls the host and reconnects on its own as soon as it’s back. Wake-on-LAN works the same way: send the magic packet and RustConn connects automatically once the machine boots. You can also right-click any connection to check if the host is online, and a new “Connect All” option opens every connection in a folder at once. For RDP there’s a Mouse Jiggler that keeps idle sessions alive.

    Terminal Activity Monitor is a new per-session feature that watches for output activity or silence, which is handy for long-running jobs. You get notifications as tab icons, toasts, and desktop alerts when the window is in the background.

    Security got a lot of attention. RDP now defaults to trust-on-first-use certificate validation instead of blindly accepting everything. Credentials for Bitwarden and 1Password are no longer visible in the process list. VNC passwords are zeroized on drop. Export files are written with owner-only permissions. Dangerous custom arguments are blocked for both VNC and FreeRDP viewers.

    Hoop.dev joins as the 11th Zero Trust provider. There’s also a new custom SSH agent socket setting that lets Flatpak users connect through KeePassXC, Bitwarden, or GPG-based SSH agents, something the Flatpak sandbox previously made difficult.

    Smoother on HiDPI and 4K. RDP frame rendering skips a 33 MB per-frame copy when the data is already in the right format. Highlight rules, search, and log sanitization patterns are compiled once instead of on every keystroke or terminal line.

    GNOME HIG polish. Success notifications now use non-blocking toasts instead of modal dialogs. Sidebar context menus are native PopoverMenus with keyboard navigation and screen reader support. Translations completed for all 15 languages.

    Project: https://github.com/totoshko88/RustConn Flatpak: https://flathub.org/en/apps/io.github.totoshko88.RustConn

    rustconn.B0H0ecFv_Z8nore.webp

    Phosh

    A pure wayland shell for mobile devices.

    Guido announces

    Phosh 0.54 is out:

    There’s now a notification when an app fails to start, the status bar can be extended via plugins, and the location quick toggle has a status page to set the maximum allowed accuracy.

    On the compositor side we improved X11 support, making docked mode (aka convergence) with applications like emacs or ardour more fun to use.

    The on screen keyboard Stevia now supports Japanese and Chinese input via UIM, has a new us+workman layout and automatic space handling can be disabled.

    There’s more - see the full details here .

    phosh-app-failed-to-start-notification.cQ6G-QDG_Z2u7AWC.webp

    Documentation

    Emmanuele Bassi announces

    The GNOME User documentation project has been ported to use Meson for its configuration, build, and installation. The User documentation contains the desktop help and the system administration guide, and gets published on the user help website , as well as being available locally through the Help browser . The switch to Meson improved build times, and moved the tests and validation in the build system. There’s a whole new contribution guideline as well. If you want to help writing the GNOME documentation, join us in the Docs room on Matrix !

    Shell Extensions

    Weather O’Clock

    Display the current weather inside the pill next to the clock.

    Cleo Menezes Jr. reports

    Weather O’Clock 50 released with fluffier animations: smooth fades between loading, weather and offline states; instant temperature updates; first-fetch spinner; offline indicator; GNOME Shell 45–50 support; and various bug fixes.

    Get it on GNOME Extensions

    Follow development

    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!

    • Pl chevron_right

      Andy Wingo: wastrel milestone: full hoot support, with generational gc as a treat

      news.movim.eu / PlanetGnome • 9 April 2026 • 7 minutes

    Hear ye, hear ye: Wastrel and Hoot means REPL!

    Which is to say, Wastrel can now make native binaries out of WebAssembly files as produced by the Hoot Scheme toolchain, up to and including a full read-eval-print loop. Like the REPL on the Hoot web page , but instead of requiring a browser, you can just run it on your console. Amazing stuff!

    try it at home

    First, we need the latest Hoot. Build it from source , then compile a simple REPL:

    echo '(import (hoot repl)) (spawn-repl)' > repl.scm
    ./pre-inst-env hoot compile -fruntime-modules -o repl.wasm repl.scm
    

    This takes about a minute. The resulting wasm file has a pretty full standard library including a full macro expander and evaluator.

    Normally Hoot would do some aggressive tree-shaking to discard any definitions not used by the program, but with a REPL we don’t know what we might need. So, we pass -fruntime-modules to instruct Hoot to record all modules and their bindings in a central registry, so they can be looked up at run-time. This results in a 6.6 MB Wasm file; with tree-shaking we would have been at 1.2 MB.

    Next, build Wastrel from source , and compile our new repl.wasm :

    wastrel compile -o repl repl.wasm
    

    This takes about 5 minutes on my machine: about 3 minutes to generate all the C, about 6.6MLOC all in all, split into a couple hundred files of about 30KLOC each, and then 2 minutes to compile with GCC and link-time optimization (parallelised over 32 cores in my case). I have some ideas to golf the first part down a bit, but the the GCC side will resist improvements.

    Finally, the moment of truth:

    $ ./repl
    Hoot 0.8.0
    
    Enter `,help' for help.
    (hoot user)> "hello, world!"
    => "hello, world!"
    (hoot user)>
    

    statics

    When I first got the REPL working last week, I gasped out loud: it’s alive, it’s alive!!! Now that some days have passed, I am finally able to look a bit more dispassionately at where we’re at.

    Firstly, let’s look at the compiled binary itself. By default, Wastrel passes the -g flag to GCC, which results in binaries with embedded debug information. Which is to say, my ./repl is chonky: 180 MB!! Stripped, it’s “just” 33 MB. 92% of that is in the .text (code) section. I would like a smaller binary, but it’s what we got for now: each byte in the Wasm file corresponds to around 5 bytes in the x86-64 instruction stream.

    As for dependencies, this is a pretty minimal binary, though dynamically linked to libc :

    linux-vdso.so.1 (0x00007f6c19fb0000)
    libm.so.6 => /gnu/store/…-glibc-2.41/lib/libm.so.6 (0x00007f6c19eba000)
    libgcc_s.so.1 => /gnu/store/…-gcc-15.2.0-lib/lib/libgcc_s.so.1 (0x00007f6c19e8d000)
    libc.so.6 => /gnu/store/…-glibc-2.41/lib/libc.so.6 (0x00007f6c19c9f000)
    /gnu/store/…-glibc-2.41/lib/ld-linux-x86-64.so.2 (0x00007f6c19fb2000)
    

    Our compiled ./repl includes a garbage collector from Whippet , about which, more in a minute. For now, we just note that our use of Whippet introduces no run-time dependencies.

    dynamics

    Just running the REPL with WASTREL_PRINT_STATS=1 in the environment, it seems that the REPL has a peak live data size of 4MB or so, but for some reason uses 15 MB total. It takes about 17 ms to start up and then exit.

    These numbers I give are consistent over a choice of particular garbage collector implementations: the default --gc=stack-conservative-parallel-generational-mmc , or the non-generational stack-conservative-parallel-mmc , or the Boehm-Demers-Weiser bdw . Benchmarking collectors is a bit gnarly because the dynamic heap growth heuristics aren’t the same between the various collectors; by default, the heap grows to 15 MB or so with all collectors, but whether it chooses to collect or expand the heap in response to allocation affects startup timing. I get the above startup numbers by setting GC_OPTIONS=heap-size=15m,heap-size-policy=fixed in the environment.

    Hoot implements Guile Scheme , so we can also benchmark Hoot against Guile. Given the following test program that sums the leaf values for ten thousand quad trees of height 5:

    (define (quads depth)
      (if (zero? depth)
          1
          (vector (quads (- depth 1))
                  (quads (- depth 1))
                  (quads (- depth 1))
                  (quads (- depth 1)))))
    (define (sum-quad q)
      (if (vector? q)
          (+ (sum-quad (vector-ref q 0))
             (sum-quad (vector-ref q 1))
             (sum-quad (vector-ref q 2))
             (sum-quad (vector-ref q 3)))
          q))
    
    (define (sum-of-sums n depth)
      (let lp ((n n) (sum 0))
        (if (zero? n)
            sum
            (lp (- n 1)
                (+ sum (sum-quad (quads depth)))))))
    
    
    (sum-of-sums #e1e4 5)
    

    We can cat it to our repl to see how we do:

    Hoot 0.8.0
    
    Enter `,help' for help.
    (hoot user)> => 10240000
    (hoot user)>
    Completed 3 major collections (281 minor).
    4445.267 ms total time (84.214 stopped); 4556.235 ms CPU time (189.188 stopped).
    0.256 ms median pause time, 0.272 p95, 7.168 max.
    Heap size is 28.269 MB (max 28.269 MB); peak live data 9.388 MB.
    

    That is to say, 4.44s, of which 0.084s was spent in garbage collection pauses. The default collector configuration is generational, which can result in some odd heap growth patterns; as it happens, this workload runs fine in a 15MB heap. Pause time as a percentage of total run-time is very low, so all the various GCs perform the same, more or less; we seem to be benchmarking eval more than the GC itself.

    Is our Wastrel-compiled repl performance good? Well, we can evaluate it in two ways. Firstly, against Chrome or Firefox, which can run the same program; if I paste in the above program in the REPL over at the Hoot web site , it takes about 5 or 6 times as long to complete, respectively. Wastrel wins!

    I can also try this program under Guile itself: if I eval it in Guile, it takes about 3.5s. Granted, Guile’s implementation of the same source language is different, and it benefits from a number of representational tricks, for example using just two words for a pair instead of four on Hoot+Wastrel. But these numbers are in the same ballpark, which is heartening. Compiling the test program instead of interpreting is about 10× faster with both Wastrel and Guile, with a similar relative ratio.

    Finally, I should note that Hoot’s binaries are pretty well optimized in many ways, but not in all the ways. Notably, they use too many locals, and the post-pass to fix this is unimplemented , and last time I checked (a long time ago!), wasm-opt didn’t work on our binaries. I should take another look some time.

    generational?

    This week I dotted all the t’s and crossed all the i’s to emit write barriers when we mutate the value of a field to store a new GC-managed data type, allowing me to enable the sticky mark-bit variant of the Immix-inspired mostly-marking collector . It seems to work fine, though this kind of generational collector still baffles me sometimes .

    With all of this, Wastrel’s GC-using binaries use a stack-conservative , parallel , generational collector that can compact the heap as needed. This collector supports multiple concurrent mutator threads, though Wastrel doesn’t do threading yet. Other collectors can be chosen at compile-time, though always-moving collectors are off the table due to not emitting stack maps.

    The neat thing is that any language that compiles to Wasm can have any of these collectors! And when the Whippet GC library gets another collector or another mode on an existing collector, you can have that too.

    missing pieces

    The biggest missing piece for Wastrel and Hoot is some kind of asynchrony, similar to JavaScript Promise Integration (JSPI) , and somewhat related to stack switching . You want Wasm programs to be able to wait on external events, and Wastrel doesn’t support that yet.

    Other than that, it would be lovely to experiment with Wasm shared-everything threads at some point.

    what’s next

    So I have an ahead-of-time Wasm compiler. It does GC and lots of neat things. Its performance is state-of-the-art. It implements a few standard libraries, including WASI 0.1 and Hoot. It can make a pretty good standalone Guile REPL. But what the hell is it for?

    Friends, I... I don’t know! It’s really cool, but I don’t yet know who needs it. I have a few purposes of my own (pushing Wasm standards, performance work on Whippet, etc), but you or someone you know needs a wastrel, do let me know at wingo@igalia.com : I would love to be able to spend more time hacking in this area.

    Until next time, happy compiling to all!

    • Pl chevron_right

      Andy Wingo: the value of a performance oracle

      news.movim.eu / PlanetGnome • 7 April 2026 • 5 minutes

    Over on his excellent blog, Matt Keeter posts some results from having ported a bytecode virtual machine to tail-calling style . He finds that his tail-calling interpreter written in Rust beats his switch-based interpreter, and even beats hand-coded assembly on some platforms.

    He also compares tail-calling versus switch-based interpreters on WebAssembly, and concludes that performance of tail-calling interpreters in Wasm is terrible:

    1.2× slower on Firefox, 3.7× slower on Chrome, and 4.6× slower in wasmtime. I guess patterns which generate good assembly don't map well to the WASM stack machine, and the JITs aren't smart enough to lower it to optimal machine code.

    In this article, I would like to argue the opposite: patterns that generate good assembly map just fine to the Wasm stack machine, and the underperformance of V8, SpiderMonkey, and Wasmtime is an accident.

    some numbers

    I re-ran Matt’s experiment locally on my x86-64 machine (AMD Ryzen Threadripper PRO 5955WX). I tested three toolchains:

    • Compiled natively via cargo / rustc

    • Compiled to WebAssembly, then run with Wasmtime

    • Compiled to WebAssembly, then run with Wastrel

    For each of these toolchains, I tested Raven as implemented in Rust in both “switch-based” and “tail-calling” modes. Additionally, Matt has a Raven implementation written directly in assembly; I test this as well, for the native toolchain. All results use nightly/git toolchains from 7 April 2026.

    My results confirm Matt’s for the native and wasmtime toolchains, but wastrel puts them in context:

    Bar charts showing native, wasmtime, and wastrel scenarios testing tail-calling versus switch implementations; wasmtime slows down for tail-calling, whereas wastrel speeds up.

    We can read this chart from left to right: a switch-based interpreter written in Rust is 1.5× slower than a tail-calling interpreter, and the tail-calling interpreter just about reaches the speed of hand-written assembler. (Testing on AArch64, Matt even sees the tail-calling interpreter beating his hand-written assembler.)

    Then moving to WebAssembly run using Wasmtime, we see that Wasmtime takes 4.3× as much time to run the switch-based interpreter, compared to the fastest run from the hand-written assembler, and worse, actually shows 6.5× overhead for the tail-calling interpreter. Hence Matt’s conclusions: there must be something wrong with WebAssembly.

    But if we compare to Wastrel , we see a different story: Wastrel runs the basic interpreter with 2.4× overhead, and the tail-calling interpreter improves on this marginally with a 2.3x overhead. Now, granted, two-point-whatever-x is not one; Matt’s Raven VM still runs slower in Wasm than when compiled natively. Still, a tail-calling interpreter is inherently a pretty good idea.

    where does the time go

    When I think about it, there’s no reason that the switch-based interpreter should be slower when compiled via Wastrel than when compiled via rustc . Memory accesses via Wasm should actually be cheaper due to 32-bit pointers, and all the rest of it should be pretty much the same. I looked at the assembly that Wastrel produces and I see most of the patterns that I would expect.

    I do see, however, that Wastrel repeatedly reloads a struct memory value, containing the address (and size) of main memory. I need to figure out a way to keep this value in registers. I don’t know what’s up with the other Wasm implementations here; for Wastrel, I get 98% of time spent in the single interpreter function, and surely this is bread-and-butter for an optimizing compiler such as Cranelift. I tried pre-compilation in Wasmtime but it didn’t help. It could be that there is a different Wasmtime configuration that allows for higher performance.

    Things are more nuanced for the tail-calling VM. When compiling natively, Matt is careful to use a preserve_none calling convention for the opcode-implementing functions, which allows LLVM to allocate more registers to function parameters; this is just as well, as it seems that his opcodes have around 9 parameters. Wastrel currently uses GCC’s default calling convention, which only has 6 registers for non-floating-point arguments on x86-64, leaving three values to be passed via global variables (described here ); this obviously will be slower than the native build. Perhaps Wastrel should add the equivalent annotation to tail-calling functions.

    On the one hand, Cranelift (and V8) are a bit more constrained than Wastrel by their function-at-a-time compilation model that privileges latency over throughput; and as they allow Wasm modules to be instantiated at run-time, functions are effectively closures, in which the “instance” is an additional hidden dynamic parameter. On the other hand, these compilers get to choose an ABI; last I looked into it, SpiderMonkey used the equivalent of preserve_none , which would allow it to allocate more registers to function parameters. But it doesn’t: you only get 6 register arguments on x86-64, and only 8 on AArch64. Something to fix, perhaps, in the Wasm engines, but also something to keep in mind when making tail-calling virtual machines: there are only so many registers available for VM state.

    the value of time

    Well friends, you know us compiler types: we walk a line between collegial and catty. In that regard, I won’t deny that I was delighted when I saw the Wastrel numbers coming in better than Wasmtime! Of course, most of the credit goes to GCC; Wastrel is a relatively small wrapper on top.

    But my message is not about the relative worth of different Wasm implementations. Rather, it is that performance oracles are a public good : a fast implementation of a particular algorithm is of use to everyone who uses that algorithm, whether they use that implementation or not.

    This happens in two ways. Firstly, faster implementations advance the state of the art, and through competition-driven convergence will in time result in better performance for all implementations. Someone in Google will see these benchmarks, turn them into an OKR, and golf their way to a faster web and also hopefully a bonus.

    Secondly, there is a dialectic between the state of the art and our collective imagination of what is possible, and advancing one will eventually ratchet the other forward. We can forgive the conclusion that “patterns which generate good assembly don’t map well to the WASM stack machine” as long as Wasm implementations fall short; but having shown that good performance is possible, our toolkit of applicable patterns in source languages also expands to new horizons.

    Well, that is all for today. Until next time, happy hacking!

    • Pl chevron_right

      Jussi Pakkanen: Sorting performance rabbit hole

      news.movim.eu / PlanetGnome • 6 April 2026 • 2 minutes

    In an earlier blog post we found out that Pystd's simple sorting algorithm implementations were 5-10% slower than their stdlibc++ counterparts. The obvious follow up nerd snipe is to ask "can we make the Pystd implementation faster than stdlibc++?"

    For all tests below the data set used was 10 million consecutive 64 bit integers shuffled in a random order. The order was the same for all algorithms.

    Stable sort

    It turns out that the answer for stable sorting is "yes, surprisingly easily". I made a few obvious tweaks (whose details I don't even remember any more) and got the runtime down to 0.86 seconds. This is approximately 5% faster than std::stable_sort . Done. Onwards to unstable sort.

    Unstable sort

    This one was not, as they say, a picnic. I suspect that stdlib developers have spent more time optimizing std::sort than std::stable_sort simply because it is used a lot more.

    After all the improvements I could think of were done, Pystd's implementation was consistently 5-10% percent slower. At this point I started cheating and examined how stdlibc++'s implementation worked to see if there are any optimization ideas to steal. Indeed there were, but they did not help.

    Pystd's insertion sort moves elements by pairwise swaps. Stdlibc++ does it by moving the last item to a temporary, shifting the array elements onwards and then moving the stored item to its final location. I implemented that. It made things slower.

    Stdlibc++'s moves use memmove instead of copying (at least according to code comments).  I implemented that. It made things slower.

    Then I implemented shell sort to see if it made things faster. It didn't. It made them a lot slower. So did radix sort .

    Then I reworked the way pivot selection is done and realized that if you do it in a specific way, some elements move to their correct partitions as a side effect of median selection. I implemented that and it did not make things faster. It did not make them slower, either, but the end result should be more resistant against bad pivot selection so I left it in.

    At some point the implementation grew a bug which only appeared with very large data sets. For debugging purposes I reduce the limit where introsort switches from qsort to insertion sort from 16 to 8. I got the bug fixed but the change made sorting a lot slower. As it should.

    But this raises a question, namely would increasing the limit from 16 to 32 make things faster? It turns out that it did. A lot. Out of all perf improvements I implemented, this was the one that yielded the biggest improvement by a fairly wide margin. Going to 64 elements made it even faster, but that made other algorithms using insertion sort slower, so 32 it is. For now at least.

    After a few final tweaks I managed to finally beat stdlibc++. By how much you ask? Pystd's best observed time was 0.754 seconds while stdlibc++'s was 0.755 seconds. And it happened only once. But that's enough for me.

    • Pl chevron_right

      This Week in GNOME: #243 Delayed Trains

      news.movim.eu / PlanetGnome • 3 April 2026 • 8 minutes

    Update on what happened across the GNOME project in the week from March 27 to April 03.

    GNOME Core Apps and Libraries

    Maps

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

    mlundblad says

    Now Maps shows delays for public transit journeys (when there’s a realtime GTFS-RT feed available for the affected journey)

    public-transit-delays.BxDJr5pj_Z1FLOS8.webp

    Glycin

    Sandboxed and extendable image loading and editing.

    Sophie (she/her) reports

    After four weeks of work, glycin now supports compiled-in loaders. The main benefit of this is that glycin should now work on other operating systems like FreeBSD, Windows, or macOS.

    Glycin uses Linux exclusive technologies to sandbox image operations. For this, the image processing is happening in a separate, isolated, process. It would be very hard to impossible to replicate this technology for other operating systems. Therefore, glycin now supports building loaders into it directly. This still provides a huge benefit compared to traditional image loaders, since almost all of the code is written in safe Rust. The feature of ‘builtin’ loaders can, in theory, be combined with ‘external’ loaders.

    The glycin crate now builds with external loaders for Linux, and automatically uses builtin loaders for all other operating systems. That means that libglycin should work on other operating systems as well. So far, the CI only contains builds cross compiled for x86_64-pc-windows-gnu and tested on Wine. Further testing, feedback, and fixes are very welcome.

    Image loaders that are written in C/C++ like for HEIF, AVIF, SVG, and JPEG XL, are currently not supported for being used without sandbox. Since AVIF and JPEG XL already have rust-based implementations, and rsvg might move away from libxml2 in the future, potentially allowing for safe builtin loaders for these formats in the future.

    If you want, you can support my work financially on various platforms .

    GNOME Circle Apps and Libraries

    Pika Backup

    Keep your data safe.

    Sophie (she/her) reports

    On March 31, we observed Trans Day of Visibility 🏳️‍⚧️, World Backup Day, and fittingly, the release of Pika Backup 0.8 . After two years of work, this release not only brings many small improvements , but also a rework of the code base that dates back to 2018. This will greatly help to keep Pika Backup stable and maintainable for another eight years.

    You can support the development on Open Collective or support my work via various other platforms .

    Big thanks to everyone who makes Pika Backup possible, especially BorgBackup , our donors, and translators.

    pika-backup.Lg0f3L1V_Z19xA4K.webp

    Third Party Projects

    Antonio Zugaldia announces

    Speed of Sound, voice typing for the Linux desktop, is now available on Flathub!

    Main features:

    • Offline, on-device transcription using Whisper. No data leaves your machine.
    • Multiple activation options: click the in-app button or use a global keyboard shortcut.
    • Types the result directly into any focused application using Portals for wide desktop support (X11, Wayland).
    • Multi-language support with switchable primary and secondary languages on the fly.
    • Works out of the box with the built-in Whisper Tiny model. Download additional models from within the app to improve accuracy.
    • Optional text polishing with LLMs, with support for a custom context and vocabulary.
    • Supports self-hosted services like vLLM, Ollama, and llama.cpp (cloud services supported but not required).
    • Built with the fantastic Java GI bindings, come hang out on #java-gi:matrix.org .

    Get it from https://flathub.org/en/apps/io.speedofsound.SpeedOfSound . Learn more on https://www.speedofsound.io .

    demo-light.CceIw5Qt_28oUCv.webp

    Ronnie Nissan reports

    This week I released Embellish v1.0,0.This is a major rewrite of the app from Gjs to Vala, using all the experience I gain from making GTK apps for the past few years. The app now uses view models for the fonts ListBox and a GridView for the Icons. Not only is the app more performant now, the code is much nicer and easier to maintain and hack.

    You can get Embellish from Flatpak

    Or you can contribute to it’s Development/Translation on Github

    embellish-v1.0.0-icons-page.Cyp8_cns_Z25gbLa.webp

    embellish-v1.0.0-preview-dialog.CTu5TX7P_w1Nj0.webp

    Daniel Wood reports

    Design, 2D computer aided design (CAD) for GNOME sees a new release, highlights include:

    • Polyline Trim (TR)
    • Polyline Extend (EX)
    • Chamfer Command (CHA)
    • Fillet Command (F)
    • Inferred direction for Arc Command (A)
    • Diameter input for Circle Command (C)
    • Close option for Line Command (L)
    • Close and Undo options for Polyline Command (PL)
    • Multiple copies with Copy Command (CO)
    • Show angle in Distance Command (DI)
    • Performance improvements when panning
    • Nested elements with Hatch Command (H)
    • Consistent Toast message format
    • Plus many fixes!

    Design is available from Flathub:

    https://flathub.org/apps/details/io.github.dubstar_04.design

    drawing.B8ObgpVr_lqAxg.webp

    Cleo Menezes Jr. reports

    Serigy has reached version 2, evolving into a focused, minimal clipboard manager. The release brings substantial improvements across functionality, performance, and user experience.

    The new version introduces automatic expiration of old clipboard items, incognito mode for privacy, and a grid view that brings clarity to your slots. Advanced features are now accessible through context menus and tooltips, while global shortcuts let you summon Serigy instantly from anywhere.

    Several bug fixes have improved stability and reliability, and the UI is significantly more responsive. The application now persists window size across sessions, and Wayland clipboard detection has been improved.

    Serigy 2 also refines its design. The app now supports Brazilian Portuguese, Russian, and Spanish (Chile).

    Get it on Flathub Follow the development

    serigy.mzQ6JWYu_Z38cfs.webp

    Wildcard

    Test your regular expressions.

    says

    Wildcard 0.3.5 released, bringing matching of regex groups, sidebar now shows overall match and group information, and new quick reference dialog showing common regular expression use cases! You can download the latest release from Flathub!

    wildcard-0.3.5.B3uIty9O_18spUb.webp

    Files

    Providing a simple and integrated way of managing your files and browsing your file system.

    Romain says

    I have created a Nautilus extension that adds an “Open in” context menu for installed IDEs , allowing to easily open directories and files in them.

    It works with any IDE marked as such in their desktop entry. That includes IDEs in development containers such as Toolbx if you create a desktop file for it on the host system.

    To install, download the latest version and follow the instructions in the README file.

    Metadata Cleaner

    View and clean metadata in files.

    GeopJr 🏳️‍⚧️🏳️‍🌈 says

    Metadata Cleaner is back, now with more adaptive layouts, bug fixes and features!

    Grab the latest release from Flathub !

    metadatacleaner.NvR--Orx_GMvMN.webp

    Fractal

    Matrix messaging app for GNOME written in Rust.

    Kévin Commaille reports

    Things have been fairly quiet since the Jason AI takeover , but here comes Fractal 14.beta.

    • Sending files & location is properly disabled while editing/replying, as it doesn’t work anyway.
    • Call rooms are identified with a camera icon in the sidebar and show a banner to warn that other users might not read messages in these rooms.
    • While we still support signing in via SSO, we have dropped support for identity providers, to simplify our code and a have a closer experience to signing in with OAuth 2.0.
    • Map markers now use a darker variant of the accent color to have a better contrast with the map underneath.
    • Many small behind the scenes changes, mostly through dependency updates, and we have removed a few of them. Small improvements to the technical docs as well.

    As usual, this release includes other improvements, fixes and new translations thanks to all our contributors, and our upstream projects.

    It is available to install via Flathub Beta, see the instructions in our README .

    As the version implies, there might be a slight risk of regressions, but it should be mostly stable. If all goes well the next step is the release candidate!

    We are very excited to see several new contributors opening MRs lately to take care of their pet peeves with Fractal, which will benefit everyone in the end. If you have a little bit of time on your hands, you can try to join them by fixing one of our newcomers issues .

    Flood It

    Flood the board

    tfuxu reports

    Flood It 2.0 has been released! It now comes with a simple game explanation dialog, the ability to replay recently played board, full translation support, and a Ctrl+1…6 keyboard shortcut for color buttons.

    It also contains many under-the-hood improvements, like the transition from Gotk4 to Puregotk, a runtime update to GNOME 50, custom seed support, and much more.

    Check it out on Flathub !

    floodit_2.0_game_rules.DkS1U6q0_2tFl7y.webp

    floodit_2.0_play_again.CDSKQkJ3_c77v1.webp

    Bouncer

    Bouncer is an application to help you choose the correct firewall zone for wireless connections.

    justinrdonnelly announces

    Bouncer 50 was released this week, using the GNOME 50 runtime. It has bug fixes related to NetworkManager restarts, and autostart status. It also includes translations for Italian and Polish. Check it out on Flathub !

    GNOME Websites

    Guillaume Bernard says

    GNOME Damned Lies has seen a few UX improvements! For the release of GNOME 50, I added a specific tag for Damned Lies to track the changes and link them to existing GNOME cycles. You can see all the changes I already spoke about like merge request support, background refresh of statistics, etc. (see: https://gitlab.gnome.org/Infrastructure/damned-lies/-/releases/gnome_50 ). After that, I am working towards GNOME 50.1. Why follow the GNOME release calendar? Because it provides pace, and pace is important while developing. After more than 3 years fixing technical debt and refactoring, upgrading existing code, you can see the pace of changes has increased a lot. At the beginning of GNOME 50, we had more than 120 open issues in the Damned Lies tracker; it’s down to 76 at the time of writing these lines. So what’s new this week? I worked a lot on long-standing UX-related issues and can proudly announce a few changes in Damned Lies:

    • Better consistency in many strings (‘Release’ vs ‘Release Set’, past tense in action history that previously used the infinitive form).
    • Administrators now see the modules maintained in the site backend.
    • String freeze notifications now expose the affected versions and are far more stable when detecting string freeze breaks.
    • You now have anchors in your team pages for each language your team is working on.
    • i18n coordinators are now identified by a mini badge in their profile, helping any user to reach them more easily.
    • i18n coordinators can take action in any workflow without being a member of the team they act on.
    • Users can remove their own accounts.

    That’s all for this week! 😃

    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!