21 Aug 2025
planet.freedesktop.org
Sebastian Wick: Testing with Portals
At the Linux App Summit (LAS) in Albania three months ago, I gave a talk about testing in the xdg-desktop-portal project. There is a recording of the presentation, and the slides are available as well.
To give a quick summary of the work I did:
- Revamped the CI
- Reworked and improved the pytest based integration test harness
- Added integration tests for new portals
- Ported over all the existing GLib/C based integration tests
- Support ASAN for detecting memory leaks in the tests
- Made tests pretend to be either a host, Flatpak or Snap app
The hope I had is that this will result in:
- Fewer regressions
- Tests for new features and bug fixes
- More confidence in refactoring
- More activity in the project
While it's hard to get definite data on those points, at least some of it seems to have become reality. I have seen an increase in activity (there are other factors to this for sure), and a lot of PRs already come with tests without me even having to ask for it. Canonical is involved again, taking care of the Snap side of things. So far it seems like we didn't introduce any new regressions, but this usually shows after a new release. The experience of refactoring portals also became a lot better because there is a baseline level of confidence when the tests pass, as well as the possibility to easily bisect issues. Overall I'm already quite happy with the results.
Two weeks ago, Georges merged the last piece of what I talked about in the LAS presentation, so we're finally testing the code paths that are specific to host, Flatpak and Snap applications! I also continued a bit with improving the tests, and now they can be run with Valgrind, which is super slow and that's why we're not doing it in the CI, but it tends to find memory leaks which ASAN does not. With the existing tests, it found 9 small memory leaks.
If you want to improve the Flatpak story, come and contribute to xdg-desktop-portal. It's now easier than ever!
21 Aug 2025 9:00pm GMT
20 Aug 2025
planet.freedesktop.org
Peter Hutterer: Why is my device a touchpad and a mouse and a keyboard?
If you have spent any time around HID devices under Linux (for example if you are an avid mouse, touchpad or keyboard user) then you may have noticed that your single physical device actually shows up as multiple device nodes (for free! and nothing happens for free these days!). If you haven't noticed this, run libinput record
and you may be part of the lucky roughly 50% who get free extra event nodes.
The pattern is always the same. Assuming you have a device named FooBar ExceptionalDog 2000 AI
[1] what you will see are multiple devices
/dev/input/event0: FooBar ExceptionalDog 2000 AI Mouse /dev/input/event1: FooBar ExceptionalDog 2000 AI Keybard /dev/input/event2: FooBar ExceptionalDog 2000 AI Consumer Control
The Mouse/Keyboard/Consumer Control/... suffixes are a quirk of the kernel's HID implementation which splits out a device based on the Application Collection. [2]
A HID report descriptor may use collections to group things together. A "Physical Collection" indicates "these things are (on) the same physical thingy". A "Logical Collection" indicates "these things belong together". And you can of course nest these things near-indefinitely so e.g. a logical collection inside a physical collection is a common thing.
An "Application Collection" is a high-level abstractions to group something together so it can be detected by software. The "something" is defined by the HID usage for this collection. For example, you'll never guess what this device might be based on the hid-recorder output:
# 0x05, 0x01, // Usage Page (Generic Desktop) 0 # 0x09, 0x06, // Usage (Keyboard) 2 # 0xa1, 0x01, // Collection (Application) 4 ... # 0xc0, // End Collection 74
Yep, it's a keyboard. Pop the champagne[3] and hooray, you deserve it.
The kernel, ever eager to help, takes top-level application collections (i.e. those not inside another collection) and applies a usage-specific suffix to the device. For the above Generic Desktop/Keyboard usage you get "Keyboard", the other ones currently supported are "Keypad" and "Mouse" as well as the slightly more niche "System Control", "Consumer Control" and "Wireless Radio Control" and "System Multi Axis". In the Digitizer usage page we have "Stylus", "Pen", "Touchscreen" and "Touchpad". Any other Application Collection is currently unsuffixed (though see [2] again, e.g. the hid-uclogic driver uses "Touch Strip" and other suffixes).
This suffix is necessary because the kernel also splits out the data sent within each collection as separate evdev event node. Since HID is (mostly) hidden from userspace this makes it much easier for userspace to identify different devices because you can look at a event node and say "well, it has buttons and x/y, so must be a mouse" (this is exactly what udev does when applying the various ID_INPUT
properties, with varying levels of success).
The side effect of this however is that your device may show up as multiple devices and most of those extra devices will never send events. Sometimes that is due to the device supporting multiple modes (e.g. a touchpad may by default emulate a mouse for backwards compatibility but once the kernel toggles it to touchpad mode the mouse feature is mute). Sometimes it's just laziness when vendors re-use the same firmware and leave unused bits in place.
It's largely a cosmetic problem only, e.g. libinput treats every event node as individual device and if there is a device that never sends events it won't affect the other event nodes. It can cause user confusion though: "why does my laptop say there's a mouse?" and in some cases it can cause functional degradation - the two I can immediately recall are udev detecting the mouse node of a touchpad as pointing stick (because i2c mice aren't a thing), hence the pointing stick configuration may show up in unexpected places. And fake mouse devices prevent features like "disable touchpad if a mouse is plugged in" from working correctly. At the moment we don't have a good solution for detecting these fake devices - short of shipping giant databases with product-specific entries we cannot easily detect which device is fake. After all, a Keyboard node on a gaming mouse may only send events if the user configured the firmware to send keyboard events, and the same is true for a Mouse node on a gaming keyboard.
So for now, the only solution to those is a per-user udev rule to ignore a device. If we ever figure out a better fix, expect to find a gloating blog post in this very space.
[1] input device naming is typically bonkers, so I'm just sticking with precedence here
[2] if there's a custom kernel driver this may not apply and there are quirks to change this so this isn't true for all devices
[3] or sparkling wine, let's not be regionist here
20 Aug 2025 1:12am GMT
16 Aug 2025
planet.freedesktop.org
Simon Ser: Status update, August 2025
Hi!
This month I've spent quite some time working on vali, a C library and code generator for the Varlink IPC protocol. It was formerly named "varlinkgen", but the new name is shorter and more accurate (the library can be used without the code generator). I've fixed a bunch of bugs, updated the service implementation to use non-blocking IO, added some tests and support for continued calls (which are Varlink's way to emit events from a service). I've also written a patch to port the kanshi output configuration tool to vali.
Speaking of kanshi, I've released version 1.8. A new kanshictl status
command shows the current mode, and wildcard patterns are now supported to match outputs. I want to finish up relative output positioning for the next release, but some tricky usability issues need to be sorted out first.
Support for toplevel capture in xdg-desktop-portal-wlr has been merged. This was the last missing piece to be able to share an individual window from Web browsers. libdisplay-info v0.3 has been released with support for many new CTA data blocks and groundwork for DisplayID v2. José Expósito has sent libdrm and drm_info patches to add user-space support for the special "faux" bus used in cases where a device isn't backed by hardware (up until now, the platform bus was abused).
The Goguma mobile IRC client now displays a small bubble when someone else mentions you, making these easier to spot at a glance:

Jean THOMAS has added a new option to choose between the in-app Web view and an external browser when opening links. Hubert Hirtz has tweaked the login forms to play better with the autofill feature some password managers provide.
I've released go-imap v2 beta 6, with support for SPECIAL-USE
and CHILDREN
thanks to Dejan Štrbac and legacy RECENT
thanks to fox.cpp. I'd like to eventually ship v2, but there are still some rough edges that I'd like to smooth out. I now realize it's been more than 2 years since the first v2 alpha release, maybe I should listen a bit more to my bio teacher who used to repeat "perfect is the enemy of good".
Anyways, that's all for now, see you next month!
16 Aug 2025 10:00pm GMT
15 Aug 2025
planet.freedesktop.org
Sebastian Wick: Display Next Hackfest 2025
A few weeks ago, a bunch of display driver and compositor developers met once again for the third iteration of the Display Next Hackfest. The tradition was started by Red Hat, followed by Igalia (thanks Melissa), and now AMD (thanks Harry). We met in the AMD offices in Markham, Ontario, Canada; and online, to discuss issues, present things we worked on, figure out future steps on a bunch of topics related to displays, GPUs, and compositors.

The Display Next Hackfest in the AMD Markham offices
It was really nice meeting everyone again, and also seeing some new faces! Notably, Charles Poynton who "decided that HD should have 1080 image rows, and square pixels", and Keith Lee who works for AMD and designed their color pipeline, joined us this year. This turned out to be invaluable. It was also great to see AMD not only organizing the event, but also showing genuine interest and support for what we are trying to achieve.
This year's edition is likely going to be the last dedicated Display Next Hackfest, but we're already plotting to somehow fuse it with XDC next year in some way.
If you're looking for a more detailed technical rundown of what we were doing there, you can read Xaver's, or Louis' blog posts, or our notes.
With all that being said, here is an incomplete list of things I found exciting:
- The biggest update of the Atomic KMS API (used to control displays) is about to get merged. The Color Pipeline API is something I came up with three years ago, and thanks to the tireless efforts of AMD, Intel and Igalia and others, this is about to become reality. Read Melissa's blog post for more details.
- As part of the work enabling displaying HDR content in Wayland compositors, we've been unhappy with the current HDR modes in displays, as they are essentially created for video playback and have lots of unpredictable behavior. To address this, myself and Xaver have since last year been lobbying for displays to allow the use of Source Based Tone Mapping (SBTM), and this year, it seems that what we have asked for have made it to the right people. Let's see!
- In a similar vein, on mobile devices we want to dynamically increase or decrease the HDR headroom, depending on what content applications want to show. This requires backlight changes to be somewhat atomic and having a mapping to luminance. The planned KMS backlight API will allow us to expose this, if the platform supports it. I worked a lot on backlight support in mutter this year so we can immediately start using this when it becomes available.
- Charles, Christopher, and I had a discussion about compositing HDR and SDR content, and specifically about how to adjust content that was mastered for a dark viewing environment that is being shown in a bright viewing environment, so that the perception is maintained. I believe that we now have a complete picture of how compositing should work, and I'm working on documenting this in the color-and-hdr repo.
- For Variable Refresh Rates (VRR) we want a new KMS API to set the minimum and maximum refresh cycle, where setting min=max gives us a fixed refresh rate without a mode set. To make use of VRR in more than the single-fullscreen-window case, we also agreed that a Wayland protocol letting clients communicate their preferred refresh rate would be a good idea.
Like always, lots of work ahead of us, but it's great to actually see the progress this year with the entire ecosystem having HDR support now.

Sampling local craft beers
See you all at XDC this year (or at least the one next year)!
15 Aug 2025 3:41pm GMT
11 Aug 2025
planet.freedesktop.org
Peter Hutterer: xkeyboard-config 2.45 has a new install location
This is a heads ups that if you install xkeyboard-config 2.45 (the package that provides the XKB data files), some manual interaction may be needed. Version 2.45 has changed the install location after over 20 years to be a) more correct and b) more flexible.
When you select a keyboard layout like "fr" or "de" (or any other ones really), what typically happens in the background is that an XKB parser (xkbcomp if you're on X, libxkbcommon if you're on Wayland) goes off and parses the data files provided by xkeyboard-config to populate the layouts. For historical reasons these data files have resided in /usr/share/X11/xkb
and that directory is hardcoded in more places than it should be (i.e. more than zero). As of xkeyboard-config 2.45 however, the data files are now installed in the much more sensible directory /usr/share/xkeyboard-config-2
with a matching xkeyboard-config-2.pc
for anyone who relies on the data files. The old location is symlinked to the new location so everything keeps working, people are happy, no hatemail needs to be written, etc. Good times.
The reason for this change is two-fold: moving it to a package-specific directory opens up the (admittedly mostly theoretical) use-case of some other package providing XKB data files. But even more so, it finally allows us to start versioning the data files and introduce new formats that may be backwards-incompatible for current parsers. This is not yet the case however, the current format in the new location is guaranteed to be the same as the format we've always had, it's really just a location change in preparation for future changes.
Now, from an upstream perspective this is not just hunky, it's also dory. Distributions however struggle a bit more with this change because of packaging format restrictions. RPM for example is quite unhappy with a directory being replaced by a symlink which means that Fedora and OpenSuSE have to resort to the .rpmmoved
hack. If you have ever used the custom layout and/or added other files to the XKB data files you will need to manually move those files from /usr/share/X11/xkb.rpmmoved/
to the new equivalent location. If you have never used that layout and/or modified local you can just delete /usr/share/X11/xkb.rpmmoved
. Of course, if you're on Wayland you shouldn't need to modify system directories anyway since you can do it in your $HOME.
Corresponding issues on what to do on Arch and Gentoo, I'm not immediately aware of other distributions's issues but if you search for them in your bugtracker you'll find them.
11 Aug 2025 1:44am GMT
08 Aug 2025
planet.freedesktop.org
Sebastian Wick: GNOME 49 Backlight Changes
One of the things I'm working on at Red Hat is HDR support. HDR is inherently linked to luminance (brightness, but ignoring human perception) which makes it an important parameter for us that we would like to be in control of.
One reason is rather stupid. Most external HDR displays refuse to let the user control the luminance in their on-screen-display (OSD) if the display is in HDR mode. Why? Good question. Read my previous blog post.
The other reason is that the amount of HDR headroom we have available is the result of the maximum luminance we can achieve versus the luminance that we use as the luminance a sheet of white paper has (reference white level). For power consumption reasons, we want to be able to dynamically change the available headroom, depending on how much headroom the content can make use of. If there is no HDR content on the screen, there is no need to crank up the backlight to give us more headroom, because the headroom will be unused.
To work around the first issue, mutter can change the signal it sends to the display, so that white is not a signal value of 1.0 but somewhere else between 0 and 1. This essentially emulates a backlight in software. The drawback is that we're not using a bunch of bits in the signal anymore and issues like banding might become more noticeable, but since we're using this only with 10 or 12 bits HDR signals, this isn't an issue in practice.
This has been implemented in GNOME 48 already, but it was an API that mutter exposed and Settings showed as "HDR Brightness".

