XScreenSaver 5.45

XScreenSaver 5.45 is out now, including iOS and Android.

Second release this month! The previous release came out on March 20th, and now it's only March 283rd.

  • New hacks, covid19, headroom, sphereeversion and beats.
  • Shader updates to hypertorus.
  • No more image-loading pause in glslideshow.
  • BSOD supports GNOME.
  • Image loaders support SVG.
  • macOS: Fixed text loading on 10.15.
  • X11: xscreensaver-systemd now allows video players to request that the screen not blank.
  • X11: Glade → GtkBuilder.
  • Android: These hacks work now: carousel, juggler3d, molecule, photopile, polyominoes.
  • Various bug fixes.

I only personally wrote two savers since the plague began. Usually my business going poorly results in more savers, but not this time.

I've wanted to make a Max Headroom screen saver for years, but -- and this is shocking to me -- I could not find a 3D model of Max's head anywhere on the interwebs. Then finally one day I found one! And it was great! Really faithful, and even a reasonable number of polygons. But the guy who made it won't let me use it. I even offered to pay.

So finally I said fuck it, I guess we get Skull Headroom. Maybe this being out there will give someone the incentive to make me a real Max model. Do you have the skill to make one? Or do you have the tech to scan a 3D model from MP4s of the TV show? Lemme know. I very much look forward to replacing the skull.


    Thanks very much to Martin Lucina for leading the way on the systemd integration. I hope that this results in me getting a lot less email.

    For decades, the traditional way for a video player to temporarily inhibit the screen saver was to have a heartbeat command that ran "xscreensaver-command -deactivate" once a minute while the video was playing, and ceased when the video was paused or stopped. The reason to do it as a heartbeat rather than a toggle is so that the player fails SAFE -- if the player exits abnormally, the heart stops beating, and screen saving and locking resumes.

    "Fail safe" is just the most basic of all basic engineering techniques. I shouldn't even have to say this out loud.

    These days, the popular apps try to inhibit blanking by talking to "systemd". The design of the systemd method easily and trivially allows an app to inhibit the screen saver, crash, and then never un-inhibit it, so now your screen will never blank again.

    Furthermore, since the systemd method uses cookies to ensure that only the app that sent "inhibit" can send the matching "uninhibit", simply re-launching the crashed video player does not fix the problem.

    "Did IQs just drop sharply while I was away?" -- Ellen Ripley

    So here's what we're dealing with now, with the various apps you might use to play video on Linux at the end of 2020:

    • Firefox, Chrome, Chromium:
      If they crash or are killed while playing, they leave the screen saver permanently inhibited. They need signal handlers.

      If systemd's sd_bus_creds_get_pid() worked, I could work around this, but it doesn't so I can't.

    • Firefox, Chromium, MPV:
      Playing audio-only inhibits screen blanking. This is horrible. Playing audio should prevent your machine from going to sleep, but it should not prevent your screen from blanking or locking.

    • MPlayer:
      I can't get this weird WinAmp clone to play video at all (it plays them as audio) so who knows what it does.

    • VLC:
      The only one that appears to do everything right!


    There hasn't been much progress recently on the remaining systemic Android bugs. I could use some help with that from anyone with Android experience. The bugs are listed in detail in android/README, but an overview:

    • Rotation is wonky (on some devices?)
    • Deprecation warnings about android.preference, MediaColumns, MediaStore, etc.
    • Grabbing an image of the screen doesn't work.
    • Rendering text into pixmaps doesn't work. Affects 4 savers.
    • Rendering text into textures doesn't work, possibly because of the above, or because retrieving the GL_TEXTURE_MATRIX doesn't work. Affects 24 savers.
    • Retrieving GL_MODELVIEW_MATRIX doesn't work. Affects 7 savers.
    • Pixmap masks don't work. Affects 6 savers.
    • Complex polygon fills don't work. Affects 4 savers.
    • Alpha blending doesn't seem to work. Affects 3 savers.

