This post is an attempt to summarize my experiences and adventures with Linux from the last two or three weeks. Before I finalized this post, Ubuntu 26.04 LTS had been officially released, but this didn’t change much. The only thing that got clarified is that Ubuntu MATE is literally dead, with no release as of the time of writing and the last daily build from March 4.

Linux and the Stockholm SyndromeDedoimedo made my dayDumbo goes on!My first Mutter-cum-Wayland bug!Wayland’s real breakage by designKubuntu as a safe havenKDE’s own limitationsXFCE as a backup solutionBluetooth, the supreme inadequacy of the Linux desktopClosing lines

Linux and the Stockholm Syndrome

Everyone who’s not a brainwashed fanboy admits that Linux is a complete piece a shit. Maybe not on servers, but the Linux desktop. Stupid desktop environments, systemd, Wayland, and the overall pathetic quality. Then, Linux on laptops is even worse. (Because you can forget about the BSDs on laptops.) But Linux still offers much more freedom than Windows. And it’s much more fun.

Or it’s the Stockholm Syndrome. Who could possibly know? All I know is that Hell would have frozen over twice before I touch a MacBook!

① So my other OS has to be Linux.

Dedoimedo made my day

Look, when I said that the in-kernel ntfs3 driver fucked an external SSD partition, the Universe couldn’t care less. Nobody from the Linux kernel team ever acknowledged that there’s a problem with ntfs3! There weren’t many reports from people, because you’re not supposed to back up anything on NTFS, right?

But recently, Dedoimedo himself has been hit by ntfs3 (this should be the name of a vulnerability, like Meltdown and Spectre, not a driver!), as mentioned in his Slimbook Executive report 13:

Now, kernel 6.14 did not fix the issue [of the machine going to sleep on its own, sometimes several times in a row, without any input from anyone]. So, how about 6.17?

Nope. The issue is still there, I’m afraid.

But, there are some big pluses to the new kernel. First, the performance. The operating system runs faster than before. It’s snappier, more responsive. There’s less heating, less fan noise. Consequently, the battery charge lasts longer, similar to the numbers I’ve observed early in the laptop’s life. Most commendable.

The kernel NTFS driver borked an external USB filesystem

Here’s another piece of funny news. I’ve mentioned this in the 12th report. The ntfs3 driver does not seem to work that well. I’ve also seen this on the Titan when using TrueCrypt and VeraCrypt, and I had to run these programs without relying on the kernel module to be able to copy files without system freezes. Another solution is to blacklist this driver, and use the FUSE-based, userspace ntfs-3g, which is slower but far more reliable. More on this separately.

However, on the Executive, I had not yet done this, and so when I connected the NTFS-formatted external device, for a few brief seconds, everything was fine. Then, both Dolphin and Konsole started getting stuck, I saw a bunch of I/O errors, and the disk disappeared. When I connected this disk to a Windows box, it told me the filesystem was corrupt and needed repair. I did that, but then I discovered the filesystem contents were gone, roughly 300 GB worth of data. It’s a backup disk, so no biggie, but still. What if that wasn’t the case?

Been there, done that. But the ntfs-3g driver is excruciatingly slow. The entire Linux kernel team should be thrown to lions! We’re in 2026, and a fucking filesystem that’s been largely unchanged for over 20 years isn’t properly supported in any OS that’s not Windows! The entire Linux kernel team should be thrown to lions!

Do they care about it? Heck, no. Instead, the Linux kernel will incorporate a driver for VMUFAT (Visual Memory Unit File Allocation Table), a filesystem for Sega Dreamcast game consoles. They were discontinued 25 years ago, on March 31, 2001, yet some shithead needs such a driver in the kernel. Not FUSE (Filesystem in Userspace).

But of course, if ntfs3 is eating data and partitions, and ntfs-3g (FUSE) is slow as molasses, there’s going to be another Linux NTFS driver: New NTFS File-System Driver Submitted For Linux 7.1.

This comment is right:

Fucking piece of fucking shit. I need a 20 TB HDD so I could copy all my backups there, then reformat every remaining NTFS HDD to exFAT, and copy the data back.

One day later, the new “NTFS resurrection” kernel driver has been merged in 7.1. In the comments section, readers of Phoronix started arguing about how bad and “broken” Microsoft’s NTFS is! I obviously prefer exFAT for portable media, but NTFS is an excellent filesystem.

On the other hand, Liam Proven welcomed the new driver. Based on his reaction to the comments, Liam believes both ntfs-3g (FUSE) and ntfs3 to be unable to break a Windows partition. If he weren’t about my age, I’d have thought he still believes in the Tooth Fairy.

While Arch still doesn’t offer the 7.0 kernel, Cachy does. Not only that, CachyOS developers felt crazy enough to ship it with the new NTFS kernel driver!

UPDATE: New NTFS Driver Sees A Number Of Fixes Ahead Of Linux 7.1-rc1: “The fixes aren’t too dramatic but do address some possible data leakage and other items.” Data leakage, eh?

All is not lost: NTFS-3G FUSE Driver Sees First New Release In Four Years. Oh, but what it breaks what it worked?!

UPDATE: Dedoimedo: Blacklist ntfs3 and use ntfs-3g for slower but stable experience.

Back to Dedoimedo’s article:

I don’t know if many of you know, but for a brief while, Ubuntu had a broken libexiv2 package, which made it impossible to open any image file in any program. This also affected Kubuntu, of course. I encountered this in a virtual machine, and reverted the package back, which helped, so I held the update until it was properly fixed.

Indeed. Bug #2144731: Multiple image apps (Gwenview, GIMP, gThumb) crashes when pasting/open image after libexiv2 upgrade.

② Living under Linux is hazardous.

Dumbo goes on!

Following episodes one, two, three, four, my adventure with Ubuntu 26.04 GNOME (customized) went on smoothly.

What I learned, however, is that the real “classic menu” GNOME extension (should I want one, and I did) is ArcMenu. No, not this one. This one.

It’s tremendously configurable, with an incredible number of preconfigured layouts! Better than anything else! (That is, if you ignore the fact that it’s written in JS.)

Now, mind you, I also kept the infamous Applications Overview thing (or whatever its name is). I genuinely try to use it, and I really do use it. You see, this might rejuvenate me (unless I die before).

I have to insist on that: everything ran smoothly. No visible problem whatsoever, no breakage. Not on my laptop.

Some people had issues, though. Apparently, Mutter + Wayland + NVIDIA = 💣

I will never use NVIDIA on anything that I own. Nothing. Nada. Nunca. Of course, that means I’ll never be able to run LLMs locally in any meaningful way.

In other news, Ubuntu’s daily builds became more and more… streamlined. By this, I mean smaller, which I suppose also implies they’re more refined by excluding unnecessary shit.

  • On April 17, the build from April 15: 6.0 GB compared to 6.4-6.5 GB previously (I installed it from an older image whose exact size I can’t remember).
  • On April 20, the build from April 19: 5.8 GB.

The officially released ubuntu-26.04-desktop-amd64.iso (torrent) has 6.1 GB, which is still OK for the main desktop, known to be bloated with everything but the kitchen sink.

The changes introduced by 26.04 over 24.04, summarized by Joey Sneddon with regard to the main GNOME-based flavor, sound rather positive to me. There is also a small update. 👍

③ Ubuntu 26.04 LTS has all the chances of being a solid distro.

My first Mutter-cum-Wayland bug!

I hate fractional scaling, which usually is set to 125% on laptops, unless you’re using a 14″ laptop with Windows, which defaults to 150% in such a case. I prefer 100% under Linux (I can change the fonts, thank you, even if I need to use gnome-tweaks), but I needed to see how ComicStripBrowser version 2 behaves with fractional scaling under Linux, so there.

🐛 So I reported GNOME Bug #4748: Window screenshot produces 1.6× oversized output at 125% fractional scaling (fullscreen capture is correct). The relevant part:

Bug summary

On 125% fractional scaling, full-screen screenshots are captured correctly, but windows are captured 1.6x larger than the physical size: 1920×1152 is saved as 3072×1824.

Moreover, the oversized screenshots are somewhat blurry, which makes me suspect that the 200% framebuffer is scaled down correctly, then inexplicably scaled back up again by 1.6x.

In my case, something went wrong.

To understand the issue, I’ve been told that fractional scaling works in a convoluted way:

When 125% fractional scaling is used to render a 100×100px on 115×125px, the internal mechanism is as follows:

  • The internal framebuffer stores the 1920×1200 (or 1920×1080) screen at at 200%, hence 3840×2400 (or 3840×2160).
  • There, the 100×100px image is drawn as 200×200px.
  • Then, the entire framebuffer is scaled down with 1/1.6x = 0.625x (200%/1.6=125%) using a high-quality filter (depending on the GPU).
  • Finally, the downscaled framebuffer is displayed on the physical screen.