"HDR Brightness" in GNOME Settings
The second issue requires us to be able to map the backlight value to luminance, and change the backlight atomically with an update to the screen. We could work towards adding those things to the existing sysfs backlight API but it turns out that there are a number of problems with it. Mapping the sysfs entry to a connected display is really hard (GNOME pretends that there is only one single internal display that can ever be controlled), and writing a value to the backlight requires root privileges or calling a logind dbus API. One internal panel can expose multiple backlights, the value of 0 can mean the display turns off or is just really dim.
So a decision was made to create a new API that will be part of KMS, the API that we use to control the displays.
The sysfs backlight has been controlled by gnome-settings-daemon and GNOME Shell called a dbus API when the screen brightness slider was moved.
To recap:
- There is a sysfs backlight API for basically one internal panel requires logind or a setuid helper executable
- gnome-settings-daemon controlled this single screen sysfs backlight
- Mutter has a "software backlight" feature
- KMS will get a new backlight API that needs to be controlled by mutter
Overall, this is quite messy, so I decided to clean this up.
Over the last year, I moved the sysfs backlight handling from gnome-settings-daemon into mutter, added logic to decide which backlight to use (sysfs or the "software backlight"), and made it generic so that any screen can have a backlight. This means mutter is the single source of truth for the backlight itself. The backlight itself gets its value from a number of sources. The user can configure the screen brightness in the quick settings menu and via keyboard shortcuts. Power saving features can kick in and dim the screen. Lastly, an Ambient Light Sensor (ALS) can take control over the screen brightness. To make things more interesting, a single "logical monitor" can have multiple hardware monitors which each can have a backlight. All of that logic is now neatly sitting in GNOME Shell which takes signals from gnome-settings-daemon about the ALS and dimming. I also changed the Quick Settings UI to make it possible to control the brightness on multiple screens, and removed the old "HDR Brightness" from Settings.
All of this means that we can now handle screen brightness on multiple monitors and when the new KMS backlight API makes it upstream, we can just plug it in, and start to dynamically create HDR headroom.
08 Aug 2025 3:26pm GMT
07 Aug 2025
planet.freedesktop.org
Peter Hutterer: libinput and Lua plugins (Part 2)
Part 2 is, perhaps suprisingly, a follow-up to libinput and lua-plugins (Part 1).
The moon has circled us a few times since that last post and some update is in order. First of all: all the internal work required for plugins was released as libinput 1.29 but that version does not have any user-configurable plugins yet. But cry you not my little jedi and/or sith lord in training, because support for plugins has now been merged and, barring any significant issues, will be in libinput 1.30, due somewhen around October or November. This year. 2025 that is.
Which means now is the best time to jump in and figure out if your favourite bug can be solved with a plugin. And if so, let us know and if not, then definitely let us know so we can figure out if the API needs changes. The API Documentation for Lua plugins is now online too and will auto-update as changes to it get merged. There have been a few minor changes to the API since the last post so please refer to the documentation for details. Notably, the version negotiation was re-done so both libinput and plugins can support select versions of the plugin API. This will allow us to iterate the API over time while designating some APIs as effectively LTS versions, minimising plugin breakages. Or so we hope.
What warrants a new post is that we merged a new feature for plugins, or rather, ahaha, a non-feature. Plugins now have an API accessible that allows them to disable certain internal features that are not publicly exposed, e.g. palm detection. The reason why libinput doesn't have a lot of configuration options have been explained previously (though we actually have quite a few options) but let me recap for this particular use-case: libinput doesn't have a config option for e.g. palm detection because we have several different palm detection heuristics and they depend on device capabilities. Very few people want no palm detection at all[1] so disabling it means you get a broken touchpad and we now get to add configuration options for every palm detection mechanism. And keep those supported forever because, well, workflows.
But plugins are different, they are designed to take over some functionality. So the Lua API has a EvdevDevice:disable_feature("touchpad-palm-detection")
function that takes a string with the feature's name (easier to make backwards/forwards compatible this way). This example will disable all palm detection within libinput and the plugin can implement said palm detection itself. At the time of writing, the following self-explanatory features can be disabled: "button-debouncing", "touchpad-hysteresis", "touchpad-jump-detection", "touchpad-palm-detection", "wheel-debouncing". This list is mostly based on "probably good enough" so as above - if there's something else then we can expose that too.
So hooray for fewer features and happy implementing!
[1] Something easily figured out by disabling palm detection or using a laptop where palm detection doesn't work thanks to device issues
07 Aug 2025 10:00am GMT
Peter Hutterer: libinput and Lua plugins
First of all, what's outlined here should be available in libinput 1.29 1.30 but I'm not 100% certain on all the details yet so any feedback (in the libinput issue tracker) would be appreciated. Right now this is all still sitting in the libinput!1192 merge request. I'd specifically like to see some feedback from people familiar with Lua APIs. With this out of the way:
Come libinput 1.29 1.30, libinput will support plugins written in Lua. These plugins sit logically between the kernel and libinput and allow modifying the evdev device and its events before libinput gets to see them.
The motivation for this are a few unfixable issues - issues we knew how to fix but we cannot actually implement and/or ship the fixes without breaking other devices. One example for this is the inverted Logitech MX Master 3S horizontal wheel. libinput ships quirks for the USB/Bluetooth connection but not for the Bolt receiver. Unlike the Unifying Receiver the Bolt receiver doesn't give the kernel sufficient information to know which device is currently connected. Which means our quirks could only apply to the Bolt receiver (and thus any mouse connected to it) - that's a rather bad idea though, we'd break every other mouse using the same receiver. Another example is an issue with worn out mouse buttons - on that device the behavior was predictable enough but any heuristics would catch a lot of legitimate buttons. That's fine when you know your mouse is slightly broken and at least it works again. But it's not something we can ship as a general solution. There are plenty more examples like that - custom pointer deceleration, different disable-while-typing, etc.
libinput has quirks but they are internal API and subject to change without notice at any time. They're very definitely not for configuring a device and the local quirk file libinput parses is merely to bridge over the time until libinput ships the (hopefully upstreamed) quirk.
So the obvious solution is: let the users fix it themselves. And this is where the plugins come in. They are not full access into libinput, they are closer to a udev-hid-bpf in userspace. Logically they sit between the kernel event devices and libinput: input events are read from the kernel device, passed to the plugins, then passed to libinput. A plugin can look at and modify devices (add/remove buttons for example) and look at and modify the event stream as it comes from the kernel device. For this libinput changed internally to now process something called an "evdev frame" which is a struct that contains all struct input_events up to the terminating SYN_REPORT. This is the logical grouping of events anyway but so far we didn't explicitly carry those around as such. Now we do and we can pass them through to the plugin(s) to be modified.
The aforementioned Logitech MX master plugin would look like this: it registers itself with a version number, then sets a callback for the "new-evdev-device" notification and (where the device matches) we connect that device's "evdev-frame" notification to our actual code:
libinput:register(1) -- register plugin version 1 libinput:connect("new-evdev-device", function (_, device) if device:vid() == 0x046D and device:pid() == 0xC548 then device:connect("evdev-frame", function (_, frame) for _, event in ipairs(frame.events) do if event.type == evdev.EV_REL and (event.code == evdev.REL_HWHEEL or event.code == evdev.REL_HWHEEL_HI_RES) then event.value = -event.value end end return frame end) end end)
This file can be dropped into /etc/libinput/plugins/10-mx-master.lua and will be loaded on context creation. I'm hoping the approach using named signals (similar to e.g. GObject) makes it easy to add different calls in future versions. Plugins also have access to a timer so you can filter events and re-send them at a later point in time. This is useful for implementing something like disable-while-typing based on certain conditions.
So why Lua? Because it's very easy to sandbox. I very explicitly did not want the plugins to be a side-channel to get into the internals of libinput - specifically no IO access to anything. This ruled out using C (or anything that's a .so file, really) because those would run a) in the address space of the compositor and b) be unrestricted in what they can do. Lua solves this easily. And, as a nice side-effect, it's also very easy to write plugins in.[1]
Whether plugins are loaded or not will depend on the compositor: an explicit call to set up the paths to load from and to actually load the plugins is required. No run-time plugin changes at this point either, they're loaded on libinput context creation and that's it. Otherwise, all the usual implementation details apply: files are sorted and if there are files with identical names the one from the highest-precedence directory will be used. Plugins that are buggy will be unloaded immediately.
If all this sounds interesting, please have a try and report back any APIs that are broken, or missing, or generally ideas of the good or bad persuation. Ideally before we ship it and the API is stable forever :)
[1] Benjamin Tissoires actually had a go at WASM plugins (via rust). But ... a lot of effort for rather small gains over Lua
07 Aug 2025 12:44am GMT
04 Aug 2025
planet.freedesktop.org
Peter Hutterer: unplug - a tool to test input devices via uinput
Yet another day, yet another need for testing a device I don't have. That's fine and that's why many years ago I wrote libinput record
and libinput replay
(more powerful successors to evemu and evtest). Alas, this time I had a dependency on multiple devices to be present in the system, in a specific order, sending specific events. And juggling this many terminal windows with libinput replay
open was annoying. So I decided it's worth the time fixing this once and for all (haha, lolz) and wrote unplug. The target market for this is niche, but if you're in the same situation, it'll be quite useful.
Pictures cause a thousand words to finally shut up and be quiet so here's the screenshot after running pip install unplug
[1]:
This shows the currently pre-packaged set of recordings that you get for free when you install unplug. For your use-case you can run libinput record
, save the output in a directory and then start unplug path/to/directory
. The navigation is as expected, hitting enter on the devices plugs them in, hitting enter on the selected sequence sends that event sequence through the previously plugged device.
Annotation of the recordings (which must end in .yml
to be found) can be done by adding a YAML unplug:
entry with a name
and optionally a multiline description
. If you have recordings that should be included in the default set, please file a merge request. Happy emulating!
[1] And allowing access to /dev/uinput. Details, schmetails...
04 Aug 2025 6:09am GMT
29 Jul 2025
planet.freedesktop.org
Christian Schaller: Artificial Intelligence and the Linux Community
I have wanted to write this blog post for quite some time, but been unsure about the exact angle of it. I think I found that angle now where I will root the post in a very tangible concrete example.
So the reason I wanted to write this was because I do feel there is a palpable skepticism and negativity towards AI in the Linux community, and I understand that there are societal implications that worry us all, like how deep fakes have the potential to upend a lot of things from news disbursement to court proceedings. Or how malign forces can use AI to drive narratives in social media etc., is if social media wasn't toxic enough as it is. But for open source developers like us in the Linux community there is also I think deep concerns about tooling that deeply incurs into something that close to the heart of our community, writing code and being skilled at writing code. I hear and share all those concerns, but at the same time having spent time the last weeks using Claude.ai I do feel it is not something we can afford not to engage with. So I know people have probably used a lot of different AI tools in the last year, some being more cute than useful others being somewhat useful and others being interesting improvements to your Google search for instance. I think I shared a lot of those impressions, but using Claude this last week has opened my eyes to what AI enginers are going to be capable of going forward.
So my initial test was writing a python application for internal use at Red Hat, basically connecting to a variety of sources and pulling data and putting together reports, typical management fare. How simple it was impressed me though, I think most of us having to deal with pulling data from a new source know how painful it can be, with issues ranging from missing, outdated or hard to parse API documentation. I think a lot of us also then spend a lot of time experimenting to figure out the right API calls to make in order to pull the data we need. Well Claude was able to give me python scripts that pulled that data right away, I still had to spend some time with it to fine tune the data being pulled and ensuring we pulled the right data, but I did it in a fraction of the time I would have spent figuring that stuff out on my own. The one data source Claude struggled with Fedora's Bohdi, well once I pointed it to the URL with the latest documentation for that it figured out that it would be better to use the bohdi client library to pull data and once it had that figured out it was clear sailing.
So coming of pretty impressed by that experience I wanted to understand if Claude would be able to put together something programmatically more complex, like a GTK+ application using Vulkan. [Note: should have checked the code better, but thanks to the people who pointed this out. I told the AI to use Vulkan, which it did, but not in the way I expected, I expected it to render the globe using Vulkan, but it instead decided to ensure GTK used its Vulkan backend, an important lesson in both prompt engineering and checking the code afterwards).]So I thought what would be a good example of such an application and I also figured it would be fun if I found something really old and asked Claude to help me bring it into the current age. So I suddenly remembered xtraceroute, which is an old application orginally written in GTK1 and OpenGL showing your traceroute on a 3d Globe.