Two Minutes Hate, Apple Edition:

    I'm still running macOS 10.14.6 because I'm not a crazy person, and guess what! That means that I can no longer install a development version of xscreensaver on my own damned phone! My phone is running iOS 14.2 but the most recent Xcode that I can install on my Mac is 11.3.1, and they won't talk to each other.

    I think that this also means that I barely dodged the bullet of not being able to do a build for distribution in the App Store at all. You can't submit builds that were made against the "Simulator" target, they have to be against a real, physical device. Fortunately my iPad is ancient and the latest iOS released for it is 12.4.5, so I was able to do my build against that.

    All of this also means that these macOS builds are still x86, since my version of Xcode won't emit M1 code. So if you're running this on the new fancy, you'll need Rosetta 2 installed. (I tried to make it so that the dialog nagging you about that will pop up when you run the installer, instead of it waiting until the first time a screen saver is launched, but I'm not sure if that worked. Let me know.)

    I tested image loading and text loading (phosphor, etc.) on both 10.15 and 11.0.1 and it worked for me, but I've had people complain about that with the previous release, so lemme know about that, too.

Make that Four Minutes Hate:

    5.45 Binary Rejected
    Guideline 1.1 - Safety - Objectionable Content

    We found that your app includes content or concepts that some users may find upsetting, offensive, or otherwise objectionable.

    Specifically, your entertainment or gaming app inappropriately references the COVID-19 pandemic in the metadata or binary. Entertainment or gaming apps that directly or indirectly reference the COVID-19 pandemic in any way are not appropriate for the App Store.

    Next Steps

    While your app's current content or concept is not appropriate for the App Store, we would welcome a new app from you in alignment with our App Store Review Guidelines that is not focused on or related to the COVID-19 pandemic.


    For additional information regarding Apple's response to the COVID-19 pandemic, please refer to the Ensuring the Credibility of Health & Safety Information update on the Apple Developer website.

    Please see attached screenshots for details.

    These attachments may display potentially objectionable content, such as nudity, pornography, and profanity.


    I tried renaming it to "Co____9" and changing the description to "This is fine", hoping that spinning the wheel would get me a different reviewer from whatever third world call center handles such things, but that trick didn't work. So no iOS COVID for you.

Tags: , , , , , , , ,