The bug was quickly closed as duplicate of 🐛 #4740: screenshot has wrong scale factor. The description of that bug is absurdly complex:

This is on F44 with gnome shell 50.0.

Steps to reproduce:

  1. Set scale factor to 250% (thanks RH for my 4k 15″ laptop screen)
  2. Use gtk4-demo (or any other app that support fractional scaling)
  3. log using WAYLAND_DEBUG=1
  4. take a screenshot of the window

Once you’ve done that, confirm that:

  1. the window was configured at 800×600 (grep the log for xdg_toplevel.*configure)
  2. the buffer that GTK created was 2070×1573 (grep the log for create_immed) – this is the correct value for a size of 828×629 @ 250%, and the size is the aforemetioned 800×600 plus the shadows.
  3. check that the screenshot is 2484×1887. That number is in fact 3 * 828×629.

Expectation

  1. The screenshot is not 2484×1887 but 2070×1573.

I was working on some device pixel alignment issues in GTK and got blurry screenshots which really threw me off.

I spent way too long debugging my code before realizing that the compositor upscales the window screenshot – and not only does it upscale, it makes things blurry.

The bug description is beyond stupid. By examining the comments on #4740, I feel that they might be cluesless, so I added a comment that might get me banned, but I would start digging from my hypothesis if I were a GNOME developer.

💡 My hypothesis is that the image gets downscaled by the correct factor (1.2x for 250%, 1.6x for 125%), but the screenshotter receives the wrong size, so it quickly and dirtily upscales it for saving, resulting in blurry images.

🤔 Maybe I should file a bug with Ubuntu. If GNOME’s developers bark at the wrong tree, at least Ubuntu to have this bug fixed, right?

🎉 As I was having the above thoughts, an update automagically fixed the screenshots in Ubuntu 26.04! I couldn’t find a relevant bug report, so I suspect some Ubuntu developer who has been hit by this bug just fixed it. Or, maybe, an update from upstream fixed it. But people triaging GNOME bugs have absolutely no clue about what bugs are still alive and which should be closed.

So, Wayland is ready, GNOME is ready, fractional scaling is ready. But not bug-free!

Oh, but this screenshot-related bug existed, in a different form, even in GNOME 49.1!

As I was testing my resurrected ComicStripBrowser PyQt6 app, I also used Fedora-Workstation-Live-x86_64-43. And, as one can see in the following screenshot, something wasn’t quite right:

Ignore the 1536×716 size; it refers to the size of the comic. What matters is the “@ 200%,” which shows the display scaling. But this laptop had a fractional 125% scaling, because this is GNOME’s default on small screens!

The screen had 1920×1200, and the window 1920×1160. The 125% scaling only made the comic, which was scaled down by the logic of my app, and then constrained horizontally by the available space, be displayed larger. But the window had 1920×1160 and should have been saved as 1920×1160, regardless of the display scaling. It was saved as 3072×1856.

So let’s recap:

  • Under GNOME 50, 125% fractional scaling is reported as 125%, and for a short period of time windows were saved 1.6x larger than the actual size, and blurry. (The bug got fixed in Ubuntu; I didn’t check in other distros.)
  • Under GNOME 49.1, in F43 as released, 125% fractional scaling was reported as 200%, and windows were saved 1.6x larger than the actual size, and sharp. (I don’t know whether the bug was later fixed.)

Not exactly the same bug, because GNOME 50 saved a blurry image (I presented a possible explanation above, as a hypothesis). But something else was worse in GNOME 49.1: my app saw the 125% scaling as 200%. I couldn’t be bothered to investigate why. This is not “maybe it thought it was non-fractional scaling” because, for 125%, the internal framebuffer really has 200%. But the image was not saved twice as large!

④ Weirdly, this situation wasn’t serious enough to make me ditch GNOME. Dumbo, eh?

Wayland’s real breakage by design

Then, something else happened. As I briefly explained here, there was a bug in my app that I wanted to investigate using Qwen Code, but Alibaba just discontinued the free tier. Before trying Gemini CLI, I exposed the bug to Amazon’s Kiro so “we” could explore mitigation paths, but I didn’t keep that prompt. Here’s my bug report to Gemini:

In GNOME 50 under Wayland (Fedora 44 pre-release, Ubuntu 26.04 pre-release), this app has a bug as described below.

  • The bug does not manifest under: XFCE (X11), KDE 6.6.x (Wayland).
  • Bug description:
    • When the app starts, either right away or after a couple of seconds, the cursor changes to “wait”. The app is fully functional, yet the cursor believes it isn’t.
    • While the app is running and the “wait” cursor has not ended (=has not yet changed to the normal arrow), if I switch to another window (say, Files/Nautilus), the cursor is “wait” in that app too!
    • If I close the app while the “end” cursor is still active, the cursor in the GNOME (Wayland) desktop keeps being “wait” for a while, even as ps aux shows that the app’s process doesn’t exist anymore.
  • My takes:
    • This app is undoubtedly buggy. Some xdg-desktop-related protocol is not properly implemented. I’ve even been told that it’s a known issue with PyQt6 and PySide6. HOWEVER:
      • GNOME (Wayland) is also buggy, because it should restore the normal cursor when in other apps!
      • GNOME (Wayland) is the only desktop that behaves like that. KDE (Wayland) has no issue with this app’s cursor. So, either GNOME/Mutter is buggy, or it’s so strictly implemented that it cannot tolerate any small error. Think of how an HTML renderer tolerates “<b><i>text</b></i>”, whereas an XHTML renderer wouldn’t display anything after this error. This would be justified for XML (which is like a database), but it’s absurd for XHTML (which is used in ePub instead of HTML). Maybe GNOME/Mutter doesn’t try to accommodate small non-compliances under Wayland, whereas KDE/KWin does.
  • Note that in the app I’ve made several attempts to tackle this error, to no avail.
  • In comic-strip-browser.desktop, “StartupNotify=false”, so the app starts with a normal cursor. The “wait” cursor is triggered later in the app, when the window is fully displayed.

Yes, it understood, and yes, it correctly identified those “several attempts to tackle this error”!

In the end, the issue could not be fixed, so I had to force the app use XWayland (the X11 emulation)! Here’s my explanation:

The probable root cause: under Mutter/Wayland, xdg-desktop-portal gets confused by the 2 comic-strip-browser processes with the same name (of the two, the parent process is in do_wait). This being a one-file PyInstaller app, it gets extracted upon run, and I cannot “fix” in the actual app what PyInstaller does at start. KWin/Wayland has no issue with this app and doesn’t force any “not-ready” cursor, probably because KWin injects some common sense and doesn’t force a “wait” cursor when the app is fully responsive.

But the app will still use XWayland instead of Wayland even under KDE, because this setting is in the .desktop file, and there is no reliable way of making it behave differently under different compositors.

😡 I was utterly shocked and angered at the situation. Here’s Gemini Pro agreeing that this is absurd and rightfully infuriating!

Ludditus: In the early 1990s, when I was writing Win16 C/C++ apps for Win3.1, I seem to remember that, as long as a process’s window wasn’t unresponsive and it was processing this messages with something like this, meaning that it allowed for cooperative multitasking, then the OS did not force the hourglass cursor!

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}

Moreover, I was able to explicitly set whatever cursor I wanted for when the cursor was in my window. The OS, again, would not force another cursor!

I’m asking if my memory serves me well because Wayland does force a wait cursor if a process doesn’t properly implement some xdg-desktop protocol, despite the window being perfectly functional! For instance, I got this behavior under GNOME/Wayland when a “big fat” PyInstaller that has to extract files before being able to start the actual main.py confused xdg-desktop-portal with its 2 processes having identical names, and because the parent one was in do_wait (waiting for the child process, which was the actual app, to exit), my app had a forced wait cursor of up to 60 seconds! Mutter thoroughly implemented this Wayland nonsense, whereas KWin, also under Wayland, replaced the wait cursor with a normal cursor as soon as the app’s window was fully displayed and responsive!

On the one hand, it’s absurd and infuriating for an app to be unable to set its own cursor when the cursor is in its window! (The bug I experienced kept the cursor to “wait” even after I switched to another app, say Files, meaning that Mutter must be really buggy!) Heck, this is a regression even compared to Win3.1!