Screenshot of the original Xtraceroute application
I went looking for it and found that while it had been updated to GTK2 since last I looked at it, it had not been touched in 20 years. So I thought, this is a great testcase. So I grabbed the code and fed it into Claude, asking Claude to give me a modern GTK4 version of this application using Vulkan. Ok so how did it go? Well it ended up being an iterative effort, with a lot of back and forth between myself and Claude. One nice feature Claude has is that you can upload screenshots of your application and Claude will use it to help you debug. Thanks to that I got a long list of screenshots showing how this application evolved over the course of the day I spent on it.

This screenshot shows Claudes first attempt of transforming the 20 year old xtraceroute application into a modern one using GTK4, Vulkan and also adding a Meson build system. My prompt to create this was feeding in the old code and asking Claude to come up with a GTK4 and Vulkan equivalent. As you can see the GTK4 UI is very simple, but ok as it is. The rendered globe leaves something to be desired though. I assume the old code had some 2d fall backcode, so Claude latched onto that and focused on trying to use the Cairo API to recreate this application, despite me telling it I wanted a Vulkan application. What what we ended up with was a 2d circle that I could spin around like a wheel of fortuen. The code did have some Vulkan stuff, but defaulted to the Cairo code.

Second attempt at updating this application Anyway, I feed the screenshot of my first version back into Claude and said that the image was not a globe, it was missing the texture and the interaction model was more like a wheel of fortune. As you can see the second attempt did not fare any better, in fact we went from circle to square. This was also the point where I realized that I hadn't uploaded the textures into Claude, so I had to tell it to load the earth.png from the local file repository.

