This feed omits posts by rms. Just 'cause.
Is our military resilient when the attack is coming from inside the House? I doubt it. Hegseth rubber-stamps some unconstitutional order, then starts firing generals until they get to one who says yes. So either the military goes along with it, meaning now they're Trump's military instead of the USA's, which is not good, or they don't recognize the authority of their Commander in Chief, and the only way that story ends is with armed insurrection and the military installing a new president, which is also not good.
I hesitate to even post this worry for a few reasons:
- I don't need to have my time wasted by minimizing Reply Guys telling me "they wouldn't do that" or "that would be illegal" or "you're paranoid" or "let's give him a chance."
- There is absolutely nothing that you or I or anyone we know can do about it, short of offering up our torsos for target practice. Once the military is pointed at "The Enemy Within", the strategies of "sign this change dot org petition" and "vote harder in the next midterms" are kind of off the table.
Previously, previously, previously, previously, previously, previously.
A while ago I was looking at Rust-based parsing of HID reports but, surprisingly, outside of C wrappers and the usual cratesquatting I couldn't find anything ready to use. So I figured, why not write my own, NIH style. Yay! Gave me a good excuse to learn API design for Rust and whatnot. Anyway, the result of this effort is the hidutils collection of repositories which includes commandline tools like hid-recorder and hid-replay but, more importantly, the hidreport (documentation) and hut (documentation) crates. Let's have a look at the latter two.
Both crates were intentionally written with minimal dependencies, they currently only depend on thiserror and arguably even that dependency can be removed.
HID Usage Tables (HUT)
As you know, HID Fields have a so-called "Usage" which is divided into a Usage Page (like a chapter) and a Usage ID. The HID Usage tells us what a sequence of bits in a HID Report represents, e.g. "this is the X axis" or "this is button number 5". These usages are specified in the HID Usage Tables (HUT) (currently at version 1.5 (PDF)). The hut crate is generated from the official HUT json file and contains all current HID Usages together with the various conversions you will need to get from a numeric value in a report descriptor to the named usage and vice versa. Which means you can do things like this:
let gd_x = GenericDesktop::X; let usage_page = gd_x.usage_page(); assert!(matches!(usage_page, UsagePage::GenericDesktop));Or the more likely need: convert from a numeric page/id tuple to a named usage.
let usage = Usage::new_from_page_and_id(0x1, 0x30); // GenericDesktop / X println!("Usage is {}", usage.name());90% of this crate are the various conversions from a named usage to the numeric value and vice versa. It's a huge crate in that there are lots of enum values but the actual functionality is relatively simple.
hidreport - Report Descriptor parsing
The hidreport crate is the one that can take a set of HID Report Descriptor bytes obtained from a device and parse the contents. Or extract the value of a HID Field from a HID Report, given the HID Report Descriptor. So let's assume we have a bunch of bytes that are HID report descriptor read from the device (or sysfs) we can do this:
let rdesc: ReportDescriptor = ReportDescriptor::try_from(bytes).unwrap();I'm not going to copy/paste the code to run through this report descriptor but suffice to day it will give us access to the input, output and feature reports on the device together with every field inside those reports. Now let's read from the device and parse the data for whatever the first field is in the report (this is obviously device-specific, could be a button, a coordinate, anything):
let input_report_bytes = read_from_device(); let report = rdesc.find_input_report(&input_report_bytes).unwrap(); let field = report.fields().first().unwrap(); match field { Field::Variable(var) => { let val: u32 = var.extract(&input_report_bytes).unwrap().into(); println!("Field {:?} is of value {}", field, val); }, _ => {} }The full documentation is of course on docs.rs and I'd be happy to take suggestions on how to improve the API and/or add features not currently present.
hid-recorder
The hidreport and hut crates are still quite new but we have an existing test bed that we use regularly. The venerable hid-recorder tool has been rewritten twice already. Benjamin Tissoires' first version was in C, then a Python version of it became part of hid-tools and now we have the third version written in Rust. Which has a few nice features over the Python version and we're using it heavily for e.g. udev-hid-bpf debugging and development. An examle output of that is below and it shows that you can get all the information out of the device via the hidreport and hut crates.
$ sudo hid-recorder /dev/hidraw1 # Microsoft Microsoft® 2.4GHz Transceiver v9.0 # Report descriptor length: 223 bytes # 0x05, 0x01, // Usage Page (Generic Desktop) 0 # 0x09, 0x02, // Usage (Mouse) 2 # 0xa1, 0x01, // Collection (Application) 4 # 0x05, 0x01, // Usage Page (Generic Desktop) 6 # 0x09, 0x02, // Usage (Mouse) 8 # 0xa1, 0x02, // Collection (Logical) 10 # 0x85, 0x1a, // Report ID (26) 12 # 0x09, 0x01, // Usage (Pointer) 14 # 0xa1, 0x00, // Collection (Physical) 16 # 0x05, 0x09, // Usage Page (Button) 18 # 0x19, 0x01, // UsageMinimum (1) 20 # 0x29, 0x05, // UsageMaximum (5) 22 # 0x95, 0x05, // Report Count (5) 24 # 0x75, 0x01, // Report Size (1) 26 ... omitted for brevity # 0x75, 0x01, // Report Size (1) 213 # 0xb1, 0x02, // Feature (Data,Var,Abs) 215 # 0x75, 0x03, // Report Size (3) 217 # 0xb1, 0x01, // Feature (Cnst,Arr,Abs) 219 # 0xc0, // End Collection 221 # 0xc0, // End Collection 222 R: 223 05 01 09 02 a1 01 05 01 09 02 a1 02 85 1a 09 ... omitted for previty N: Microsoft Microsoft® 2.4GHz Transceiver v9.0 I: 3 45e 7a5 # Report descriptor: # ------- Input Report ------- # Report ID: 26 # Report size: 80 bits # | Bit: 8 | Usage: 0009/0001: Button / Button 1 | Logical Range: 0..=1 | # | Bit: 9 | Usage: 0009/0002: Button / Button 2 | Logical Range: 0..=1 | # | Bit: 10 | Usage: 0009/0003: Button / Button 3 | Logical Range: 0..=1 | # | Bit: 11 | Usage: 0009/0004: Button / Button 4 | Logical Range: 0..=1 | # | Bit: 12 | Usage: 0009/0005: Button / Button 5 | Logical Range: 0..=1 | # | Bits: 13..=15 | ######### Padding | # | Bits: 16..=31 | Usage: 0001/0030: Generic Desktop / X | Logical Range: -32767..=32767 | # | Bits: 32..=47 | Usage: 0001/0031: Generic Desktop / Y | Logical Range: -32767..=32767 | # | Bits: 48..=63 | Usage: 0001/0038: Generic Desktop / Wheel | Logical Range: -32767..=32767 | Physical Range: 0..=0 | # | Bits: 64..=79 | Usage: 000c/0238: Consumer / AC Pan | Logical Range: -32767..=32767 | Physical Range: 0..=0 | # ------- Input Report ------- # Report ID: 31 # Report size: 24 bits # | Bits: 8..=23 | Usage: 000c/0238: Consumer / AC Pan | Logical Range: -32767..=32767 | Physical Range: 0..=0 | # ------- Feature Report ------- # Report ID: 18 # Report size: 16 bits # | Bits: 8..=9 | Usage: 0001/0048: Generic Desktop / Resolution Multiplier | Logical Range: 0..=1 | Physical Range: 1..=12 | # | Bits: 10..=11 | Usage: 0001/0048: Generic Desktop / Resolution Multiplier | Logical Range: 0..=1 | Physical Range: 1..=12 | # | Bits: 12..=15 | ######### Padding | # ------- Feature Report ------- # Report ID: 23 # Report size: 16 bits # | Bits: 8..=9 | Usage: ff00/ff06: Vendor Defined Page 0xFF00 / Vendor Usage 0xff06 | Logical Range: 0..=1 | Physical Range: 1..=12 | # | Bits: 10..=11 | Usage: ff00/ff0f: Vendor Defined Page 0xFF00 / Vendor Usage 0xff0f | Logical Range: 0..=1 | Physical Range: 1..=12 | # | Bit: 12 | Usage: ff00/ff04: Vendor Defined Page 0xFF00 / Vendor Usage 0xff04 | Logical Range: 0..=1 | Physical Range: 0..=0 | # | Bits: 13..=15 | ######### Padding | ############################################################################## # Recorded events below in format: # E: . [bytes ...] # # Current time: 11:31:20 # Report ID: 26 / # Button 1: 0 | Button 2: 0 | Button 3: 0 | Button 4: 0 | Button 5: 0 | X: 5 | Y: 0 | # Wheel: 0 | # AC Pan: 0 | E: 000000.000124 10 1a 00 05 00 00 00 00 00 00 00
The trucks were transporting 4,040 cases of tequila, or 24,240 bottles, including Santo blanco, reposado and a specially-made extra añejo, which took 39 months to create. [...]
One truck was expected to arrive at a warehouse in California and the other to one in Pennsylvania, but neither arrived at their destination. Johanson then discovered that the loads had been "illegally double brokered" to different carriers, according to the report.
"We believe the GPS tracking signal we were monitoring was spoofed by a GPS emulator application used by the criminals," reads the report. [...]
"Data analytics from Verisk CargoNet project that cargo theft has reached an all-time high in 2024 and will be over 25 percent higher than in 2023," [...] They add that much of the theft in 2023 was related to hard seltzer, but this year, hard liquor like Santo is being targeted "almost exclusively."
Previously, previously, previously, previously, previously, previously, previously, previously, previously.
In this weekend’s edition of ‘Bram gets nerd sniped by something ridiculous so makes a blog post about it to make it somebody else’s problem’ Mark Rober said something about ‘A Lava Lamp made out of real lava’. Unfortunately he just poured lava on a regular lava lamp to destroy it but this does raise the question of whether you could have a real lava lamp which uses a molten salt instead of water.
First the requirements. The lamp is made of three substances: the lamp itself, the ‘liquid’ inside, and the ‘solid’ inside. The lamp must be transparent and remain solid across the range of temperatures used. The ‘liquid’ must be solid at room temperature, become liquid at a high but not too high temperature, and be transparent in its liquid phase. It should also be opaque in its solid phase to give a cool reveal of what the thing does as it heats up but but that’s hard to avoid. The ‘solid’ should have a melting point higher than the ‘liquid’ but not so high that it softens the lamp and be opaque. The density of the ‘solid’ should be just barely below that of the ‘liquid’ in its melted form and just barely above in its solid form to give it that distinctive lava lamp buoyancy effect. The ‘solid’ and ‘liquid’ should not react with each other or stick to the lamp or decompose over time.
That was a lot of requirements, but it does seem to be possible to meet them. The choice for the lamp is obvious: Borosilicate glass. That’s physically strong, transparent, can withstand big temperature changes (due to low thermal expansion) and is chemically inert. All the same reasons why it’s ideal for cookware. It doesn’t get soft until over 800C, so the melting points of the other materials should be well below that.
For the ‘liquid’ there also turns out to only be one real option: Zinc Chloride. That’s transparent and has a melting point of 290C and a density of 2.9 (it’s also opaque at room temperature). The other transparent salts aren’t dense enough.
For the ‘solid’ there once again only seems to be one option: Boron Trioxide. That has a melting point of 450C and a density of 2.46. Every other oxide has a density which is way too high, but this one overshoots it a bit. It’s much easier to get get the densities closer together by making mixing the Boron Trioxide with something heavy than the Zinc Chloride with something light, so some Lead(II) oxide can be mixed in. That has a density of 9.53 so not much of it is needed and a melting point of 888C so the combined melting point will still be completely reasonable. (Due to eutectic-type effects it might be barely higher at all.) It should also add some color, possibly multiple ones because the colors formed depend on how it cools. Bismuth(III) oxide should also work and may be a bit more colorful.
I’m crossing my fingers a bit on these things not reacting but given that they’re glasses and salts it seems reasonable. The glasses may have a bit of a tendency to stick to each other. Hopefully not so much because one is a solid at these temperatures and the other is a liquid, but it’s probably a good idea to coat the top and bottom of the insides of the lamp with Silicon and to use an overall shape where the pieces inside never come close to the walls, in particular having an inverted cone shape at the bottom and a similar tapering at the top. The whole lamp should also be sealed because oxygen and water might react at the high temperatures reached, and there should be an argon bubble at the top because there is some expansion and contraction going on. Those same concerns apply to regular lava lamps which explains a lot about how they’re shaped.
Anyone who wants to feel free to try this build. You don’t need any more permission from me. I’d like to see it happen and don’t have the time to spend on building it myself.
InfoWars, A Global Tetrahedron Company.
ANDROALPHUS: A powerful demon and a marquis of the infernal empire; he shows himself in the shape of a peacock with a deep voice. When he appears in human form, he can be forced to give lessons of geometry. He is an astronomer and, besides, he teaches how to skillfully argue over details.
I say to you, whomst among us has not leaned against the bar and drunkenly given lessons of geometry.
Previously, previously, previously, previously, previously, previously.
Scientists have found that a "rare intense wind event" during NASA's Voyager 2 flyby of Uranus in 1986 may have seriously messed with our understanding of the planet.
Previously, previously, previously, previously, previously, previously, previously.
Why can't we just agree to disagree? Demonizing Trump voters like me only leads to toxicity, and it's bad for your health to be so agitated. Let's find a way to unite so that this ugliness doesn't surface again when we head to the polls in four years. And if your worst-case scenario comes to pass -- that this was the last democratic election we'll have in this country -- think of how stress-free you'll be then. For now, maybe just pop a Xanax and have a little faith.
I personally believe we'll continue to have elections. We will elect Trump in 2028 and in 2032 and, God willing, every four years as long as he shall live. Or perhaps scientists will find a way to preserve his body and stop aging so that he can be our leader until the literal end of the world, which I know you think will happen soon because of climate change, and if you genuinely believe that, why are you so worried? You'll only have, what, twenty years or so of authoritarian rule before life becomes nothing but fleeing fire and flood. It'll be like those Irwin Allen disaster movies we loved as kids! I personally think it's awesome that my house in Central Massachusetts might be waterfront property sooner rather than later.
Previously, previously, previously, previously, previously, previously.
"Now that Dorsey has bailed as a board member and principal funder, Bluesky's DNA is basically [TESCREAL / Effective Altruist] people. It gets worse. Blockchain Capital LLC was co-founded by Steve Bannon pal Brock Pierce, a major crypto advocate, perennial presidential candidate, and close friend of Eric Adams. Pierce has dozens of other shady MAGA/Russia ties as well."
Let’s say you happen to need a color code something and want RGB values corresponding to all the common color names. Let’s further say that you’re an obsessive maniac and would like to avoid losing your sanity studying color theory just for the sake of this one silly task. How do you do it? Easy, leverage the work I already did for you. Here’s the chart, followed by caveats and methodology:
First the caveats: The level of saturation of these colors varies a lot mostly because sRGB sucks and your monitor can only display faded versions of some of them. (For colorblind accessibility it might be a good idea to use slightly lower saturation.) A luminance high enough to make yellow have decent saturation washes out other things so this was set to a consistent level which is a reasonable compromise. (This isn’t the fault of sRGB, it’s a limitation of human eyes.) Purple hues at angles 300 and 320 are both things which my eyes accept as the single ideal of Purple and don’t realize are two different things until I see them next to each other. The value given is midway between. Reasonable descriptions of them are ‘Royal Purple’ and ‘Common Purple’. They have an analogous relationship to the one between Blue and Cyan.
The methodology behind this first has to answer the question ‘What is a color?’ For the purposes of this exercise we’ll just pretend that hues are colors. The next question is why particular positions in the hue continuum count as colors. Hues are a twisting road. In particular places the road bends, making a gradient crossing over it look not like a straight line. The places where those bends happen we call colors. Which bends get a name is dependent on where you set the threshold and cultural factors. The exact point where the bend happens is also hard to define exactly. I located them by the highly scientific process of picking them out with my own two eyes.
There’s a standard statement of what the common color words are in English to which I’m adding Cyan and Pink. Cyan is a proper name for what’s usually called ‘Light Blue’, a name which makes no sense because both Cyan and Blue can appear at any amount of luminance. It may be that Cyan is denied a proper common name because our displays can barely show it. The biggest limitation of sRGB by far is that it can only display Cyan with poor saturation. Pink I put in both because it’s a primary color (as is Cyan) and because it’s a very common color word in English, mostly denied its proper place out of an absurd bit of misogyny and homophobia. It’s especially funny that in printing Pink is euphemized as ‘Magenta’ even though the shade which is used is a light one and the common usage of ‘Magenta’ is to refer to a darker shade.
One important thing to note is that the primary colors, which have sRGB values set to 00 and FF, are NOT on ideal color hues. Those colors correspond to the most saturated things your display can show, which is important, but the positioning of RGB was selected first and foremost for them to be 120 degrees from each other to maximize how much color display could be done with only three phosphores. They happen to be very close to the true ideals but not exactly.
To pick out exact shades I used an OKHSL color picker with saturation 100% and light and dark luminance at 65% and 43%. There are still a few artifacts of OKHSL, in particular its hues bend a tiny bit in the darker shades. To compensate I picked out color angles which are good at both high and low luminance, mostly resulting in Cyan being shifted over because in darker shades Teal is elbowing it out of the way. One thing OKHSL does NOT do is maintain the property that two colors which are opposite each other in space are true opposites, which is annoying because oppositeness is one of the most objective things you can say about colors. (That could probably be improved by having brightness correction be done by cubing a single value instead of three values separately but I personally am not going to put together such a proposal.)
Annoyingly the human perceptual system doesn’t see fit to put color angles with canonical names opposite each other, instead placing them roughly evenly but with seemingly random noise added. This of course creates problems for color wheels, which want both to show what colors are opposites and what the color names are.
If you want to know how bad your computer display is, go here, select sRGB for the gamut, OKLab for the geometric color coordinate space, and Color for the spectral colors, and rotate it around. You’ll get a much better sense of what’s going on rotating it in 3D yourself, but I’ll do some explaining. Here’s a screenshot showing just how much of the color space your monitor is missing:
The colored shape shows the extremes of what your color can display. It’s warped to reflect the cognitive distance between colors, so the distances in space reflect the apparent distance between the colors in your brain. Ideally that shape would fill the entire basket, which represents all the colors your eyes can perceive. You might notice that it comes nowhere close. It’s a stick going from black at the bottom to white at the top, with just enough around it that you can get colors but the saturation is poor.
The biggest chunks missing from this are that there’s very little bright blue and dark cyan. This may be why people mischaracterize cyan as ‘light blue’. Our display technologies are literally incapable of displaying a highly saturated light blue or a highly saturated dark cyan. It’s likely that most of the paintings from Picasso’s blue period can’t be displayed properly on a monitor, and that he was going with blues not as a gimmick but because it’s literally half the human cognitive space. If you have the ability to make a display or physical object without the standard restrictions go with bright blue or dark cyan. Even better contrast them with each other and break everybody’s brains.
Sadly this situation is basically unfixable. The Rec2020 standard covers much more of the color space, but you can’t simply display sRGB values as Rec2020 values. That will result in more intense colors, but because the original inputs weren’t designed for it the effect will be cartoony and weird. You can simply display the correct values specified by sRGB, but that will waste the potential of the display . If there was content recored for sRGB which specified that in its format it would display very well, but that’s has a chicken and egg problem, and the displaying input recorded for Rec2020 on a legacy sRGB display is even worse than going the other way around. Maybe about the best you can do is have a Rec2020 display which applies a superlinear saturation filter to sRGB input so low saturations are true but ‘fully saturated’ values look more intense.
This is an example of how modern televisions do a huge amount of processing of their input before displaying it and it’s extremely difficult to disentangle how good the physical display is from the quality of the processing software. Another example of that is in the display of gradients. A 10 bit color display will naturally display gradients much better than an 8 bit color display, but an 8 bit color display can dither the errors well enough to be nearly imperceptible. The problem then is that causes flicker due to the dithering changing between frames. There are ways of fixing this by keeping information between frames but I don’t think there’s an open source implementation of this for televisions to use. One has to assume that many if not nearly all of the proprietary ones do it.
Speaking of which, this is a problem how software in general handles color precision. It’s true that 8 bits is plenty for display, but like with audio you should keep all intermediate representations with much greater precision and only smash them down when making the final output. Ideally operating systems would pretend that final display had 16 bit color and fix it on final display, or even in the monitor. Lossy video compression in particular inexplicably gives 8 bit color output resulting in truly awful dark gradients. The standard Python image libraries don’t even have an option for higher color precision resulting in them producing terrible gradients. This should be completely fixable.
Popping back up the stack I’d like to fantasize about a data format for display technology which supports the entire range of human perceptible colors. This would encode color as three values: x, y, and luma. x would go between 0 and 2 with y between 0 and 1. It’s a little hard to describe what exactly these values mean, but (0, 0) would be red, (1, 0) yellow, (2, 0) green, (2, 1) cyan, (1, 1) blue, and (0, 1) pink. The outer edge goes around the color wheel keeping opposite colors opposite and doing an okay job of corresponding with cognitive space even in raw form. You could make an approximate rendering of this in sRGB as a smushed color wheel but by definition the outer edge of that would be horrendously faded compared to how it should look. Luminance should work as it implicitly does in RGB: Luminance 0 is exactly black and x and y have no effect. As it goes up the cognitive width which x and y represent increases up until the midway point, then it shrinks again until it gets to luminance 1 which is exactly white and x and y again have no effect. This shrinking at the top is to reflect how real displays work. If you want to get much better bright colors you can use the luminance of 1/2 as white at the expense of everything being darker. Many movies do this, which makes them look great when covering a whole display but dark when open in a window next to true white on a monitor.
Deep diving on color theory of course has given me multiple ideas for hobby software projects, most of which I’ll probably never get around to because many things don’t pan out but mostly because I have limited hobby coding time so things get triaged heavily. If anybody wants to beat me to the punch on these please go ahead:
A color cycling utility which instead of rotating the color space reflects it. Usually when color cycling there’s one position which is true, then it rotates until all hues are changed to their opposite, then it rotates back around the other way. This would instead at all times have two opposite hues which are true and two opposite colors which are flipped and cycle which those are. Ideally this would be implemented by converting to okHSL, changing H to (d-H) % 1 and converting back again. As you change d it will cycle. You could trivially change it to a very nice traditional color cycler using (d+H) % 1.
A color cycling utility which allows user controlled real time three dimensional color rotation. If you take an input image, convert it into the okLab color space and shrink its color space to fit in a sphere centered at (0.76, 0, 0) with radius 0.125 then this can be done without hitting any values which are unreachable in sRGB. The interface for rotating it should be similar to this one. In the past when I’ve tried doing these sorts of three dimensional color rotations they’ve looked horrible when white-black gets off axis. Hopefully that’s because the cognitive distance in that direction is so much greater than in the color directions and keeping everything uniform will fix it, but it may be that getting white and black inverted at all fundamentally looks weird.
TLDR: if you know what EVIOCREVOKE does, the same now works for hidraw devices via HIDIOCREVOKE.
The HID standard is the most common hardware protocol for input devices. In the Linux kernel HID is typically translated to the evdev protocol which is what libinput and all Xorg input drivers use. evdev is the kernel's input API and used for all devices, not just HID ones.
evdev is mostly compatible with HID but there are quite a few niche cases where they differ a fair bit. And some cases where evdev doesn't work well because of different assumptions, e.g. it's near-impossible to correctly express a device with 40 generic buttons (as opposed to named buttons like "left", "right", ...[0]). In particular for gaming devices it's quite common to access the HID device directly via the /dev/hidraw nodes. And of course for configuration of devices accessing the hidraw node is a must too (see Solaar, openrazer, libratbag, etc.). Alas, /dev/hidraw nodes are only accessible as root - right now applications work around this by either "run as root" or shipping udev rules tagging the device with uaccess.
evdev too can only be accessed as root (or the input group) but many many moons ago when dinosaurs still roamed the earth (version 3.12 to be precise), David Rheinsberg merged the EVIOCREVOKE ioctl. When called the file descriptor immediately becomes invalid, any further reads/writes will fail with ENODEV. This is a cornerstone for systemd-logind: it hands out a file descriptor via DBus to Xorg or the Wayland compositor but keeps a copy. On VT switch it calls the ioctl, thus preventing any events from reaching said X server/compositor. In turn this means that a) X no longer needs to run as root[1] since it can get input devices from logind and b) X loses access to those input devices at logind's leisure so we don't have to worry about leaking passwords.
Real-time forward to 2024 and kernel 6.12 now gained the HIDIOCREVOKE for /dev/hidraw nodes. The corresponding logind support has also been merged. The principle is the same: logind can hand out an fd to a hidraw node and can revoke it at will so we don't have to worry about data leakage to processes that should not longer receive events. This is the first of many steps towards more general HID support in userspace. It's not immediately usable since logind will only hand out those fds to the session leader (read: compositor or Xorg) so if you as application want that fd you need to convince your display server to give it to you. For that we may have something like the inputfd Wayland protocol (or maybe a portal but right now it seems a Wayland protocol is more likely). But that aside, let's hooray nonetheless. One step down, many more to go.
One of the other side-effects of this is that logind now has an fd to any device opened by a user-space process. With HID-BPF this means we can eventually "firewall" these devices from malicious applications: we could e.g. allow libratbag to configure your mouse' buttons but block any attempts to upload a new firmware. This is very much an idea for now, there's a lot of code that needs to be written to get there. But getting there we can now, so full of optimism we go[2].
[0] to illustrate: the button that goes back in your browser is actually evdev's BTN_SIDE and BTN_BACK is ... just another button assigned to nothing particular by default.
[1] and c) I have to care less about X server CVEs.
[2] mind you, optimism is just another word for naïveté
Matt Parker asks for an 'ideal’ jigsaw with two solutions:
The criteria seem to be that the jigsaw should be (a) 25 pieces in a 5x5 grid (b) each edge type occurs exactly twice (c) there are exactly two solutions (d) in the two different solutions the maximum number of pieces are reoriented upside down. He’s done a search using a computer but that turns out to be unnecessary.
There’s a very simple mathematical trick which can be applied here. If the rows and columns are numbered 1-5, first swap columns 2 and 4, then swap rows 2 and 4, like this:
Then you flip it all upside down, and presto, all the criteria satisfied perfectly. Except… not quite. The problem is that this doesn’t result in two solutions, it results in four. You can independently decide whether to swap the rows and the columns. The most elegant fix for this seems to be to change the shapes of the pieces a bit so that instead of each piece just sharing an edge with the ones in the left, right, up, and down directions they also share with the ones in the upper right and lower left. This not only enforces that there are exactly two solutions, it also preserves the property that each edge type occurs exactly twice, even on the diagonal edges