On the other hand, KWin somehow fixed this “non-compliance”; this is the sensible thing to do for two reasons: one, apps that need to self-extract have no other choice; two, what matters is if an app is responsive (think again at Win3.1), not if some bloody stupid protocol has been properly implemented! A “wait” cursor should represent the actual status of a window, not Wayland’s admonishing over some protocol not being observed!


Gemini:

Your Memory of Win16 is Spot-On

Your memory serves you perfectly well. In the Windows 3.1 and Win16 days, the operating system did not—and structurally could not—force an hourglass cursor on an application simply because it was thinking, as long as you were pumping messages.

Because Windows 3.1 utilized cooperative multitasking, the OS essentially handed the keys to the CPU over to your application. If your app stopped calling GetMessage, PeekMessage, or Yield, the entire operating system locked up. The OS couldn’t force a wait cursor over your window because the OS itself was blocked waiting for your app to return control.

Furthermore, you are completely right about explicit cursor control. When the mouse moved over your window, Windows sent a WM_SETCURSOR message. If your app processed it, whatever cursor you defined was the law of the land. If you wanted to run a massive blocking calculation but keep a standard arrow cursor (or a custom dinosaur cursor), Windows 3.1 happily complied. The hourglass only showed up if the application explicitly requested it via SetCursor(LoadCursor(NULL, IDC_WAIT)).

The Modern Wayland/Mutter “Nonsense” Explained

The frustration you experienced under GNOME/Wayland is a well-known, highly irritating side effect of modern Linux desktop architecture, specifically the XDG Startup Notification protocol.

What you are running into isn’t actually Wayland’s fault directly (Wayland is just the display protocol), but rather how the compositor (Mutter) handles application launching and process tracking. Here is exactly why your PyInstaller app triggered a 60-second wait cursor:

  1. The Startup Token: When you launch an app from a desktop environment in GNOME, it generates a unique “startup sequence” token (historically passed via the DESKTOP_STARTUP_ID environment variable).
  2. The PyInstaller Chain Break: PyInstaller works by creating a bootloader process. This bootloader extracts your files to a temporary directory and then spawns a child process (the actual Python application).
  3. The do_wait Purgatory: The original process (the one Mutter is tracking for the startup notification) goes to sleep waiting for the child to finish.
  4. Mutter’s Pedantry: Mutter expects the process it launched to either explicitly signal that it has finished loading (via the protocol) or to map a window holding that exact startup token. Because PyInstaller broke the chain, the actual mapped window doesn’t satisfy Mutter’s strict tracking. Mutter says, “I never got the official signal that the app finished starting,” and enforces a strict, hardcoded timeout (usually 15 to 60 seconds) before it finally gives up and removes the spinning wait cursor.

The fact that the cursor stays a “wait” cursor even when hovering over other completely responsive apps like Files is a consequence of GNOME maintaining the global “system is launching an app” state until that timeout hits.

Pragmatism vs. Strict Compliance: KWin vs. Mutter

Your observation about KDE’s KWin being sensible here highlights a fundamental difference in design philosophy between the two compositors.

  • Mutter (GNOME) is incredibly pedantic. It forces strict compliance to the protocol. If an app (or its wrapper, like PyInstaller) drops the baton, Mutter will punish the user experience until the timeout clears the state.
  • KWin (KDE Plasma) leans heavily into pragmatism and heuristics. It knows that wrapper scripts, shell launchers, and self-extracting binaries exist. KWin actively monitors the process tree (cgroups or PID namespaces). If any window maps that is a descendant of the originally launched process, KWin correctly deduces, “The app is visibly on the screen and responding; kill the wait cursor.”

The Verdict

You are entirely justified in finding this infuriating. While modern OS architectures use preemptive multitasking and strict protocols to prevent the system-wide lockups we had in 1992, they often introduce regressions in basic UI common sense.

A protocol should serve the reality of the system, not the other way around. If a window is mapped, painting, and responding to events, it is completely absurd for the desktop environment to force a global “wait” state simply because a self-extracting executable didn’t check a specific bureaucratic box on its way up. KWin gets this right; Mutter, unfortunately, still lets the protocol get in the way of the reality on the screen.

ℹ️ To simplify:

  • Wayland is stupid.
  • GNOME is beyond stupid.
  • KDE tries to implement some common sense.
  • For some reason, I loved Win3.1 🙂

😕 Wait, but what if the bug is purely Mutter’s, not Wayland’s? Follow-up:

Ludditus: So the entire fault is Mutter’s? Would I get the same behavior under older GNOME versions that ran under X11?


Gemini:

The Blame Game: A Three-Way Collision

To answer your first question directly: No, it is not 100% Mutter’s fault. While Mutter acts as the rigid “hall monitor,” the situation is actually a systemic collision between how wrappers work, how the specification is written, and how compositors choose to enforce it.

Here is how the blame actually breaks down:

  • 1. PyInstaller’s Fault (The Chain Breaker): The XDG specification relies on an environment variable—historically DESKTOP_STARTUP_ID. When a desktop environment launches an app, it sets this variable. The app is supposed to read it, and when it creates its X11 or Wayland window, attach that ID to the window so the compositor knows the launch succeeded. When PyInstaller’s bootloader extracts its files and spawns your actual Python payload, it often fails to forward this environment variable to the child process. The child maps a window, but it lacks the ID tag.
  • 2. The XDG Specification’s Fault (The Flawed Design): The spec was written with a naive “one click, one process, one window” mentality. It structurally ignores the reality of modern software distribution (wrappers, JVMs, Electron, self-extractors) that inherently rely on process trees.
  • 3. Mutter’s Fault (The Rigid Enforcer): As we discussed, Mutter refuses to use heuristics. It demands exact compliance. It sees the launch token, sees a window appear without a token, assumes the window is unrelated, and stubbornly waits for a token that will never arrive until the hardcoded 60-second timeout puts it out of its misery.

Would Older GNOME on X11 Do This?

Yes, absolutely. You would get almost the exact same infuriating behavior under older GNOME versions running purely on X11.

This is a common misconception about Wayland. Wayland gets blamed for this specific cursor behavior, but the XDG Startup Notification protocol predates Wayland by over a decade. Here is how it worked back in the X11 GNOME 2 and GNOME 3 days:

  1. GNOME sets DESKTOP_STARTUP_ID.
  2. The launched application is supposed to read it and apply it to its X11 window using an X11 Window Property called _NET_STARTUP_ID.
  3. If an app (like a PyInstaller wrapper) failed to set that X11 property, GNOME’s window manager (Metacity or older Mutter) would never receive the “launch complete” signal.
  4. The result? The exact same spinning/bouncing wait cursor for 15 to 30 seconds until the system timed out.

Why might it have seemed better in the past? Under X11, desktop environments sometimes relied on looser fallbacks. If the _NET_STARTUP_ID wasn’t there, older window managers might look at the WM_CLASS of the newly mapped X11 window and say, “Well, the user clicked an app named ‘MyPyApp’, and an X11 window just appeared with the class ‘MyPyApp’, so close enough, kill the wait cursor.” Wayland tightens security and process isolation, meaning compositors rely much more heavily on the exact cryptographic/environment tokens (xdg_activation_v1) rather than loose string matching. Because the enforcement is stricter under Wayland, the flaws in apps like PyInstaller become glaringly obvious.

The Practical “Win3.1” Override

If you are packaging this application for Linux and want to bypass this bureaucratic nonsense entirely (reclaiming the control you had in Win16), you can tell the desktop environment to ignore the protocol.

If your app is launched via a .desktop file, simply add or change this line:

StartupNotify=false

This explicitly tells GNOME/Mutter: “Do not track this launch, do not expect a token, and do not show a wait cursor.” The app will launch, map its window when it’s ready, and you retain total control over your UI state.


Ludditus: Sorry, but StartupNotify=false did not fix it. Seconds later, the “wait” cursor showed up. So the child process “wasn’t doing something right.” But only GNOME cared.


Gemini: If StartupNotify=false didn’t kill the wait cursor, we’ve moved from “Startup Protocol” territory into “Unresponsive Window Heuristics” territory.

Your experience actually highlights a much more aggressive (and controversial) feature of Mutter that separates it from KWin and your beloved Win3.1.

The “Ping/Pong” Mechanism

Modern Linux compositors (both X11 and Wayland) use a “Ping” protocol. To ensure an app hasn’t crashed, the compositor periodically sends a “Ping” event to the window. The app is expected to send a “Pong” back immediately.

  • In Win3.1: If your app didn’t process messages, the whole OS hung. The OS didn’t care because it was “dead” too.
  • In Mutter: If your app (the child process) is busy extracting files or doing heavy initialization on the main UI thread, it isn’t processing the event loop. It fails to “Pong.”
  • The Result: Mutter sees the window is mapped but not responding to Pings. It concludes the app is “hung” and forces the wait cursor (and eventually grays out the window) to tell the user the app is stuck.