49 Responses:

  1. frandroid says:

    The app I work on was also blocked by the App store due to their COVID filter, and we were able to appeal the decision by explaining how we were not sharing information about the disease, but about government policy around it (our app helps people migrate to Canada). Telling them that it's a screensaver of the molecule and makes no claim nor advocacy about the disease might help get that through?

  2. GhostInAJar says:

    I've used macs almost exclusively since I bought my first Mac+ at my college bookstore - am I crazy to think it's a good time to jump ship? I can't upgrade my computer anymore or all my existing software will stop working. I can barely control what happens with my files anymore.

    I built a PC to play games on last year, and at least it seems you have a choice on what you want to do with your computer there.

    • dzm says:

      "I can't upgrade my computer anymore or all my existing software will stop working."
      I understand your fear, but this is factually wrong. I am writing this to you on a computer built on the M1 chip. I have had 0 compatibility problems with x86/"Intel" software running on this machine. Rosetta 2 is surprisingly robust and performant. All the x86 software I was using on a 2017 MBPro is working better under Rosetta 2 than it was on that 2017.

      The problems I am seeing are to be expected from a new platform being rolled out. The GPU and driver have some interesting gaps in feature coverage, but these issues are being worked on by Apple in software updates (most notable are stability problems with full-screen graphics unless VSync is enabled, and supporting multi-stream video for older 4K monitors).

  3. jwz says:

    Yes, you have successfully discovered the only extant Max Headroom model. That's the guy who said no.

  4. Line Noise says:

    I, too, have been looking for a decent Max Headroom model (most are really, really bad) to use in a digital assistant project (if I'm gonna have a digital assistant I want the OG digital assistant!). If I ever get a job in a VFX studio again I'll definitely be having a quiet chat to some modellers, riggers and texture artists.

    I really appreciate your continuing support of Linux given the current clusterfuck that is modern Linux desktop environments. I've been running XScreensaver since my SGI Irix days on real, honest to god, X terminals.

    I won't go into the horrible hacks I've had to do to disable XScreensaver when I'm in a Zoom call. I didn't know about the systemd support. I might look at that.

    • jwz says:


      If you're using Zoom in a browser that will definitely work. I don't know what their standalone app does, since their Linux version only exists for x86 and I've got a Pi. So I'd be curious to know what it does, if anything. Maybe run strings on the binary and look for "org.freedesktop.ScreenSaver".

      • Line Noise says:


        ❯ strings zoom | grep ScreenSaver

        It looks like it should be aware of screensavers. I will dig deeper. Thanks for the tip!

        • jwz says:

          My guess would be that Zoom is a copy of Chromium with their web app baked in, plus their surveillance rootkit. Kill and restart xscreensaver-systemd with -verbose, then launch Zoom, and see what xscreensaver-systemd says. Things to test:

          - Start video should send "inhibit"
          - Stop/pause video should send "uninhibit"
          - Quit while video playing should send "uninhibit"
          - Killing it from the shell while video playing should send "uninhibit" (but probably doesn't)

          • Andrew Klossner says:

            My guess would be that Zoom is a copy of Chromium with their web app baked in

            That would have made sense: package it up in Electron. I downloaded the zoom_amd64.deb package and took a look. It appears to be a native app using Qt, and it's aware of Wayland.

  5. pakraticus says:

    Freedesktop.org defined a saver suspend protocol without a fail safe and systemd blindly implemented it.

    I haven't gone near freedesktop.org crap since a Google Summer of Code destroyed X session save.
    Anyone care to give pointers on where to begin arguing "Inhibit requires a timeout value so the design may be fail safe. Once implemented the default without timeout should be phased out. And maybe the correct response to 'Inhibit forever' is 'This is how you uninstall the screensaver.'"

    Thank you! This explains the "WTF won't it autolock anymore."
    Because the only consistent way for Chrome to save tabs for restart is 'killall -9 chrome'

    • jwz says:

      Adding a timeout is a stupid non-solution. The only sane way to do this is as a heartbeat. It doesn't matter whether that heartbeat is the old way (fork a program once a minute) or some new way (e.g. send a ping to some new systemd protocol once a minute). The point is it must be a heartbeat, not a toggle.

      My preferred solution would be for every video player to implement a heartbeat command that ran either xscreensaver-command or xdg-screensaver which does the same thing.

      But that's not going to happen, so the simplest solution is for the systemd developers to make sd_bus_creds_get_pid() work. Because if xscreensaver-systemd can get the pid of the process calling "inhibit" then it can detect when that pid has died and auto-uninhibit. The code's already in there.

      • pakraticus says:

        I agree, heartbeat is the right approach.
        And I agree with your preferred protocol. Although I won't argue with folks with a dbus fetish.
        And I won't get anywhere arguing for a heartbeat with idiots that insist "The app can uninhibit on crash."
        My crazy idea...
        They may not flinch at "I want an inhibit with timeout so I can provide a fail safe with heartbeat."
        They then may flinch at "Hey, shouldn't inhibit without a timeout have a fail safe too?"

        And sd_bus_creds_get_pid() will fail when the app is in a snap.
        And enough distributions are shoving crap like Chromium into snaps.

        • pakraticus says:

          Bleah... "They then may not flinch at 'Hey, shouldn't inhibit without a timeout have a fail safe too?'"

        • jf says:

          Actually the heartbeat method is not needed, although it does have a certain nice simplicity to it. The logind inhibitor handles it in a different way, by transferring a fifo to the inhibiting process. The inhibitor gets cancelled when the fifo triggers POLLHUP, either by the process calling close() manually or when process death causes all its fds to close automatically. That effectively implements a similar failsafe.

          The FDO protocol isn't designed like this unfortunately but it appears you can get it to have similar behavior with some dbus maneuvering.

          • Alan says:

            The FIFO technique works for processes that crash, but not so much processes that hang or are intentionally suspended. Heartbeats/renewable leases are the correct answer.

            • jf says:

              The FIFO technique with the optional timeout allows for that. It's a matter of design consideration on the app's part if the inhibit should persist when the process hangs or gets SIGINT. For example a maintenance task that consumes a lot of CPU but is required to complete before a suspend/hibernate happens would probably not want to have its inhibit ignored just because it missed a heartbeat. The FIFO technique with the timeout allows you to choose if it does or not, whereas sticking with just the heartbeat method will limit you only to the one option.

    • Martin Lucina says:

      > Freedesktop.org defined a saver suspend protocol without a fail safe and systemd blindly implemented it.

      Actually, no. The crap design of the FDO saver suspend protocol and derivatives has nothing to do with systemd.

      There are two protocols implemented in xscreensaver-systemd:

      1. "Inhibitor Locks" [1], which make "activate the screensaver on system suspend, deactivate-or-show-password-dialog on system resume" work. This spec was invented by the systemd folks, and has a very nice fail-safe solution through passing the caller (xscreensaver-systemd) a file descriptor over DBUS, so if we (the xscreensaver-systemd process) die, the fd gets closed and the inhibitor lock gets dropped.

      2. The FDO screensaver spec you mentioned, which we (xscreensaver-systemd) implement and has no such fail-safe if the caller dies.

      We might be able to fix (2) if sd_bus_creds_get_pid() actually worked on a received message, but it doesn't, at least on Debian 10.

      [1]: https://www.freedesktop.org/wiki/Software/systemd/inhibit/

    • Zygo says:

      I had no idea any of that systemd fuckery was happening. This means I was not insane for whipping up a daemon a decade ago that does two things:

      1. Monitor raw input from HID input devices. Filter out noise events like accelerometers and non-click non-scroll mouse events.
      2. If there's no human for N minutes, run xscreensaver-command -lock. If that doesn't work then kill the X server to force a new login ("I said, 'lock the screen,' asshole").

      Looking at the commit timelines, it appears I started accidentally working around this bug about 2 years before it happened in freedesktop.org. As much as I like to retroactively predict the future, the reality is we needed specific behavior, and the possibility of any other behavior would be a high-severity bug all by itself. Somewhere around 2010 all the adults left the Linux desktop design room, and we knew that if we tried to integrate with the shitstorm that was coming from upstream, we would be fixing it at least once a year assuming we were aware of the bugs before they hurt us. We rolled our own, put it in a place where freedesktop.org and systemd can't mess with it, and it has been working so well that until today I didn't notice a tire fire that has been burning for years now (our screens lock no matter how many times Chromium crashes, even if an invisible advertisement fires up a media player).

      Full disclosure: I live and work with a cat. Unlocked keyboards without human hands above them are not acceptable for any reason. No exceptions. Yes I have to tap the shift key every few minutes while watching a video or on a call, because if I don't, it's "gerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrytyyyyyyyyyyyyyyyyy [36 pages redacted] yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyhnp" every damn time. On TV-like setups I run with no screensaver at all, but I can do that because they have no keyboard heated, cat-shaped, pocket-coil-mattress bed on them.

  6. meerkatmcr says:

    For information, mplayer can be configured to send a heartbeat command in the traditional manner.

    I have my install of it set up to run xscreensaver-command -deactivate as the heartbeat, and this works fine.

    I have no idea if can integrate with systemd to do things the New Stupid Way, though, since the machine it's on does not use systemd.

    • jwz says:

      This sounds like you got mplayer to show videos, which I was not able to accomplish!

      • meerkatmcr says:

        It's always Just Worked for me for playing video, for values of "Just Worked" appropriate for someone running Gentoo. I don't recall any special weirdness being needed to make it work.

        I don't think I've ever tried it on any other distro, however.

        If it's any help, it reports its version as "MPlayer 1.4-10.2.0", which looks like some Gentoo-specific patching onto upstream version 1.4, from April 2019.

        To cause the heartbeat command to be run, create a file at ~/.mplayer/config containing

        heartbeat-cmd='xscreensaver-command -deactivate >/dev/null 2>&1'

        which is what I have in my working setup.

        Per their manual, using a command of the form mplayer -heartbeat-cmd "xscreensaver-command -deactivate" $FILE to play $FILE should run the heartbeat command too, though I have not personally tested that it works.

        I have no reason to suppose that won't work for something non-Gentoo (assuming you can persuade it to work at all), but again I have not tested vanilla version 1.4 to find out.

        • jwz says:

          This extremely stale joke left over from the early 90s is all I see when I try to play a video with mplayer on Rasbian 10.4 or 10.6:

          • meerkatmcr says:

            Oh, wow... I think I was better off compiling it without the GUI support, in that case. I've always wondered whether it was worth the bother, but I wonder no more.

            I can't say anything useful about what Raspbian might have done to break MPlayer, I'm afraid, being as how the only thing I've ever used Raspbian for is the firmware updater package. The method the Pi website tells you to use to do that without the official updater did a whole lot of nothing, so I had to.

            However one of my working installs of MPlayer is on a Pi 4, so it's not entirely incapable of running on a Pi.

            MPlayer usually says something at least vaguely helpful about what it's up to if run from the command line, so that might at least tell you what stage of the process has imploded.

          • k3ninho says:

            Is there any chance MPlayer is configured to use the Pi's MPEG 2/4 hardware acceleration and you've not unlocked their keys in boot.txt ??

            (I would assume you've paid for the secret database numbers that let you use this Pi hardware for its intended purpose, but gotta check.)

            Those who would trade a few bytes of device-unique serial number for temporary unlocking of hardware capability can do so: here.


            • Carlos says:

              To clarify:

              h.264 video codec support in hardware is always available on all models of the Pi.

              On the Pi 4, MPEG-2 and VC-1 can be done in software, so no codec license is required.

              On the Pi 3 and earlier, you need an additional license to enable the hardware decode of MPEG-2 or VC-1 (they're separate licenses).


            • jwz says:

              I just installed and ran the thing in their repo, that's it. Because my goal was not "make mplayer work" but "see how mplayer behaves for random users". That question has been answered to my satisfaction.

  7. Jim says:

    Do any of your modules produce strong proofs of useful work?

    • jwz says:

      No, and never, because distributed-work "screensavers" are and have always been a stupid idea. Want to participate in a project like that? Run it in the background with "nice". A screen saver related to such a distributed task should only be a visualization of the current state, not the thing doing actual computation.

      • dcapacitor says:

        I get why it doesn't really make sense from an architectural standpoint for a screensaver to do the work - separation of concerns - but are there other reasons beyond that why distributed-work screensavers are a stupid idea?

  8. jf says:

    Using signal handlers isn't foolproof, that method will still fail if the process receives SIGSTOP or SIGKILL. Realistically the most reliable way to do this is to have some process tracking somewhere that removes the inhibit when the application requesting is killed or loses connection to the display server.

    • jwz says:

      True, which is why "make sd_bus_creds_get_pid() work" is the easiest solution, since "redesign this shitty API" is not really on the table.

      • jf says:

        So what you probably want to do there is use a tracking object and then use sd_bus_track_add_sender to have dbus track if/when the peer gets disconnected from the session bus for you, and drop the inhibitor on that condition. (gnome's screensaver thing does the equivalent of this) In any unix it's usually racy and unreliable to try to read procfs entries for pids of processes that you didn't start, you need some kind of additional tracking mechanism which is what the dbus name tracking is for.

  9. badc0ffee says:

    I think if you build with a target of "Any iOS device", you should be fine? We build our app from a headless Mac Mini with no iOS devices attached, and can submit to the store.

    I think you'll be able to get by for a while yet with Xcode 11.3.1, but of course there are no guarantees (current minimum is 10, and before that it was 6 or 7). But you don't need to depend on that old iPad for your build, just rapid on-device testing/debugging. Even if you lose the iPad you can still publish to TestFlight for on-device testing on newer devices like your iPhone.

  10. I'm not surprised that systemd did an half-assed thing but I don't really see the reason why nor why a lot of apps switched to it, meanwhile wayland folks made an idle-inhibit API that quite works with it being linked to the window.

    I think an heartbeat would still be a better choice as this way a frozen app doesn't ends up locking it inhibited but in a good shell/multiplexer force-quitting a frozen client is possible and I think having the option of knowing what is preventing the idling is a good option to have (ie. browsers keeping the heartbeat but not playing anything).

  11. Walex says:

    «don't really see the reason why nor why a lot of apps switched to it»

    The UNIX system architecture has a huge, huge, huge, weak point: while cooperation among "related" processes is very easy and useful, cooperation among "unrelated" processes is very awkward. What our "jwz" is describing is an issue related to cooperation among "unrelated" processes (the screensaver process and whatever other processes are started after it), and his solution is the classic UNIXy one to achieve such cooperation via signals and/or the filesystem tree.

    DBUS and SystemD are crap (because Poettering seems to me a highly skilled hacker with a considerable lack of insight as to system architecture) attempts to create a universal mechanism to provide communication and control of "unrelated" processes, and it has become popular because there is a huge demand for that type of communication and control and not many easy ways to achieve it.

    • jwz says:

      In case it wasn't clear, I don't have a problem with systemd per se. (I mean, the API is pretty baroque, but whatever.) The "PrepareForSleep" mechanism by which the OS, via systemd, informs xscreensaver that a suspend is immanent and allows us to do some shutdown actions seems to work just fine. It's the unrelated "org.freedesktop.ScreenSaver" API, which is also built on top of systemd, which is garbage. A non-garbage API built on top of systemd for preventing screen blanking could hypothetically exist. It happens not to.

      • Walex says:

        «A non-garbage API built on top of systemd for preventing screen blanking could hypothetically exist. It happens not to.»

        Indeed, because DBUS and SystemD, however crap, could provide suitably well designed mechanisms for "unrelated" processes.
        But it is a problem of culture: both DBUS and SystemD are part of a culture that encourages crap hacks, that's why "happens not to". I remember your well justified rants about 'gnome-screensaver', the issue there was part of the same culture (largely centered in the FreeDesktop.org "conspiracy" to microsoftize GNU/Linux) of crap hacks.

        I guess everybody following this blog is familiar with this humorous "misdescription" of the GNOME (and FreeDesktop.org) development style:


  12. May I be so impudent to as for a feature?

    Could you add automatic loading of .pdb files from, say, /usr/share/xscreensaver/molecule in the "molecule" plugin?

    A friend of mine has a small collection of beautiful pdb files, which I wanted to package as a Linux package which users would be able to install and get different molecules on their screen. The easiest way to accomplish that would be to just copy all the pdbs to some dedicated directory.

    Would that be too much of a request?

    • jwz says:

      It already does that, the "-molecule" option can point to a .pdb file or to a directory. However, it's not a sure thing that any given PDB file will work; xscreensaver can only parse simple ones.

      • nameless internet troll says:

        That's not what I meant. I am aware of the option, and of the gui field in the xscreensaver-demo.

        But I do not want to parse xscreensaver's config files in my post-install script. I would like to just place the pdbs into a specific directory and have them picked up automatically.

        Sure, we will test them for compatibility.

        • jwz says:

          So pick a directory, tell it what that is, and then it will load them? I don't understand what you're asking.

          • nameless internet troll says:

            I do not want to "tell" the directory manually. I want to have a specially dedicated directory, where I could copy (install) the pdb files and _not_ do any further telling given that "molecule" is already selected as the default plugin.

            The "user story" is the following:

            1)the user discovers xscreensaver, plays with the few plugins from the GUI, and likes the "molecule" plugin.
            2)he/she runs whatever GUI package manager is available on their distro and finds the "xscreensaver-molecule-beautifulpdbs" and installs it.
            3)the new pdb appear in the screensaver with no more interaction at all

            The point here is to make (3) work, because _I_ can choose whatever directory I want, but I have no way to tell the user which one it is, apart from writing it into the package description, which nobody reads.

            • jwz says:

              I think you're saying "changing the preferences is too hard, so make the default be what I want them to be instead." No, I'm not going to do that. When someone downloads your collection of PDBs they should just point the saver at wherever they installed them. If that's too complicated for them, they probably shouldn't be installing packages they downloaded from the internet in the first place.

  13. Rick Richardson says:

    I use glslideshow on Fedora 32. 5.45 gives photo->briefly all white->photo, etc. Had to dnf downgrade to 5.44, which works: photo->photo->photo, etc.

Leave a Reply

Your email address will not be published. But if you provide a fake email address, I will likely assume that you are a troll, and not publish your comment.

You may use these HTML tags and attributes: <a href="" title=""> <b> <blockquote cite=""> <code> <em> <i> <s> <strike> <strong> <img src="" width="" height="" style=""> <iframe src="" class=""> <video src="" class="" controls="" loop="" muted="" autoplay="" playsinline=""> <div class=""> <blink> <tt> <u>, or *italics*.