Happy holidays, everyone – I hope you can still enjoy them somewhat given the circumstances. For me it’s always a time of reflection, thinking back on the ending year. You know, I always set high standards for the work I do, I just want to put the highest quality of work out there on the interwebs, so I kinda want to write only about stuff that I’ve already uploaded some actual code for, or where I am at least confident to pull off a release soon. However, often “perfect is the enemy of good”, so I decided to just write about some of the things I did for fun over the past days. All of what you see below may or may not end up in a release at some point, or maybe or maybe not.
Animated cursor thumbnailer
I want KDE applications to offer thumbnails for as many file types as possible, so over the years I’ve written a bunch of thumbnailers in kio-extras, such as for AppImages, Open Document (odt, ods, odp, …) files, various ebooks formats (epub, fiction book), Microsoft Office XML documents, and other files conforming to the “Open Packaging Convention”. Thankfully, modern document formats are often just ZIP archives (that can easily be handled using our KArchive framework) which already contain a thumbnail generated by the authoring application.
Furthermore, I improved the Windows EXE and ICO thumbnailer to choose the prettiest icon available and even added support for friggin’ 16-bit executables from Windows 3.1. Qt already comes with support for reading ICO and CUR (Cursor) files but there’s no support for animated cursors (ANI). Naturally, I sat down and started writing a thumbnailer for that. A short while into reading the file format specification, I realized I might as well write a proper KImageFormats plugin, so that any Qt application, like Kolourpaint and Gwenview, can present those files. Gwenview would even play them like a GIF animation!
ANI files are RIFF containers, like your good ol’ WAVE or AVI, which contain a series of CUR files. This meant I could delegate actual rendering of the image with all its format intricacies (monochrome, 8-bit indexed, etc) to Qt’s built-in image format plug-in.
Annoyingly, there’s a bunch of metadata before the actual images. Not only can you define the image change delay on a per-frame basis (note how the hourglass pauses briefly before flipping over), it’s even possible to specify a fully custom sequence in which the frames are played, the same one multiple times, even. Qt on the other hand requires a linear list of images, so I have to seek around the frame data on the fly in order to have a subsequent read() call end up with whatever frame is supposed to be displayed next. Bonus points to whoever makes KWin capable of using those as actual mouse cursors :D
Speaking of thumbnailers, I was looking into getting thumbnails generated for ASTC textures. I noticed that there wasn’t even a MIME type for them, so I added one. There already was image/ktx (for which I’d love a thumbnailer too, by the way), so I figured a simple image/astc was fitting.
I then tried to use Google’s astc-codec library but the CMake build system there wasn’t quite up to the standard I was used to from our ECM framework – I had a hard time even just building this thing as a shared library… It also only does the actual rendering, you still need to implement all metadata processing yourself, including reading image size and row stride, and picking the right “footprint type”. I got it kinda working but couldn’t figure out why it’s not rendering correctly – not sure if I did something stupid or hit a bug in that library, but it affects all images and formats I tried.
Browser phone number detection
Don’t you hate it when a website doesn’t add tel: hyperlinks to phone numbers? Thanks to Volker’s KItinerary library we already have the necessary modules in ECM to find and link Google’s libphonenumber, which I used in an attempt to remedy that situation through Plasma Browser Integration. Unfortunately, it wasn’t quite as straightforward.
First of all, only Firefox has an extension API that notifies when a context menu is opened to start a phone number search once the user right-clicks one. Secondly, while there is a property for the DOM element clicked in the API, it is only available when using WebExtensions “menus” API, not the “contextmenus” API Chrome offers. Firefox maps all its APIs under the chrome namespace for interoperability, including the aforementioned “proprietary” onShown event, but explicitly forgoes the targetElementId property in this case – an odd choice.
Luckily, instead I could just listen to the contextmenu event from within the content script injected into each page. Getting the actual text around the cursor position turned out to be super painful. Originally I just processed the innerText of the clicked element but what if you have multiple numbers scattered throughout a paragraph of text? I then found a horrific way of using HTML Ranges API to brute force a selection character by character until I found a bounding rectangle that included the mouse position. This way I can get the exact line of text but still need a way to isolate a number from adjacent ones and I didn’t want to add too much heuristics on the extension side – that’s what libphonenumber is for, after all.
PowerDevil platform profiles
A few days ago Nate was approached about a new “platform profiles” ACPI API that will be added to the Linux kernel. It allows to apply certain power management presets, such as “balanced”, “quiet”, “performance” without having to worry about changing specific details, like setting CPU frequency explicitly on the software side. Knowing that I’ve wanted a setting like this forever, Nate told me about this, and on Christmas Eve after returning from a smaller-than-usual family dinner I fired up a Linux kernel build and wrote a KAuth helper for manipulating those new sysfs files.
I also added a PowerDevil action which can automatically change the profile when you plug in/out your power supply or the battery is running low. Finally, I also added a DBus interface for enumerating and switching profiles that can then be used for some sort of UI in battery monitor to change between profiles anytime. I actually haven’t managed to get it working on my ThinkPad just yet but it looked simple enough to write that plug-in blindly.