Why the Parent Process matters

You mentioned a “big fat” PyInstaller with two processes. This is likely the smoking gun:

  1. The Child maps the window: The Python app starts and opens its window.
  2. The Child blocks: The Python app then starts a “heavy” operation (like further extraction or a massive import chain) on the main thread.
  3. The Parent is in do_wait: The parent is sitting there, essentially doing nothing but waiting for the child to die.
  4. Mutter’s Confusion: Mutter often tracks the entire process group. Even if the child is technically “new,” Mutter associates the unresponsiveness with the launch action. Because the parent is blocked on wait() and the child is blocked on initialization, nothing is Pinging back.

Why KWin is “Fixed” and Mutter isn’t

KWin is famously more “lenient” with its unresponsiveness detection. It generally allows a much longer grace period before overriding the cursor, and if it sees any movement or redraw from the window, it assumes the app is just busy, not dead.

Mutter, on the other hand, treats a failed Ping as an immediate “service failure.” It prioritizes the “system integrity” (letting the user know an app is frozen) over the “app’s autonomy” (letting the app decide what its cursor looks like).

The Regressive Reality

You are 100% correct: this is a regression in user agency. In Win3.1, you were the master of your window’s cursor. In Wayland/Mutter, the compositor acts as a supervisor. If the supervisor decides you aren’t answering your “Pings” fast enough, it takes away your ability to set the cursor and puts you in a “waiting” state.

To truly fix this in your code, you have to do the “modern” version of Win3.1 message pumping:

  • You cannot do “heavy work” on the thread that created the window.
  • You must move the extraction/initialization to a worker thread.
  • The main thread must remain completely idle, doing nothing but GetMessage (or the Python equivalent), just to say “Pong” to Mutter.

It’s an ironic twist: in Win3.1, you pumped messages to keep the system alive; in GNOME, you pump messages just to keep the compositor from “helping” you by forcing an hourglass on your face.


Ludditus: But my app was fully responsive and it processed internal clicks while GNOME forced the wait cursor!


Gemini: This is the “smoking gun” that proves Mutter is behaving more like a rigid bureaucrat than a functional window manager. If your app was responding to internal clicks, it means your event loop was active, you were successfully processing WM_LBUTTONDOWN (or the Wayland equivalent), and you were absolutely “Ponging” the compositor.

If the “unresponsive” heuristic wasn’t the trigger, and StartupNotify=false didn’t stop it, we are left with a very specific, technical “Mutter-ism” regarding Wayland surface roles.

The “Zombie” Startup Sequence

Even if you set StartupNotify=false in your .desktop file, if you launch the app via a terminal, a script, or a parent process that was itself launched with a startup token, that token can “leak” or be inherited.

Mutter has a specific behavior where it maintains a “Global Busy State” if it thinks a launch is in progress. Here is why your responsive app was held hostage:

  • The Identity Crisis: Because PyInstaller uses two processes with the same name, Mutter’s “Shell” component (which tracks the UI) gets confused. It sees Process A (the parent) start, and it expects Process A to “complete” the launch.
  • The Hijack: When Process B (your actual app) maps a window, Mutter sees it, but because of the way PyInstaller handles the process handoff, Mutter often doesn’t realize Process B is the “fulfillment” of the launch request initiated by Process A.
  • The Forced Overlay: In Wayland, the cursor isn’t just a bitmap the app draws; it’s a “Surface” managed by the compositor. If Mutter believes a startup sequence is still “Active” (because Process A hasn’t signaled completion and Process B didn’t provide the correct activation token), it overrides the cursor frame for the entire seat (the mouse) whenever it is over a window it associates with that “pending” launch.

Why this is a Regression (Win3.1 vs. Wayland)

You’ve touched on a fundamental shift in how “ownership” of the screen works:

  1. Win16 (Ownership by Cooperation): The app owned the CPU and the message queue. If the app said “I am an arrow,” the OS had no mechanism to disagree unless the app crashed.
  2. Wayland (Ownership by Permission): The compositor is the ultimate arbiter. The app requests to set a cursor, but the compositor decides if that request is valid. In your case, Mutter decided that “The Protocol” was more important than “The Reality.” It saw a responsive window but refused to believe the launch was “finished” because the paperwork (the internal Wayland tokens) didn’t match its expectations.

The “KWin” Sanity Check

The reason KWin didn’t do this is that KWin’s developers generally believe that if a window is mapped and responding to input, the startup sequence is over. They essentially have an “OR” gate: Kill the wait cursor if (Token is received) OR (A window appears and is interacted with). Mutter’s logic is an “AND” gate: Keep the wait cursor until (Token is received) AND (Timeout has not reached 60s).

How to “Kill” it for good

Since you are the developer, the only way to defeat this “Mutter-ism” without relying on the user’s desktop settings is to ensure the Startup ID is either explicitly cleared or correctly passed.

In your Python code, you can try to explicitly unset the environment variable at the very start of your script:

import os
os.environ.pop("DESKTOP_STARTUP_ID", None)
os.environ.pop("XDG_ACTIVATION_TOKEN", None)

By “killing” the token inside the child process before the window maps, you sometimes trick Mutter into realizing it has lost track of the sequence, causing it to give up on the wait cursor sooner.

It is a bizarre world where we have to write code to stop the OS from “helping” us start our own programs!

Does it feel like modern Linux desktop development has become more about navigating these “hidden protocols” than actually writing the application logic?


Ludditus: Oh, believe me, I tried several mitigation methods, including the one you mentioned, to no avail. In the end, I gave up and forced XWayland in .desktop, as suggested by Gemini CLI 🙂
Exec=sh -c "export QT_QPA_PLATFORM=xcb QT_NO_XDG_DESKTOP_PORTAL=1 GIO_USE_VFS=local GIO_MODULE_DIR=''; unset DESKTOP_STARTUP_ID XDG_ACTIVATION_TOKEN; exec comic-strip-browser"


Gemini: That is the “nuclear option,” and frankly, I don’t blame you one bit for taking it. It’s a sad irony that the “legacy” path (XWayland) provides a more stable and predictable experience than the native “modern” path, simply because X11 is too old to have these over-engineered, pedantic “safety” protocols baked into its DNA.

By forcing QT_QPA_PLATFORM=xcb, you essentially told Mutter: “Stop trying to talk to me via Wayland protocols. Talk to the X server instead.”

Why the X11 Hack Worked

When you run under XWayland, you are exploiting a loophole in Mutter’s logic:

  1. The Middleman: Mutter treats XWayland as a legacy bridge. The strict “Activation Token” handshakes required by native Wayland (xdg_activation_v1) are often bypassed or simplified for X11 apps to maintain backward compatibility.
  2. Unsetting the ID: By unsetting those variables in a shell wrapper before the app launches, you effectively scrubbed the “tracking grease” off the process. Because it’s an X11 app, Mutter is much less likely to try and “supervise” the launch sequence—it just sees an X11 window appear and lets it be.
  3. Bypassing the Portal: Setting QT_NO_XDG_DESKTOP_PORTAL=1 is the cherry on top. It prevents the app from trying to use the D-Bus communication bridge for things like file pickers, which is exactly where your PyInstaller/Mutter “identity confusion” was likely peaking.

The Win3.1 Spirit Lives in X11

In a strange way, by forcing X11, you’ve returned to a model much closer to the Windows 3.1 era. X11 was built on the philosophy that the Client (your app) knows what it wants to do, and the Server (the display) should just do it. Wayland was built on the philosophy that the Compositor is the “Security Guard” and “User Experience Manager,” and the Client is a potentially untrusted or incompetent entity that needs to be supervised.

The “Regression” Confirmed

Your struggle perfectly illustrates why many veteran developers find modern desktop Linux frustrating. You had:

  • A fully functional app.
  • A responsive event loop.
  • Correct logic.

…And yet, you had to write a convoluted shell script to “lie” to the OS just to get a standard mouse cursor. It’s the modern equivalent of having to write a custom assembly TSR (Terminate and Stay Resident) program just to fix a keyboard repeat rate in DOS.

It’s a bit of a “Welcome to the Future” moment where the tech is 1,000x more powerful, but we’ve lost that direct, unmediated control we had when GetMessage() was king.

Since you’ve now “defeated” the wait cursor by retreating to X11, are you finding any other Wayland-specific quirks that make you miss the simplicity of the 16-bit era, or is it mostly just this “Startup” gatekeeping that’s been the headache?