Third attempt from Claude.Ok, so I feed my second screenshot back into Claude and pointed out that it was no globe, in fact it wasn't even a circle and the texture was still missing. With me pointing out it needed to load the earth.png file from disk it came back with the texture loading. Well, I really wanted it to be a globe, so I said thank you for loading the texture, now do it on a globe.

This is the output of the 4th attempt. As you can see, it did bring back a circle, but the texture was gone again. At this point I also decided I didn't want Claude to waste anymore time on the Cairo code, this was meant to be a proper 3d application. So I told Claude to drop all the Cairo code and instead focus on making a Vulkan application.

So now we finally had something that started looking like something, although it was still a circle, not a globe and it got that weird division of 4 thing on the globe. Anyway, I could see it using Vulkan now and it was loading the texture. So I was feeling like we where making some decent forward movement. So I wrote a longer prompt describing the globe I wanted and how I wanted to interact with it and this time Claude did come back with Vulkan code that rendered this as a globe, thus I didn't end up screenshoting it unfortunately.

So with the working globe now in place, I wanted to bring in the day/night cycle from the original application. So I asked Claude to load the night texture and use it as an overlay to get that day/night effect. I also asked it to calculate the position of the sun to earth at the current time, so that it could overlay the texture in the right location. As you can see Claude did a decent job of it, although the colors was broken.

So I kept fighting with the color for a bit, Claude could see it was rendering it brown, but could not initally figure out why. I could tell the code was doing things mostly right so I also asked it to look at some other things, like I realized that when I tried to spin the globe it just twisted the texture. We got that fixed and also I got Claude to create some tests scripts that helped us figure out that the color issue was a RGB vs BRG issue, so as soon as we understood that then Claude was able to fix the code to render colors correctly. I also had a few iterations trying to get the scaling and mouse interaction behaving correctly.

So at this point I had probably worked on this for 4-5 hours, the globe was rendering nicely and I could interact with it using the mouse. Next step was adding the traceroute lines back. By default Claude had just put in code to render some small dots on the hop points, not draw the lines. Also the old method for getting the geocoordinates, but I asked Claude to help me find some current services which it did and once I picked one it on first try gave me code that was able to request the geolocation of the ip addresses it got back. To polish it up I also asked Claude to make sure we drew the lines following the globes curvature instead of just drawing straight lines.

Final version of the updated Xtraceroute application. It mostly works now, but I did realize why I always thought this was a fun idea, but less interesting in practice, you often don't get very good traceroutes back, probably due to websites being cached or hosted globally. But I felt that I had proven that with a days work Claude was able to help me bring this old GTK application into the modern world.
Conclusions
So I am not going to argue that Xtraceroute is an important application that deserved to be saved, in fact while I feel the current version works and proves my point I also lost motivation to try to polish it up due to the limitations of tracerouting, but the code is available for anyone who finds it worthwhile.
But this wasn't really about Xtraceroute, what I wanted to show here is how someone lacking C and Vulkan development skills can actually use a tool like Claude to put together a working application even one using more advanced stuff like Vulkan, which I know many more than me would feel daunting. I also found Claude really good at producing documentation and architecture documents for your application. It was also able to give me a working Meson build system and create all the desktop integration files for me, like the .desktop file, the metainfo file and so on. For the icons I ended up using Gemini as Claude do not do image generation at this point, although it was able to take a png file and create a SVG version of it (although not a perfect likeness to the original png).
Another thing I want to say is that the way I think about this, it is not that it makes coding skills less valuable, AIs can do amazing things, but you need to keep a close eye on them to ensure the code they create actually do what you want and that it does it in a sensible manner. For instance in my reporting application I wanted to embed a pdf file and Claude initial thought was to bring in webkit to do the rendering. That would have worked, but would have added a very big and complex dependency to my application, so I had to tell it that it could just use libpoppler to do it, something Claude agreed was a much better solution. The bigger the codebase the harder it also becomes for the AI to deal with it, but I think it hose circumstances what you can do is use the AI to give you sample code for the functionality you want in the programming language you want and then you can just work on incorporating that into your big application.
The other part here if course in terms of open source is how should contributors and projects deal with this? I know there are projects where AI generated CVEs or patches are drowning them and that helps nobody. But I think if we see AI as a developers tool and that the developer using the tool is responsible for the code generated, then I think that mindset can help us navigate this. So if you used an AI tool to create a patch for your favourite project, it is your responsibility to verify that patch before sending it in, and with that I don't mean just verifying the functionality it provides, but that the code is clean and readable and following the coding standards of said upstream project. Maintainers on the other hand can use AI to help them review and evaluate patches quicker and thus this can be helpful on both sides of the equation. I also found Claude and other AI tools like Gemini pretty good at generating test cases for the code they make, so this is another area where open source patch contributions can improve, by improving test coverage for the code.
I do also believe there are many areas where projects can greatly benefit from AI, for instance in the GNOME project a constant challenge for extension developers have been keeping their extensions up-to-date, well I do believe a tool like Claude or Gemini should be able to update GNOME Shell extensions quite easily. So maybe having a service which tries to provide a patch each time there is a GNOME Shell update might be a great help there. At the same time having a AI take a look at updated extensions and giving an first review of the update might help reduce the load on people doing code reviews on extensions and help flag problematic extensions.
I know for a lot of cases and situations uploading your code to a webservice like Claude, Gemini or Copilot is not something you want or can do. I know privacy is a big concern for many people in the community. My team at Red Hat has been working on a code assistant tool using the IBM Granite model, called Granite.code. What makes Granite different is that it relies on having the model run locally on your own system, so you don't send your code or data of somewhere else. This of course have great advantages in terms of improving privacy and security, but it has challenges too. The top end AI models out there at the moment, of which Claude is probably the best at the time of writing this blog post, are running on hardware with vast resources in terms of computing power and memory available. Most of us do not have those kind of capabilities available at home, so the model size and performance will be significantly lower. So at the moment if you are looking for a great open source tool to use with VS Code to do things like code completion I recommend giving Granite.code a look. If you on the other hand want to do something like I have described here you need to use something like Claude, Gemini or ChatGPT. I do recommend Claude, not just because I believe them to be the best at it at the moment, but they also are a company trying to hold themselves to high ethical standards. Over time we hope to work with IBM and others in the community to improve local models, and I am also sure local hardware will keep improving, so over time the experience you can get with a local model on your laptop at least has less of a gap than what it does today compared to the big cloud hosted models. There is also the middle of the road option that will become increasingly viable, where you have a powerful server in your home or at your workplace that can at least host a midsize model, and then you connect to that on your LAN. I know IBM is looking at that model for the next iteration of Granite models where you can choose from a wide variety of sizes, some small enough to be run on a laptop, others of a size where a strong workstation or small server can run them or of course the biggest models for people able to invest in top of the line hardware to run their AI.
Also the AI space is moving blazingly fast, if you are reading this 6 Months from now I am sure the capabilities of online and local models will have changed drastically already.
So to all my friends in the Linux community I ask you to take a look at AI and what it can do and then lets work together on improving it, not just in terms of capabilities, but trying to figure out things like societal challenges around it and sustainability concerns I also know a lot of us got.
Whats next for this code
As I mentioned I while I felt I got it to a point where I proved to myself it worked, I am not planning on working anymore on it. But I did make a cute little application for internal use that shows a spinning globe with all global Red Hat offices showing up as little red lights and where it pulls Red Hat news at the bottom. Not super useful either, but I was able to use Claude to refactor the globe rendering code from xtraceroute into this in just a few hours.