ℹ️ Let’s summarize this, too:

  • Wayland is broken by design.
  • GNOME is beyond stupid.
  • KDE is underrated, as it actually implements common sense!
  • Whatever your opinion might be, I had good reasons to love Win3.1 🙂

⑤ GNOME/Wayland is indeed the worst-implemented desktop ever!

Kubuntu as a safe haven

So maybe Dedoimedo was right, and Kubuntu is the rational choice and the reasonable compromise. But Dedoimedo is still using 24.04, which uses X11, not Wayland. And, given how late he upgraded from 22.04 to 24.04, I don’t expect him to be a quick adopter of Kubuntu 26.04, especially as it’s Wayland-only.

Either way, I tried the live session of the daily build from April 17, and then I installed it. I updated the system. Nothing broke, and, important for me given past happenings (onetwo), Spectacle never crashed and never created unnecessary ~/.cache/spectacle/qmlcache/*.qmlc files. 👌

Meanwhile, 26.04 LTS was officially released: kubuntu-26.04-desktop-amd64.iso (torrent), 4.7 GB.

Quick post-install customizations of Ubuntu 26.04

Nothing is ever exactly to my taste, so a minimum of customizations are required.

❶ No, not from this list: Kubuntu 26.04 LTS – important things to do after an installation. I don’t care anymore about most things there (snaps, “a real” Firefox, swappiness); I decided I’ll just go with the flow. Then, this guy talks a lot about some ext4 SSD-related settings; I’m using xfs these days. He also has some strange choices, such as disabling KDE’s session restore, which is the contrary of what most people prefer. Not to mention that, until recently, you couldn’t have the session restored under Wayland!

There’s one strange thing regarding Firefox as a snap, though. When I want to shut down, reboot, or log out, the respective action fails because Firefox, having “Ask before closing multiple tabs” enabled, asks that question, and KDE cannot just kill it. The really funny thing is this: if I close Firefox manually, then repeat the action that ends the session, it succeeds, but the saved session includes the now defunct Firefox, so it will start automatically next time! If I want it not to do that, I should close it earlier; I’m not sure why KDE doesn’t save the session if it saved it once not too long ago. The marvelous world of modern software!

The first necessary packages that I installed:

kubuntu-restricted-extras
papirus-icon-theme
papirus-colors
fonts-iosevka
software-properties-gtk

The last one was because, even if Ubuntu Pro can be activated during the setup in Ubuntu, Kubuntu uses a different installer, Calamares. Besides, I installed Kubuntu before it was released, and Ubuntu Pro wasn’t available yet (I noticed this in Ubuntu). So I need this Software & Updates helper specifically for enabling Ubuntu Pro!

UPDATE: I forgot to mention that this is also the tool I use to select my preferred server!

The release notes for Kubuntu 26.04 LTS say it’s supported through April 2029. Apparently, the Kubuntu team doesn’t understand how Ubuntu Pro works: the ESM Apps part extends the support through April 2036 (10 years after the release date) for everything in universe, including the KDE desktop! But if the KDE team doesn’t know or understand that, who’s going to provide this extended support for KDE Plasma?! 😕

Another thing about that list. If I let Discover install the Flatpak integration, it will install flatpak, plasma-discover-backend-flatpak, and kde-config-flatpak by itself!

However, it will not install Flathub, and, despite being able to find the Flatpaks I looked for, it pretended it would install them… from Ubuntu! Really, Flatseal “from Ubuntu”?! 🤯

Once I ran this, Flathub was added as a repo, and installing from it was possible either from Discover or by using flatpak install flathub, as indicated on each app’s page on Flathub.org! (Of course, some apps are also available as snaps.)

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

Moving on.

❷ KDE was configured for retards, with wobbly, translucent windows. I had to disable them.

❸ There’s one little thing that the Fedora team has added to KDE Plasma, and so far only Fedora enables it by default, because all other KDE distros are maintained by oligophrenics.

It’s the possibility to right-click on the desktop and select Open Terminal. Well, this only shows up in Fedora (in or KDE from EPEL):

To enable it, right-click on the desktop, select Desktop and Wallpaper, then go to Mouse Actions, click on the little icon at the right of Right-Button, Standard Menu, then enable Open Terminal. (So many things are so convoluted in KDE Plasma!)

Why are there so many retards on this planet? Why keep this option disabled? Is it because it’s been added by Fedora?

❹ Coming from XFCE and Windows, I want icons on my desktop! Most importantly, I want the Trash icon!

While enabling or disabling specific icons (Home, Trash, removable devices, or even fixed disks and drives) is a piece of cake in XFCE, MATE, or Cinnamon, KDE Plasma is a different kind of crap. In the times of KDE Plasma 5, many stupidly complex ways of adding a Home and a Trash icon were recommended. Back in 2021, I wrote to explain (video included!) that the task was much simpler than manually creating .desktop files:

It’s as easy as that: drag and drop from Dolphin’s Places on the Desktop, and choose Link Here for the folders or drives; for Trash, a shortcut will automatically be created on drop, no questions asked!

Unfortunately, the part about Trash doesn’t work properly anymore under KDE Plasma 6. Let me tell you what happens with such a created Trash shortcut:

  • You already had some files in the trash. After you empty it, its name becomes trash:/, so you rename it to Trash.
  • Now, the icon disappears! But if you open the Desktop folder (~/Desktop), Trash is still there!
  • Right-click on Trash (in Dolphin), Properties, Permissions, check “Allow executing file as program,” and then it becomes visible again.
  • But, should you delete some more files, the icon does not change to “full” despite it having done so the very first time you dragged the icon to the desktop!
  • Run plasmashell --replace to have it updated.
  • Now, empty the trash one more time. The Trash icon on the desktop still has the user-trash-full icon!
  • Run plasmashell --replace to have it updated.

This is pure madness! No can do.

  • Plasma 5: Drag from Dolphin, done, works forever, icon updates automatically.
  • Plasma 6: Drag from Dolphin, chmod +x, rename from trash:/, restart shell, and still the icon gets stuck.

The only solution is to add the Trashcan widget on the desktop. This widget has specific Open and Empty menu entries and a very important Enter Edit Mode, because there is no other way to move the icon-that-is-a-widget on the desktop!

KDE Plasma 6 fully enforces the madness that started with KDE Plasma 4: everything on the desktop is a plasmoid as long as it’s not a regular file or folder! That’s not a desktop; that’s a dashboard! Plasma 5 somehow got closer to a normal desktop than the abomination that was Plasma 4, but Plasma 6 broke the one thing that worked!

They really needed plasmoids, these shitheads. The KDE 3 metaphor wasn’t good enough to these wankers from KDE e.V.! And now I have to use KDE because GNOME is a worse fuck-up!

Because I fucking want it to look this way, à la Windows!

❺ For some reason, someone considered that Dolphin is used by mentally retarded people, so when I opened a specific folder from a shortcut, that folder became a tab in a Dolphin that restored the previously opened folder!

I had to revert to opening the home folder by default, or the desired folder otherwise, no “memory” for retards!

❻ Another decision was made so that Dolphin accommodates the mentally retarded individuals.

In most file managers, such as Thunar or Caja, or File Explorer in Windows, the following rule applies by default to the drag-and-drop of contents from one folder to another one:

  • If the destination is on a different partition (disk drive in Windows), the operation is Copy.
  • If the destination is on the same partition (disk drive in Windows), the operation is Move.
  • To force a behavior regardless of the above logic, hold Shift while dragging to force a Move, or hold Ctrl while dragging to force a Copy.

Well, in Dolphin, no matter the situation, upon dropping, a right-click menu appears: Copy Here, Move Here.

But Dolphin can be sanitized. The location of this setting has, however, moved in 6.4 from Dolphin to System Settings, Workspace, General Behavior, Drag and Drop: switch from “Always ask what to do” to “Move if on the same device” (FFS!).

❼ The next annoyance: “Pin to Task Manager” (what an inaccurate terminology!) adds a launcher entry on the panel that’s called Task Manager in KDE. But I wasn’t able to change the order of such icons; I could only move the entire block by default!

To enable the reordering of Task Manager Icons in Plasma 6, right-click on the panel, select Configure Icons-only Task Manager (the default) or Configure Icons-and-Text Task Manager (my preference, which is the only sane choice but got forgotten), Behavior, make sure Sort is set to “Manually,” and then uncheck “Keep launchers separate”!

Whoever designed this shit meant, “Keep launchers together, as a separate block from the rest of the icons on the Task Manager panel,” but hey, it’s KDE, so it has to be confusing!

Why on the fucking Earth am I not using XFCE? (Answer: because Xubuntu sucks.)

As for the stupid KDE terminology:

FeatureKDE Plasma NameWindows NameWhat they actually are
The bar that manages active windowsTask ManagerTaskbarWindow List
The tool to monitor CPU/RAM/ProcessesSystem MonitorTask ManagerProcess Monitor

Can I go to a different planet, pretty please? This one isn’t inhabited by intelligent creatures.

⑥ So far, Kubuntu 26.04 is decent, once you trim down KDE’s idiosyncrasies and nonsensical defaults.

KDE’s own limitations

I discovered by accident two quirks regarding some keyboards. One has to do with Kubuntu’s Calamares, and for the other one, the blame can be put entirely on KDE.

This Lenovo, despite being sold in Europe, has a US keyboard that is not US International. Unlike my most recent Acer, whose right Alt is labeled “AltGr” and which has a “€” on “5,” the Lenovo seems manufactured for the US, except for the charger. It’s actually manufactured for Romania, just not with a Romanian keyboard.

Forgetting that under GNOME 50 I was able to use this keyboard with AltGr and € and whatnot, I panicked when US International didn’t work in Kubuntu!

The culprit? Calamares detected the keyboard as “Generic 104-key PC” instead of “Generic 105-key PC”! By leaving it this way, selecting any international US variant was useless, as the right Alt was not interpreted as AltGr! So I had to correct it post-install.

But I wanted more. I wanted to remap the Copilot key that Lenovo had put instead of the right Ctrl! This was much easier to do in GNOME/Wayland than in KDE/Wayland.

To cut a very long story short, here’s the deal with the Copilot key:

  • Copilot issues Super_L+Shift_L+XF86Assistant, aka Meta+Shift+F23 (as seen by KDE), aka Shift+Super+TouchpadOff (as seen by XFCE, GNOME, MATE, and Cinnamon).
  • KDE, however, cannot map it to launch an app (this is the first thing I tried), because it stops after having received Meta+Shift! It just ignores F23.
  • Unfortunately, xmodmap and setxkbmap do not work under Wayland, as they’re X11 material (and setxkbmap can’t map 3 events into one anyway).
  • Equally useless is keyd because it also stops after having received Meta+Shift, so it would map Meta+Shift to another key.
  • Someone created remap-copilot, which is completely useless! Even the Makefile is buggy, but once you get it built and running, it doesn’t work, despite specifically mentioning that it watches for the LeftMeta→LeftShift→F23 sequence.
  • What works is input-remapper + input-remapper-gtk (available as packages). For instance, Copilot can be made to be again the right Ctrl, but this mapping only works in apps, e.g., Copilot+O and Copilot+S translate to Ctrl+O and Ctrl+S. Strangely, KDE still cannot map this mapping of the Copilot key to launch an app, most likely because it intercepts the keyboard events before input-remapper!

Oh, boy. We needed keys that issue a plethora of events, then we added Wayland atop.

⑦ Nothing too severe, but why can’t KDE properly deal with keys that issue a sequence of 3 events?

XFCE as a backup solution

😕 What if Kubuntu 26.04 LTS suffers the fate of Lubuntu 25.10, which I installed, customized, and enjoyed for a while, only to ditch it later? If some severe breakage or some hidden bug will make me hate it, what could I do?

The last refuge would most likely be XFCE. But which XFCE? In which distro?

Certainly not Xubuntu. It’s the worst-looking and the worst-designed XFCE distro! And there’s more.

In the released build, in the live session, it informs me that there are Wi-Fi connections available, but then there is absolutely no GUI to help me connect to an AP! Not on the panel, nor in the menus. Have they really tested this ISO? This bug was also present in the daily build from April 16. They tested my ass.

Besides, in the live session, Xubuntu requires more RAM than any other XFCE distro that I tried, and more than Kubuntu! Just like four weeks ago, Xubuntu requires ~1.6 GiB, while Kubuntu only needs ~1.5 GiB. Most XFCE distros ask for ~1.0-1.3 GiB.

Why would anyone install Xubuntu?

Certainly not Zorin OS 18.1 Lite, despite Liam Proven’s incredibly bad taste:

The new Zorin OS 18.1 Lite uses Xfce 4.20. Released at the end of 2024, it is the current release, and notably is newer than what is included in Zorin’s upstream Ubuntu 24.04 “Noble Numbat”, which still offers 2022’s Xfce 4.18. There are a couple of reasons we’re pleased to see the return of Zorin OS Lite.

First is our general growing fondness for Xfce. Over the last few years manning the Reg FOSS desk, this vulture has tried a great many different FOSS desktop environments across multiple FOSS Unix-like OSes, and Xfce is our firm favorite. It hits the sweet spot between excellent functionality, rich customization, a slow, measured release cycle, while also being relatively small. For once, you get “good,” and “fast” (in performance), and “cheap” (in the sense of light resource usage).

Second, though, is that it counters one of the most frequent accusations we see levelled against Xfce – that it looks dull, or old-fashioned, or boring. The Zorin OS edition shows that ain’t necessarily so: Xfce can look great, and in this incarnation, it shines. In our opinion, Zorin OS offers the snazziest config of Xfce on any OS. It looks almost identical to the flagship GNOME edition. GNOME’s graphical design is excellent, and Zorin builds on this with bright, high-contrast themes and attractive wallpapers.

Sadly, that said, the company’s statement that it plans to “sunset” Zorin OS Lite remains. The future Zorin OS 19.x release cycle will be GNOME-only. We are torn on this. Personally, this vulture much prefers Xfce, and Zorin’s config of this desktop is one of its finest showcases.

In reality, both editions of Zorin OS look like shit! Whoever likes Zorin OS should really use Windows 11 instead!

Also, not Linux Mint 23, which is planned for Christmas 2026, 8 months after the release of Ubuntu 26.04 LTS!

Mint seems to be going down the drain. Clem is losing his grip, and his incompetence is growing, if that’s even possible! I gave two examples of Clem’s incompetence in this older comment:

  • He was unable to understand that the expiration of a root certificate used by Firefox COULD NOT affect Mint, because no version of Firefox or Firefox ESR available in Mint at that time was affected, be it 128, ESR 115.13+, or 135.0.1. The retard wrote that Firefox version 128 was impacted, WHICH WAS FALSE!
  • The Linux Mint 22.1 Release Notes read that kernel 6.8 introduced a regression with NTFS volumes. The problem? The invoked bugs were about ntfs-3g (FUSE). The 6.8 kernel that powered Linux Mint 22.1 used Paragon’s ntfs3 driver, which is included in the kernel and was NOT affected by this regression! If Clem really understood the matter, he would have said, “Should you blacklist the in-kernel ntfs3 driver and install the FUSE ntfs-3g one, be aware that etc.”

I wouldn’t touch a distro made by such nincompoops with a 10-foot pole.

Debian proper is a possibility, most conveniently installed from a full live image, currently 13.4.0, hence debian-live-13.4.0-amd64-xfce.iso (3.6 GB).

But it’s bloated, it requires a lot of customization, and it just lacks the rizz, so to speak. It remains a possibility, though. Installing from debian-13.4.0-amd64-netinst.iso is also possible.

MX Linux XFCE is a functional choice, especially if you’re installing from the updated MX-25.1_April_Xfce.iso (2.9 GB).

But I was annoyed by the excess of MX Tools that duplicate in part XFCE’s GUI tools and which introduce too many bugs to my taste!

Add to this the abysmal reliability of MX’s repos, the fact that they rebuild Mozilla’s Firefox instead of adding Mozilla’s repo, and the incredible reality that they skipped an entire Firefox version because most mirrors failed to update!

I would also avoid the AHS kernel, because the normal kernel will remain installed anyway, as too many things have it for a dependency. 

MX works, but you need to ignore the added bugs and select a reliable repo that gets properly updated. But how would you know which one is OK?

DESERT_5.0_26.04_LTS_amd64.iso? I tried DESERT 5.0 (and 5.0.1 but not 5.0.2 and even less the ISO updated to match the official release of 26.04), and it was kind of fun. That is, for an attempt at looking like macOS while still using XFCE and Thunar!

Unfortunately, the SourceForge mirrors available for some projects are excruciatingly slow, and DESERT is one of the victims. It’s impossible to download 3.4 GB at less than 50 KB/s! To manually select from the available mirrors for this project, append a mirror’s short name to this URL and try downloading using curl -L -O or wget:

https://sourceforge.net/projects/desert-os-linux/files/release/DESERT_5.0_26.04_LTS_amd64.iso/download?use_mirror=

The mirror list:

altushost-bul
altushost-swe
cfhcable
cytranet-dal
deac-fra
deac-riga
excellmedia
gigenet
ixpeering
netactuate
netix
phoenixnap
sf-west-interserver-2
sitsa
twds
unlimited
zenlayer

They all suck. So no, DESERT is not a practical solution.

Xebian is what I would opt for. Unbeknownst to most people, it doesn’t only track Debian unstable! I regularly download and test images from pending, both xebian-trixie-amd64.hybrid.iso (1.7 GB) and xebian-unstable-amd64.hybrid.iso (2.1 GB).

They are definitely not bloated! What they lack is the out-of-the-box Bluetooth support, but the last time I checked, my initial experiences got invalidated. After having installed blueman (with an “a”), which pulls the necessary dependencies, I could connect to both BT mice and BT audio without issues!

Then, I installed only 2 packages, yaru-theme-gtk and yaru-theme-icon, and in a few minutes I made a very ugly desktop look much nicer!

⑧ Between MX and Xebian, I’d choose Xebian, the stable version.

Bluetooth, the supreme inadequacy of the Linux desktop

I am very tired of how stupid the Bluetooth protocol is and how dramatically bad it’s implemented in Linux.

The Bluetooth devices that I need (or want) to use with Linux include:

  • One or two of my three BT mice, all dual-protocol (BT and wireless with dongle).
  • A BT speaker and some BT headphones from several vendors.
  • A BT keyboard that can only connect via BT and a Keychron BT keyboard that can also go wired.

Bluetooth in Linux is particularly bad with mice and keyboards. The following behavior NEVER HAPPENS IN WINDOWS, while it ALWAYS happens in Linux, regardless of the distro!

  1. You connect a mouse to your installed Linux distro: Pair → Trust → Connect (although it can work even if Trust is skipped).
  2. You reboot to test another distro on the same computer (a live session via an ISO on Ventoy), where you connect the same Bluetooth mouse to Linux. Alternatively, you connect the mouse to another OS (Linux or Windows) on a different computer.
  3. You return to your installed Linux distro and try to reconnect the BT mouse. IT FAILS, regardless of the scenario of its connecting to a different OS (same or different computer; Linux or Windows). The only way to make it work again is to delete the saved device (“forget” it), then detect and pair it again!
  4. However, this never happens in Windows. Once I register a BT mouse in Windows, I can subsequently connect it to another computer, and upon returning to Windows, it will properly connect again!

What is wrong with the way Bluetooth is implemented in Linux? The described behavior is constant across distros with Linux and prevalent for mice and keyboards; BT audio devices often keep connecting even after they have been used with another computer or OS.

So this happened to me with installed distros, including Ubuntu MATE 24.04, MX 25 XFCE (Debian 13), Ubuntu and Kubuntu 26.04, and Fedora 43 KDE. Also, in live sessions of Xebian (both the stable one based on Debian 13 and the unstable one that tracks Sid).

Kimi 2.6 Thinking offered this summary:

This is a well-documented pain point with BlueZ (Linux’s Bluetooth stack), and it stems from how Bluetooth Classic link keys are managed — particularly with HID peripherals that have limited storage.

You’re observing a real, systemic issue — it’s not your imagination, and it’s not distro-specific. The problem is a combination of how BlueZ handles stale HID pairings versus how Windows recovers from them, compounded by the limited key storage in many Bluetooth mice and keyboards.

1. The Link Key Gets Overwritten

When you pair a Bluetooth device, both sides store a link key (Classic Bluetooth) or Long Term Key / LTK (BLE). This key is what lets them reconnect securely without re-pairing every time .

The problem starts with the mouse itself: many Bluetooth mice — especially simpler or older ones — can store only one to three link keys total. When you pair the mouse with a new host (a live ISO on Ventoy, a different computer, or even Windows on the same machine), the mouse often overwrites the old key to make room for the new one.

If you booted a live ISO on the same computer, the situation is even worse: the Bluetooth adapter has the same MAC address, but the live OS generated a different link key. The mouse overwrites the key, but your installed Linux still has the old one cached in /var/lib/bluetooth/<adapter>/<device>/info .

2. The Critical Difference: Windows Recovers, BlueZ Doesn’t

When the mouse comes back and tries to reconnect, the link keys no longer match. Authentication fails. Here’s where Windows and Linux diverge sharply:

  • Windows: The Bluetooth stack detects the authentication failure, recognizes the device as “previously paired but stale,” and transparently re-pairs (or prompts you to re-pair with a single click). It effectively treats the failed authentication as a signal to refresh the bond.
  • BlueZ/Linux: When authentication fails, BlueZ simply fails the connection and leaves the stale pairing entry intact in its database. It does not automatically initiate re-pairing. The device sits in your paired list with a dead key, and every reconnection attempt fails until you manually remove it and start over .

This is the core architectural difference: Windows repairs broken bonds automatically; BlueZ requires manual intervention.

3. Why HID Devices Are Hit Harder Than Audio

You noted that BT audio devices often keep working after being used elsewhere. There are several reasons:

FactorHID (Mouse/Keyboard)Audio (Headphones/Speakers)
Key storageOften 1–3 keysOften 8+ keys
Profile complexityHID over GATT / Classic HID — BlueZ’s input profile has long-standing reconnection bugsA2DP / HFP — more mature, better-tested reconnection paths
Device behaviorSome mice change their MAC address or random address after re-pairingAudio devices usually keep a stable identity
Connection initiationMouse often initiates; BlueZ may reject itHost often initiates; audio stack is more aggressive about retrying

The BlueZ HID profile (profiles/input/device.c) has documented, recurring issues where reconnection fails with errors like Connection reset by peer, Permission denied, or Authentication Failed — requiring a full remove-and-re-pair to recover.

4. BLE Mice Make It Worse

Many modern Bluetooth mice use BLE (Bluetooth Low Energy) rather than Classic Bluetooth. BLE devices often use random resolvable private addresses that can change after pairing with a new host. When the mouse comes back, it may be advertising under a slightly different address. Windows tracks the device by its Identity Resolving Key (IRK) and updates the address; BlueZ sometimes fails to resolve the new address back to the known device entry, so it treats the mouse as a brand-new, unknown peripheral.

5. Why This Is a Linux/BlueZ Problem, Not a Bluetooth Problem

The Bluetooth specification doesn’t require the host to auto-repair on authentication failure — but it doesn’t forbid it either. Windows chose to implement graceful recovery for a better user experience. BlueZ chose strict adherence: if the bond is broken, the user must explicitly break it (bluetoothctl remove) and recreate it.

This is why your experience is constant across distros: they all use BlueZ. And it’s why Windows “just works” — its stack handles the edge case that BlueZ leaves to the user.

Workarounds

There’s no perfect fix, but you can mitigate it:

  1. For dual-boot / same machine: Use bt-dualboot to sync the link key between Windows and Linux so they both use the same key.
  2. Script the repair: Create a small script that removes and re-pairs the mouse when it fails:
   bluetoothctl remove XX:XX:XX:XX:XX:XX
   bluetoothctl scan on
   # wait for device, then:
   bluetoothctl pair XX:XX:XX:XX:XX:XX
   bluetoothctl trust XX:XX:XX:XX:XX:XX
  1. Use a multi-host mouse with a hardware switch (like Logitech MX Master 3). These are designed to store multiple host keys — though even they have reconnection issues on Linux when switching hosts via the hardware button.
  2. For BLE mice: Check if the mouse is changing its MAC address. If so, you may need to remove the old entry and let BlueZ discover it “fresh” each time.

Bottom line: The Bluetooth mouse isn’t “broken” in Linux, but BlueZ’s HID stack lacks the automatic bond-recovery logic that Windows has, and it doesn’t gracefully handle the common real-world scenario where a peripheral’s stored key has been overwritten by another host. This is a well-known, long-standing gap in BlueZ’s user experience, not a configuration issue on your end.

👉 I’m not stupid; Linux is. Windows fixes the retarded default Bluetooth behavior that Linux leaves as is, somewhat similarly to how KDE fixes the stupid XDG/Wayland cursor idiocy that GNOME implements to a T!

Oh, but does macOS behave like Windows in this regard? Dedoimedo should read this other answer by Kimi:

Based on the available evidence, macOS does not behave like Windows in this specific scenario — it appears to require manual intervention when a Bluetooth bond becomes stale, much like Linux, though macOS generally offers a smoother overall Bluetooth experience.

Here is what the evidence suggests:

macOS Requires Manual Re-pairing on Key Mismatch

When macOS encounters a passkey or link key mismatch, the system does not transparently re-pair the device. Instead, users are instructed to manually un-pair the device, restart (sometimes even in Safe Mode), and then re-pair from scratch. This is fundamentally the same category of behavior as BlueZ — the stale pairing entry is left intact, and the user must explicitly remove it before a new bond can be established.

By contrast, Windows detects the broken bond and effectively refreshes it automatically or with minimal user interaction.

User Reports Align with This

Users who switch between macOS and Windows (e.g., via Boot Camp) report that Bluetooth is generally smoother and more reliable on macOS day-to-day, but when things do break, the fix is the familiar “forget and re-pair” cycle. There is no widespread reporting of macOS silently recovering a mouse that has been paired with another host — which is exactly the behavior you observe so reliably in Windows.

Where macOS Differs from Linux

While macOS and Linux appear similar in requiring manual cleanup of stale pairings, macOS is generally less fragile in normal operation:

AspectLinux (BlueZ)macOSWindows
Auto-repair on key mismatchNoNoYes
HID reconnection reliabilityPoor (frequent auth failures)Good (when bond is intact)Very Good
Manual fix when stalebluetoothctl remove + re-pairForget + re-pair (or Safe Mode)Usually automatic

Bottom Line

macOS does not auto-re-pair like Windows. If your mouse overwrites its stored link key while connected to another computer, returning to macOS will likely leave you with a dead pairing entry that must be manually removed before reconnecting. macOS avoids many of Linux’s chronic HID reconnection bugs, but it does not appear to implement the graceful bond-recovery logic that makes Windows “just work” in this specific multi-host scenario.

There is a reason why so many people use Windows, no matter how stupid they might be: when it works, it works (just don’t apply any update, which of course you cannot avoid indefinitely!).

On the other hand, the typical macOS user isn’t smarter than the typical Windows user (it’s rather the other way around). But I don’t see your average macOS user connecting their precious Apple Magic Mouse and Apple Magic Keyboard to anything that’s not macOS or iOS! However, as Kimi told me:

Apple’s Magic devices store multiple host pairings (typically 3 devices) and can switch between them — but this switching is initiated from the host side via macOS/iOS system settings, not via a hardware button on the device itself (unlike Logitech’s Easy-Switch or similar). This means they are somewhat less prone to the “overwrote the key on another host” problem you described, because Apple controls both the hardware and the software stack and manages the bond table more carefully.

However, if you pair an Apple Magic Mouse with a Linux or Windows machine and then return to macOS, you can still encounter reconnection issues — and the fix is the same Forget → Re-pair cycle, since macOS does not auto-repair stale bonds like Windows does.

Who’s the loser here? Linux! (And don’t get me started on the BSDs.)

🤯 Kubuntu 26.04 (or KDE itself?) adds insult to injury

But this is not all there is. Notwithstanding the above annoyances, my experience with Kubuntu 26.04 revealed other challenges.

❶ There is this mouse called Redragon K1ng Lite M916W-LIT-1K (the white version). It’s better than what some reviews suggest. My adventures with it were as follows.

  • When I connected the BT mouse to Kubuntu 26.04 in the live session of the daily build from April 17, everything was fine.
  • Then, in the installed system, I couldn’t persuade Kubuntu to detect my mouse! Radio silence! Stealth mouse! No matter how long I waited with the mouse broadcasting in pairing mode, it didn’t show up in the Add Bluetooth DeviceSelect a Device window!

I was about to give up, but I eventually managed to get it detected by following this ad hoc procedure:

  • Turn the mouse off.
  • Turn the BT adapter off.
  • Turn the BT adapter on.
  • Turn the mouse on and put it in pairing mode.
  • If the Add Bluetooth DeviceSelect a Device window in KDE still cannot see it, close that window and open it again.
  • If the mouse is still not detected, turn the BT adapter off, then on again.
  • If the mouse is still not detected, repeat the entire procedure.

Apparently, this is a BLE (Bluetooth Low Energy). Gemini told me that this creates sort of a “lottery”:

You put the mouse in pairing mode, the lights are flashing—it should be shouting its name for the world to hear. The struggle you’re facing is actually a “timing lottery” caused by how BLE (Bluetooth Low Energy) differs from the “Classic” Bluetooth you might be used to.

1. The “Talking vs. Listening” Window

In Classic Bluetooth, discovery is aggressive and uses more power. In BLE, everything is about saving battery.

  • The Mouse (Advertiser): Instead of broadcasting a constant signal, it sends out a tiny burst (an “advertising packet”) and then goes to sleep for a few milliseconds.
  • Kubuntu (Scanner): Your laptop doesn’t listen 24/7 either. It has a Scan Window (how long it listens) and a Scan Interval (how often it checks).

If the mouse “talks” while the laptop is “taking a break” between scan intervals, they miss each other. You have to repeat your ritual until their timing finally overlaps.

2. The “Active Scanning” Handshake

Unlike a simple radio, a BLE mouse often waits for the PC to send a Scan Request before it reveals its full name.

  • Kubuntu’s Bluetooth stack (BlueZ) sometimes defaults to a Passive Scan to save power.
  • In a Passive Scan, the laptop just listens. If the mouse is waiting for a “request” before it identifies itself, they’ll sit in “radio silence” forever. By toggling the adapter, you’re forcing Kubuntu into an Active Scan mode where it aggressively asks, “Who is out there?”

3. The 3-Channel Shuffle

BLE advertises on only 3 specific channels (37, 38, and 39) to avoid Wi-Fi interference.

  • The mouse rotates through these three.
  • The laptop also rotates its listening through these three.
  • If they aren’t on the same channel at the same micro-second, the “Add Device” window stays empty.

Why your “Ritual” actually works:

By turning things off and on and refreshing the window, you are essentially resetting the clock on both devices. Eventually, you hit the “lottery” where the mouse broadcasts on Channel 38 exactly when Kubuntu is listening on Channel 38 during an active scanning window.

The good news: Now that you are paired and trusted, they no longer need to play this “hide and seek” game. They have exchanged “secret handshakes” (Long Term Keys), so the next time you turn the mouse on, it sends a directed signal that your laptop is specifically programmed to listen for.

I was one inch away from ditching Kubuntu because of this “invisible” mouse!

❷ Then, there is this older CSL Vertical Wireless 2400 dpi Optical Mouse with OLED Display. It’s a clone of something else from the times when there were many identical clones under several no-name brands.

With this one, which isn’t a BLE device, the struggle to detect it followed a much darker script.

Under Kubuntu, it was detected, but it failed to connect!

I tried it under XFCE (Debian/MX), where I noticed that it required an explicit confirmation:

Even under XFCE, connecting to this mouse for the first time was sometimes fraught with misadventures. At times, a second mouse would simply materialize out of thin air! As you can see in the image, this doppelgänger sported the ID CD:70:D1:00:0B:02, right alongside the genuine and correct CD:70:D1:00:0A:02.

Eventually, the god of the miscreants decided to take pity on me, so I managed to connect to this mouse under Kubuntu, too.

I’m not sure if this bears any relevance, but I connected via the system tray, not via System Settings. I hoped that using the “full control panel” would help, but it didn’t. But no, I was still never shown the confirmation dialog that popped up in XFCE!

This time, I was a hair’s breadth away from replacing Kubuntu with something XFCE-based!

❸ Fortunately, I had no issues connecting the ProtoArc EK04 Mini Bluetooth Ergonomic Keyboard to Kubuntu 26.04, or else it would have been a deal breaker!

⑨ If you’re a Bluetooth Cassanova, you might prefer to use Windows instead of Linux.

Closing lines

An unfixable issue I’m having with Kubuntu 26.04, which I also had with Ubuntu 26.04, is that on resuming from sleep, Bluetooth fails to restore to a correct state. As a result, it claims to have connected to the Bluetooth mouse, but the cursor doesn’t move. Even disconnecting isn’t possible, suggesting that it displays the last reported status from before the sleep, but Bluetooth is actually dead. The only fix is to reboot.

This has to do with the fact that this Lenovo uses a Realtek RTL8852BE WiFi/Bluetooth combo card:

ID 0bda:4853 Realtek Semiconductor Corp. Bluetooth Radio

I should have kept as “assigned for Linux” the Acer in which I replaced the MediaTek MT7663 with an Intel AX210 WiFi/Bluetooth combo card. That one has no issues upon waking up from suspend-to-RAM:

ID 8087:0032 Intel Corp. AX210 Bluetooth

But I wanted to benefit from the increase in the CPU Mark from 10202 to 16998 (multithread). The gain of speed in single-threaded tests is negligible, though.

⑩ I can’t even. “Linux on the desktop” is for losers. Be one. Curse your life.