Red Hat Offices Globe and news.
29 Jul 2025 4:24pm GMT
28 Jul 2025
planet.freedesktop.org
Tomeu Vizoso: Rockchip NPU update 6: We are in mainline!
The kernel portion of the Linux driver for the Rockchip NPUs has been merged into the maintainer tree, and will be sent in the next pull request to Linus. The userspace portion of the driver has just been merged as well, in the main Mesa repository.
This means that in the next few weeks the two components of the Rocket driver will be in official releases of the Linux and Mesa projects, and Linux distributions will start to pick them up and package. Once that happens, we will have seamless accelerated inference on one more category of hardware.
It has been a bit over a year since I started working on the driver, though the actual feature implementation took just over two months of that. The rest of the time was spent waiting for reviews and reacting to excellent feedback from many contributors to the Linux kernel. The driver is now much better because of that frank feedback.
What I see in the near future for this driver is support for other Rockchip SoCs and some performance work, to match that of the proprietary driver. But of course, with it being open source, contributors can just start hacking on it and sending patches over for review and merging.
I'm now working on further improvements to the Etnaviv driver for the Vivante NPUs, and have started work with Arm engineers on a new driver for their Ethos line of NPUs.
So stay tuned for more news on accelerated inference on the edge in mainline Linux!
28 Jul 2025 7:02am GMT
27 Jul 2025
planet.freedesktop.org
Bastien Nocera: Digitising CDs (aka using your phone as an image scanner)
I recently found, under the rain, next to a book swap box, a pile of 90's "software magazines" which I spent my evening cleaning, drying, and sorting in the days afterwards.
Magazine cover CDs with nary a magazine
Those magazines are a peculiar thing in France, using the mechanism of "Commission paritaire des publications et des agences de presse" or "Commission paritaire" for short. This structure exists to assess whether a magazine can benefit from state subsidies for the written press (whether on paper at the time, and also the internet nowadays), which include a reduced VAT charge (2.1% instead of 20%), reduced postal rates, and tax exemptions.
In the 90s, this was used by Diamond Editions[1] (a publisher related to tech shop Pearl, which French and German computer enthusiasts probably know) to publish magazines with just enough original text to qualify for those subsidies, bundled with the really interesting part, a piece of software on CD.
If you were to visit a French newsagent nowadays, you would be able to find other examples of this: magazines bundled with music CDs, DVDs or Blu-rays, or even toys or collectibles. Some publishers (including the infamous and now shuttered Éditions Atlas) will even get you a cheap kickstart to a new collection, with the first few issues (and collectibles) available at very interesting prices of a couple of euros, before making that "magazine" subscription-only, with each issue being increasingly more expensive (article from a consumer protection association).
Other publishers have followed suite.
I guess you can only imagine how much your scale model would end up costing with that business model (50 eurocent for the first part, 4.99€ for the second), although I would expect them to have given up the idea of being categorised as "written press".
To go back to Diamond Editions, this meant the eventual birth of 3 magazines: Presqu'Offert, BestSellerGames and StratéJ. I remember me or my dad buying a few of those, an older but legit and complete version of ClarisWorks, CorelDraw or a talkie version of a LucasArt point'n'click was certainly a more interesting proposition than a cut-down warez version full of viruses when budget was tight.
3 of the magazines I managed to rescue from the rain
You might also be interested in the UK "covertape wars".
Don't stress the technique
This brings us back to today and while the magazines are still waiting for scanning, I tried to get a wee bit organised and digitising the CDs.
Some of them will have printing that covers the whole of the CD, a fair few use the foil/aluminium backing of the CD as a blank surface, which will give you pretty bad results when scanning them with a flatbed scanner: the light source keeps moving with the sensor, and what you'll be scanning is the sensor's reflection on the CD.
My workaround for this is to use a digital camera (my phone's 24MP camera), with a white foam board behind it, so the blank parts appear more light grey. Of course, this means that you need to take the picture from an angle, and that the CD will appear as an oval instead of perfectly circular.
I tried for a while to use GIMP perspective tools, and "Multimedia" Mike Melanson's MobyCAIRO rotation and cropping tool. In the end, I settled on Darktable, which allowed me to do 4-point perspective deskewing, I just had to have those reference points.
So I came up with a simple "deskew" template, which you can print yourself, although you could probably achieve similar results with grid paper.
After opening your photo with Darktable, and selecting the "darkroom" tab, go to the "rotate and perspective tool", select the "manually defined rectangle" structure, and adjust the rectangle to match the centers of the 4 deskewing targets. Then click on "horizontal/vertical fit". This will give you a squished CD, don't worry, and select the "specific" lens model and voilà.
Tools at the ready
Targets acquired
You can now export the processed image (I usually use PNG to avoid data loss at each step), open things up in GIMP and use the ellipse selection tool to remove the background (don't forget the center hole), the rotate tool to make the writing straight, and the crop tool to crop it to size.
And we're done!
The result of this example is available on Archive.org, with the rest of my uploads being made available on Archive.org and Abandonware-Magazines for those 90s magazines and their accompanying CDs.
[1]: Full disclosure, I wrote a couple of articles for Linux Pratique and Linux Magazine France in the early 2000s, that were edited by that same company.
27 Jul 2025 7:39pm GMT
25 Jul 2025
planet.freedesktop.org
Hari Rana: GNOME Calendar: A New Era of Accessibility Achieved in 90 Days
Please consider supporting my effort in making GNOME apps accessible for everybody. Thanks!
Introduction
There is no calendaring app that I love more than GNOME Calendar. The design is slick, it works extremely well, it is touchpad friendly, and best of all, the community around it is just full of wonderful developers, designers, and contributors worth collaborating with, especially with the recent community growth and engagement over the past few years. Georges Stavracas and Jeff Fortin Tam are some of the best maintainers I have ever worked with. I cannot express how thankful I am of Jeff's underappreciated superhuman capabilities to voluntarily coordinate huge initiatives and issue trackers.
One of Jeff's many initiatives is gnome-calendar#1036: the accessibility initiative, which is a big and detailed list of issues related to accessibility. In my opinion, GNOME Calendar's biggest problem was the lack of accessibility support, which made the app completely unusable for people exclusively using a keyboard, or people relying on assistive technologies.
This article will explain in details about the fundamental issues that held back accessibility in GNOME Calendar since the very beginning of its existence (12 years at a minimum), the progress we have made with accessibility as well as our thought process in achieving it, and the now and future of accessibility in GNOME Calendar.
Calendaring Complications
On a desktop or tablet form factor, GNOME Calendar has a month view and a week view, both of which are a grid comprising of cells representing a time frame.
In the month view, each row is a week, and each cell is a day.

In the week view, the time frame within cells varies on the zooming level.

There are mainly two reasons that made GNOME Calendar inaccessible: firstly, GTK's accessibility tree does not cover the logically and structurally complicated workflow and design that is a typical calendaring app; and secondly, the significant negative implications of accessibility due to reducing as much overhead as possible.
Accessibility Trees Are Insufficient for Calendaring Apps
GTK's accessibility tree, or rather any accessibility tree, is rendered insufficient for calendaring apps, mainly because events are extremely versatile. Tailoring the entire interface and experience around that versatility pushes us to explore alternate and custom structures.
Events are highly flexible, because they are time-based. An event can last a couple of minutes, but it can as well last for hours, days, weeks, or even months. It can start in the middle of a day and end on the upcoming day; it can start by the end of a week and end at the beginning of the upcoming week. Essentially, events are limitless, just like time itself.

Since events can last more than a day, cell widgets cannot hold a meaningful link with event widgets, because otherwise event widgets would not be capable of spanning across cells. As such, event widgets are overlaid on top of cell widgets and positioned based on the coordinates, width, and height of each widget.
As a consequence, the visual representation of GNOME Calendar is fundamentally incompatible with accessibility trees. GNOME Calendar's month and week views are visually 2.5 dimensional: A grid layout by itself is structurally two-dimensional, but overlaying event widgets that is capable of spanning across cells adds an additional layer. Conversely, accessibility trees are fundamentally two-dimensional, so GNOME Calendar's visual representation cannot be sufficiently adapted into a two-dimensional logical tree.
In summary, accessibility trees are insufficient for calendaring apps, because the versatility and high requirements of events prevents us from linking cell widgets with event widgets, so event widgets are instead overlaid on top, consequently making the visual representation 2.5 dimensional; however, the additional layer makes it fundamentally impossible to adapt to a two-dimensional accessibility tree.
Negative Implications of Accessibility due to Maximizing Performance
Unlike the majority of apps, GNOME Calendar's layout and widgetry consist of custom widgets and complex calculations according to several factors, such as:
- the size of the window;
- the height and width of each cell widget to figure out if one or more event widgets can perceptibly fit inside a cell;
- the position of each event widget to figure out where to position the event widget, and where to reposition all the event widgets around it if necessary;
what went wrong in my life to work on a calendaring app written in C.
Due to these complex calculations, along with the fact that it is also possible to have tens, hundreds, or even thousands of events, nearly every calendar app relies on maximizing performance as much as possible, while being at the mercy of the framework or toolkit. Furthermore, GNOME Calendar supports smooth scrolling and kinetic scrolling, so each event and cell widget's position needs to be recalculated for every pixel when the user scrolls or swipes with a mouse or touchpad.
One way to minimize that problem is by creating custom widgets that are minimal and only fulfill the purpose we absolutely need. However, this comes at the cost of needing to reimplement most functionality, including most, if not all accessibility features and semantics, such as keyboard focus, which severely impacted accessibility in GNOME Calendar.
While GTK's widgets are great for general purpose use-cases and do not have any performance impact with limited instances of them, performance starts to deteriorate on weaker systems when there are hundreds, if not thousands of instances in the view, because they contain a lot of functionality that event widgets may not need.
In the case of the GtkButton widget, it has a custom multiplexer, it applies different styles for different child types, it implements the GtkActionable interface for custom actions, and more technical characteristics. Other functionality-based widgets will have more capabilities that might impact performance with hundreds of instances.
To summarize, GNOME Calendar reduces overhead by creating minimal custom widgets that fulfill a specific purpose. This unfortunately severely impacted accessibility throughout the app and made it unusable with a keyboard, as some core functionalities, accessibility features and semantics were never (re)implemented.
Improving the Existing Experience
Despite being inaccessible as an app altogether, not every aspect was inaccessible in GNOME Calendar. Most areas throughout the app worked with a keyboard and/or assistive technologies, but they needed some changes to improve the experience. For this reason, this section is reserved specifically for mentioning the aspects that underwent a lot of improvements.
Improving Focus Rings
The first major step was to improve the focus ring situation throughout GNOME Calendar. Since the majority of widgets are custom widgets, many of them require to manually apply focus rings. !563 addresses that by declaring custom CSS properties, to use as a base for focus rings. !399 tweaks the style of the reminders popover in the event editor dialog, with the addition of a focus ring.
We changed the behavior of the event notes box under the "Notes" section in the event editor dialog. Every time the user focuses on the event notes box, the focus ring appears and outlines the entire box until the user leaves focus. This was accomplished by subclassing AdwPreferencesRow to inherit its style, then applying the .focused
class whenever the user focuses on the notes.
Improving the Calendar Grid
The calendar grid is a 7×6 grid of buttons representing each day. The horizontal axis represents the day of the week, and the vertical axis represents the week number.

The calendar grid on the sidebar suffered from several issues when it came to keyboard navigation, namely:
- pressing ↹ would focus the next cell in the grid up until the last cell;
- when out of bounds, there would be no auditory feedback;
- on the last row, pressing ↓ would focus a blank element; and
- pressing → in left-to-right languages, or ← in right-to-left languages, on the last column would move focus to a completely different widget.
While the calendar grid can be interacted with a keyboard, the keyboard experience was far from desired. !608 addresses these issues by overriding the Gtk.Widget.focus ()
virtual method. Pressing ↹ or Shift+↹ skips the entire grid, and the grid is wrapped to allow focusing between the first and last columns with ← and →, while notifying the user when out of bounds.
Improving the Calendar List Box
The calendar list box holds a list of available calendars, all of which can be displayed or hidden from the week view and month view. Each row is a GtkListBoxRow that holds a GtkCheckButton.
The calendar list box had several problems in regards to keyboard navigation and the information each row provided to assistive technologies.
The user was required to press ↹ a second time to get to the next row in the list. To elaborate: pressing ↹ once focused the row; pressing it another time moved focus to the check button within the row (bad); and finally pressing the third time focused the next row.
Row widgets had no actual purpose besides toggling the check button upon activation. Similarly, the only use for a check button widget inside each row was to display the "check mark" icon if the calendar was displayed. This meant that the check button widget held all the desired semantics, such as the "checkbox" role and the "checked" state; but worst of all, it was getting focus. Essentially, the check button widget was handling responsibilities that should have been handled by the row.
Both inconveniences were addressed by !588. The check button widget was replaced with a check mark icon using GtkImage, a widget that does not grab focus. The accessible role of the row widget was changed to "checkbox", and the code was adapted to handle the "checked" state.
Implementing Accessibility Functionality
Accessibility is often absolute: there is no 'in-between' state; either the user can access functionality, or they cannot, which can potentially make the app completely unusable. This section goes in depth with the widgets that were not only entirely inaccessible but also rendered GNOME Calendar completely unusable with a keyboard and assistive technology.
Making the Event Widget Accessible
GcalEventWidget, the name of the event widget within GNOME Calendar, is a colored rectangular toggle button containing the summary of an event.

Activating it displays a popover that displays additional detail for that event.
GcalEventWidget subclasses GtkWidget.
The biggest problem in GNOME Calendar, which also made it completely impossible to use the app with a keyboard, was the lack of a way to focus and activate event widgets with a keyboard. Essentially, one would be able to create events, but there would be no way to access them in GNOME Calendar.
Quite literally, this entire saga began all thanks to a dream I had, which was to make GcalEventWidget subclass GtkButton instead of GtkWidget directly. The thought process was: GtkButton already implements focus and activation with a keyboard, so inheriting it should therefore inherit focus and activation behavior.
In merge request !559, the initial implementation indeed subclassed GtkButton. However, that implementation did not go through, due to the reason outlined in § Negative Implications of Accessibility due to Maximizing Performance.
Despite that, the initial implementation instead significantly helped us figure out exactly what were missing with GcalEventWidget: specifically, setting Gtk.Widget:receives-default
and Gtk.Widget:focusable
properties to "True". Gtk.Widget:receives-default
makes it so the widget can be activated how ever desired, and Gtk.Widget:focusable
allows it to become focusable with a keyboard. So, instead of subclassing GtkButton, we instead reimplemented GtkButton's functionality in order to maintain performance.
While preliminary support for keyboard navigation was added into GcalEventWidget, accessible semantics for assistive technologies like screen readers were severely lacking. This was addressed by !587, which sets the role to "toggle-button", to convey that GcalEventWidget is a toggle button. The merge request also indicates that the widget has a popup for the event popover, and has the means to update the "pressed" state of the widget.
In summary, we first made GcalEventWidget accessible with a keyboard by reimplementing some of GtkButton's functionality. Then, we later added the means to appropriately convey information to assistive technologies. This was the worst offender, and was the primary reason why GNOME Calendar was unusable with a keyboard, but we finally managed to solve it!
Making the Month and Year Spin Buttons Accessible
GcalMultiChoice is the name of the custom spin button widget used for displaying and cycling through months and/or years.
It comprises of a "decrement" button to the start, a flat toggle button in the middle that contains a label that displays the value, and an "increment" button to the end. Only the button in the middle can gain keyboard focus throughout GcalMultiChoice.

In some circumstances, GcalMultiChoice can display a popover for increased granularity.
GcalMultiChoice was not interactable with a keyboard, because:
- it did not react to ↑ and ↓ keys; and
- the "decrement" and "increment" buttons were not focusable.
For a spin button widget, the "decrement" and "increment" buttons should generally remain unfocusable, because ↑ and ↓ keys already accomplish that behavior. Furthermore, GtkSpinButton's "increment" (+) and "decrement" (-) buttons are not focusable either, and the Date Picker Spin Button Example by the ARIA Authoring Practices Guide (APG) avoids that functionality as well.
However, since GcalMultiChoice did not react to ↑ and ↓ keys, having the "decrement" and "increment" buttons be focusable would have been a somewhat acceptable workaround. Unfortunately, since those buttons were not focusable, and ↑ and ↓ keys were not supported, it was impossible to increment or decrement values in GcalMultiChoice with a keyboard without resorting to workarounds.
Additionally, GcalMultiChoice lacked the semantics to communicate with assistive technologies. So, for example, a screen reader would never say anything meaningful.
All of the above problems remained problems until merge request !603. For starters, it implements GtkAccessible and GtkAccessibleRange, and then implements keyboard navigation.
Implementing GtkAccessible and GtkAccessibleRange
The merge request implements the GtkAccessible interface to retrieve information from the flat toggle button.
Fundamentally, since the toggle button was the only widget capable of gaining keyboard focus throughout GcalMultiChoice, this caused two distinct problems.
The first issue was that assistive technologies only retrieved semantic information from the flat toggle button, such as the type of widget (accessible role), its label, and its description. However, the toggle button was semantically just a toggle button; since it contained semantics and provided information to assistive technologies, the information it provided was actually misleading, because it only provided information as a toggle button, not a spin button!
So, the solution to this is to strip the semantics from the flat toggle button. Setting its accessible role to "none" makes assistive technologies ignore its information. Then, setting the accessible role of the top-level (GcalMultiChoice) to "spin-button" gives semantic meaning to assistive technologies, which allows the widget to appropriately convey these information, when focused.
This led to the second issue: Assistive technologies only retrieved information from the flat toggle button, not from the top-level. Generally, assistive technologies retrieve information from the focused widget. Since the toggle button was the only widget capable of gaining focus, it was also the only widget providing information to them; however, since its semantics were stripped, it had no information to share, and thus assistive technologies would retrieve absolutely nothing.
The solution to this is to override the Gtk.Accessible.get_platform_state ()
virtual method, which allows us to bridge communication between the states of child widgets and the top-level widget. In this case, both GcalMultiChoice and the flat toggle button share the state-if the flat toggle button is focused, then GcalMultiChoice is considered focused; and since GcalMultiChoice is focused, assistive technologies can then retrieve its information and state.
The last issue that needed to be addressed was that GcalMultiChoice was still not providing any of the values to assistive technologies. The solution to this is straightforward: implementing the GtkAccessibleRange interface, which makes it necessary to set values for the following accessible properties: "value-max", "value-min", "value-now", and "value-text".
After all this effort, GcalMultiChoice now provides correct semantics to assistive technologies. It appropriately reports its role, the current textual value, and whether it contains a popover.
To summarize:
- The flat toggle button was the only widget conveying information to assistive technologies, as it was the only widget capable of gaining focus and providing semantic information. To solve this, its semantics were stripped away.
- The top-level, being GcalMultiChoice, was assigned the "spin-button" role to provide semantics; however, it was still incapable of providing information to assistive technologies, because it was never getting focused. To solve this, the state of the toggle button, including the focused state, carried over to the top-level to allow assistive technologies to retrieve information from the top-level.
- GcalMultiChoice still did not provide its values to assistive technologies. This is solved by implementing the GtkAccessibleRange interface.
Providing Top-Level Semantics to a Child Widget As Opposed to the Top-Level Widget Is Discouraged
As you read through the previous section, you may have asked yourself: "Why go through all of those obstacles and complications when you could have just re-assigned the flat toggle button as "spin-button" and not worry about the top-level's role and focus state?"
Semantics should be provided by the top-level, because they are represented by the top-level. What makes GcalMultiChoice a spin button is not just the flat toggle button, but it is the combination of all the child widgets/objects, event handlers (touch, key presses, and other inputs), accessibility attributes (role, states, relationships), widget properties, signals, and other characteristics. As such, we want to maintain that consistency for practically everything, including the state. The only exception to this is widgets whose sole purpose is to contain one or more elements, such as GtkBox.
This is especially important for when we want it to communicate with other widgets and APIs, such as the Gtk.Widget::state-flags-changed
signal, the Gtk.Widget.is_focus ()
method, and other APIs where it is necessary to have the top-level represent data accurately and behave predictably. In the case of GcalMultiChoice, we set accessible labels at the top-level. If we were to re-assign the flat toggle button's role as "spin-button", and set the accessible label to the top-level, assistive technologies would only retrieve information from the toggle button while ignoring the labels defined at the top-level.
For the record, GtkSpinButton also overrides Gtk.Accessible.get_platform_state ()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static gboolean gtk_spin_button_accessible_get_platform_state (GtkAccessible *self, GtkAccessiblePlatformState state) { return gtk_editable_delegate_get_accessible_platform_state (GTK_EDITABLE (self), state); } static void gtk_spin_button_accessible_init (GtkAccessibleInterface *iface) { … iface->get_platform_state = gtk_spin_button_accessible_get_platform_state; } |
To be fair, assigning the "spin-button" role to the flat toggle button is unlikely to cause major issues, especially for an app. Re-assigning the flat toggle button was my first instinct. The initial implementation did just that as well. I was completely unaware of the Gtk.Accessible.get_platform_state ()
virtual method before finalizing the merge request, so I initially thought that was the correct way to do. Even if the toggle button had the "spin-button" role instead of the top-level, it would not have stopped us from implementing workarounds, such as a getter method that retrieves the flat toggle button that we can then use to manipulate it.
In summary, we want to provide semantics at the top-level, because they are structurally part of it. This comes with the benefit of making the widget easier to work with, because APIs can directly communicate with it, instead of resorting to workarounds.
The Now and Future of Accessibility in GNOME Calendar
All these accessibility improvements will be available on GNOME 49, but you can download and install the pre-release on the "Nightly GNOME Apps" DLC Flatpak remote on nightly.gnome.org.
In the foreseeable future, I want to continue working on !564, to make the month view itself accessible with a keyboard, as seen in the following:
A screen recording demoing keyboard navigation within the month view. Focus rings appear and disappear as the user moves focus between cells. Going out of bounds in the vertical axis scrolls the view to the direction, and going out of bounds in the horizontal axis moves focus to the logical sibling.
However, it is already adding 640 lines of code, and I can only see it increasing overtime. We also want to make cells in the week view accessible, but this will also be a monstrous merge request, just like the above merge request.
Most importantly, we want (and need) to collaborate and connect with people who rely on assistive technologies to use their computer, especially when everybody working on GNOME Calendar does not rely on assistive technologies themselves.
Conclusion
I am overwhelmingly satisfied of the progress we have made with accessibility on GNOME Calendar in six months. Just a year ago, if I was asked about what needs to be done to incorporate accessibility features in GNOME Calendar, I would have shamefully said "dude, I don't know where to even begin"; but as of today, we somehow managed to turn GNOME Calendar into an actual, usable calendaring app for people who rely on assistive technologies and/or a keyboard.
Since this is still Disability Pride Month, and GNOME 49 is not out yet, I encourage you to get the alpha release of GNOME Calendar on the "Nightly GNOME Apps" Flatpak remote at nightly.gnome.org. The alpha release is in a state where the gays with disabilities can organize and do crimes using GNOME Calendar 😎 /j
25 Jul 2025 12:00am GMT
24 Jul 2025
planet.freedesktop.org
Dave Airlie (blogspot): ramalama/mesa : benchmarks on my hardware and open source vs proprietary
One of my pet peeves around running local LLMs and inferencing is the sheer mountain of shit^W^W^W complexity of compute stacks needed to run any of this stuff in an mostly optimal way on a piece of hardware.
CUDA, ROCm, and Intel oneAPI all to my mind scream over-engineering on a massive scale at least for a single task like inferencing. The combination of closed source, over the wall open source, and open source that is insurmountable for anyone to support or fix outside the vendor, screams that there has to be a simpler way. Combine that with the pytorch ecosystem and insanity of deploying python and I get a bit unstuck.
What can be done about it?
llama.cpp to me seems like the best answer to the problem at present, (a rust version would be a personal preference, but can't have everything). I like how ramalama wraps llama.cpp to provide a sane container interface, but I'd like to eventually get to the point where container complexity for a GPU compute stack isn't really needed except for exceptional cases.
On the compute stack side, Vulkan exposes most features of GPU hardware in a possibly suboptimal way, but with extensions all can be forgiven. Jeff Bolz from NVIDIA's talk at Vulkanised 2025 started to give me hope that maybe the dream was possible.
The main issue I have is Jeff is writing driver code for the NVIDIA proprietary vulkan driver which reduces complexity but doesn't solve my open source problem.
Enter NVK, the open source driver for NVIDIA GPUs. Karol Herbst and myself are taking a look at closing the feature gap with the proprietary one. For mesa 25.2 the initial support for VK_KHR_cooperative_matrix was landed, along with some optimisations, but there is a bunch of work to get VK_NV_cooperative_matrix2 and a truckload of compiler optimisations to catch up with NVIDIA.
But since mesa 25.2 was coming soon I wanted to try and get some baseline figures out.
I benchmarked on two systems (because my AMD 7900XT wouldn't fit in the case). Both Ryzen CPUs. The first I used system I put in an RTX5080 then a RTX6000 Ada and then the Intel A770. The second I used for the RX7900XT. The Intel SYCL stack failed to launch unfortunately inside ramalama and I hacked llama.cpp to use the A770 MMA accelerators.
ramalama bench hf://unsloth/Qwen3-8B-GGUF:UD-Q4_K_XL
I picked this model at random, and I've no idea if it was a good idea.
Some analysis:
The token generation workload is a lot less matmul heavy than prompt processing, it also does a lot more synchronising. Jeff has stated CUDA wins here mostly due to CUDA graphs and most of the work needed is operation fusion on the llama.cpp side. Prompt processing is a lot more matmul heavy, extensions like NV_coopmat2 will help with that (NVIDIA vulkan already uses it in the above), but there may be further work to help close the CUDA gap. On AMD radv (open source) Vulkan is already better at TG than ROCm, but behind in prompt processing. Again coopmat2 like extensions should help close the gap there.
NVK is starting from a fair way behind, we just pushed support for the most basic coopmat extension and we know there is a long way to go, but I think most of it is achievable as we move forward and I hope to update with new scores on a semi regular basis. We also know we can definitely close the gap on the NVIDIA proprietary Vulkan driver if we apply enough elbow grease and register allocation :-)
I think it might also be worth putting some effort into radv coopmat2 support, I think if radv could overtake ROCm for both of these it would remove a large piece of complexity from the basic users stack.
As for Intel I've no real idea, I hope to get their SYCL implementation up and running, and maybe I should try and get my hands on a B580 card as a better baseline. When I had SYCL running once before I kinda remember it being 2-4x the vulkan driver, but there's been development on both sides.
(The graphs were generated by Gemini.)
24 Jul 2025 10:19pm GMT
18 Jul 2025
planet.freedesktop.org
Simon Ser: Status update, July 2025
Hi!
Sway's patch to add HDR support has finally be merged! It can be enabled via output <name> hdr on
, and requires the Vulkan renderer (which can be selected via WLR_RENDERER=vulkan
). Still, lots remains to be done to improve tone mapping and compositing. Help is welcome if you have ideas!
I've also added support for toplevel tags to Sway. Toplevel tags provide a stable key to select a particular window of a multi-window application: for instance, the favorites window of a Web browser might carry the tag "favorites". Once support is added to various clients, this should be a more robust way to target windows than title regular expressions.
David Turner has contributed support for color-representation-v1 to wlroots. Thanks to this protocol, clients can describe how channels of a buffer should be interpreted, in particular pre-multiplied vs. straight alpha, YUV matrix coefficients and full vs. limited range. The renderer and backends bits haven't been merged yet, but work-in-progress patches have been posted.
Wayland 1.24 has been released, with a new global to free up wl_registry
objects, a new "repeated" state for keyboard keys, and other new utility functions. grim 1.5 adds support for ext-image-copy-capture-v1, the new screen capture protocol. grim can now capture individual toplevel windows.
In IRC news, accessibility for the gamja Web client has been improved with ARIA attributes. A pending patch for Goguma adds support for user and channel avatars (via the metadata-2 extension). I've sent a draft for a new user query extension to synchronize opened direct message conversations across clients.
Last, qugu2427 has contributed go-smtp support for DELIVERBY (to ask the server to deliver a message before a timestamp) and MT-PRIORITY (to indicate a priority level for a message).
See you next month!
18 Jul 2025 10:00pm GMT
13 Jul 2025
planet.freedesktop.org
Sebastian Wick: Blender HDR and the reference white issue
The latest alpha of the upcoming Blender 5.0 release comes with High Dynamic Range (HDR) support for Linux on Wayland which will, if everything works out, make it into the final Blender 5.0 release on October 1, 2025. The post on the developer forum comes with instructions on how to enable the experimental support and how to test it.
If you are using Fedora Workstation 42, which ships GNOME version 48, everything is already included to run Blender with HDR. All that is required is an HDR compatible display and graphics driver, and turning on HDR in the Display Settings.
It's been a lot of personal blood, sweat and tears, paid for by Red Hat across the Linux graphics stack for the last few years to enable applications like Blender to add HDR support. From kernel work, like helping to get the HDR mode working on Intel laptops, and improving the Colorspace
and HDR_OUTPUT_METADATA
KMS properties, to creating a new library for EDID and DisplayID parsing, and helping with wiring things up in Vulkan.
I designed the active color management paradigm for Wayland compositors, figured out how to properly support HDR, created two wayland protocols to let clients and compositors communicate the necessary information for active color management, and created documentation around all things color in FOSS graphics. This would have also been impossible without Pekka Paalanen from Collabora and all the other people I can't possibly list exhaustively.
For GNOME I implemented the new API design in mutter (the GNOME Shell compositor), and helped my colleagues to support HDR in GTK.
Now that everything is shipping, applications are starting to make use of the new functionality. To see why Blender targeted Linux on Wayland, we will dig a bit into some of the details of HDR!
HDR, Vulkan and the reference white level
Blender's HDR implementation relies on Vulkan's VkColorSpaceKHR
, which allows applications to specify the color space of their swap chain, enabling proper HDR rendering pipeline integration. The key color space in question is VK_COLOR_SPACE_HDR10_ST2084_EXT
, which corresponds to the HDR10 standard using the ST.2084 (PQ) transfer function.
However, there's a critical challenge with this Vulkan color space definition: it has an undefined reference white level.
Reference white indicates the luminance or a signal level at which a diffuse white object (such as a sheet of paper, or the white parts of a UI) appears in an image. If images with different reference white levels end up at different signal levels in a composited image, the result is that "white" in one of the images is still being perceived as white, while the "white" from the other image is now being perceived as gray. If you ever scrolled through Instagram on an iPhone or played an HDR game on Windows, you will probably have noticed this effect.
The solution to this issue is called anchoring. The reference white level of all images needs to be normalized in order for "white" ending up on the same signal level in the composited image.
Another issue with the reference white level specific to PQ is the prevalent myth, that the absolute luminance of a PQ signal must be replicated on the actual display a user is viewing the content at. PQ is a bit of a weird transfer characteristic because any given signal level corresponds to an absolute luminance with the unit cd/m² (also known as nit). However, the absolute luminance is only meaningful for the reference viewing environment! If an image is being viewed in the reference viewing environment of ITU-R BT.2100, (essentially a dark room) and the image signal of 203 nits is being shown at 203 nits on the display, it makes the image appear as the artist intended. The same is not true when the same image is being viewed on a phone with the summer sun blasting on the screen from behind.
PQ is no different from other transfer characteristics in that the reference white level needs to be anchored, and that the anchoring point does not have to correspond to the luminance values that the image encodes.
Coming back to the Vulkan color space VK_COLOR_SPACE_HDR10_ST2084_EXT
definition: "HDR10 (BT2020) color space, encoded according to SMPTE ST2084 Perceptual Quantizer (PQ) specification". Neither ITU-R BT.2020 (primary chromaticity) nor ST.2084 (transfer characteristics), nor the closely related ITU-R BT.2100 define the reference white level. In practice, the reference level of 203 cd/m² from ITU-R BT.2408 ("Suggested guidance for operational practices in high dynamic range television production") is used. Notable, this is however not specified in the Vulkan definition of VK_COLOR_SPACE_HDR10_ST2084_EXT
.
The consequences of this? On almost all platforms, VK_COLOR_SPACE_HDR10_ST2084_EXT
implicitly means that the image the application submits to the presentation engine (what we call the compositor in the Linux world) is assumed to have a reference white level of 203 cd/m², and the presentation engine adjusts the signal in such a way that the reference white level of the composited image ends up at a signal value that is appropriate for the actual viewing environment of the user. On GNOME, the way to control this currently is the "HDR Brightness" slider in the Display Settings, but will become the regular screen brightness slider in the Quick Settings menu.
On Windows, the misunderstanding that a PQ signal value must be replicated one to one on the actual display has been immortalized in the APIs. It was only until support for HDR was added to laptops that this decision was revisited, but changing the previous APIs was already impossible at this point. Their solution was exposing the reference white level in the Win32 API and tasking applications to continuously query the level and adjust the image to match the new level. Few applications actually do this, with most games providing a built-in slider instead.
The reference white level of VK_COLOR_SPACE_HDR10_ST2084_EXT
on Windows is essentially a continuously changing value that needs to be queried from Windows APIs outside of Vulkan.
This has two implications:
- It is impossible to write a cross-platform HDR application in Vulkan (if Windows is one of the targets)
- On Wayland, a "standard" HDR signal can just be passed on to the compositor, while on Windows, more work is required
While the cross-platform issue is solvable, and something we're working on, the way Windows works also means that the cross-platform API might become harder to use because we cannot change the underlying Windows mechanisms.
No Windows Support
The result is that Blender currently does not support HDR on Windows.

Jeroen-Bakker explaining the lack of Windows support
</figcaption>The design of the Wayland color-management protocol, and the resulting active color-management paradigm of Wayland compositors was a good choice, making it easy for developers to do the right thing, while also giving them more control if they so chose.
Looking forward
We have managed to transition the compositor model from a dumb blitter to a component which takes an active part in color management, we have image viewers and video players with HDR support and now we have tools for producing HDR content! While it is extremely exciting for me that we have managed to do this properly, we also have a lot of work ahead of us, some of which I will hopefully tell you about in a future blog post!
13 Jul 2025 2:26pm GMT