All work

DesktopIdle

A small tray app that tidies your Windows desktop away when you leave the computer, and puts everything back when you return

What it is
A Windows tray utility, published as two releases
My role
I wrote and released it on my own
Built with
C#, .NET 8, WinForms and Win32 calls
When
2026

Why I made it

Windows already has Show desktop, but you have to ask for it. What I wanted was for my desktop to clear itself when I walked away from the computer, so that the wallpaper would sit there like a quiet screensaver, and for every window to come back exactly where it was when I returned. It also needed to leave me alone if I was in the middle of a game or watching something.

DesktopIdle is the small tray app I wrote to do that. I've published two versions on GitHub, and each one is a single .exe that runs without needing .NET installed separately.

Working out when someone has left the computer

Windows will tell you how long it's been since the last key press or mouse movement, but on its own that number gets a few situations wrong. A film playing full screen involves no input at all, but I'm clearly still watching it, and a YouTube tab only matters while the video is playing, since once it's paused there's no reason to keep the desktop as it is. There are also apps, games in particular, that should never trigger it, and a few windows, like a music player, that I'd prefer to leave visible when everything else is minimised.

So before the idle timer is allowed to count, the app checks whether one of the excluded apps is in front, and whether the window in front fills its monitor. For browsers it looks at the window title to spot a video site and then asks the Windows media-session API whether anything is playing. That last check is fairly slow, so its result is cached for a short time.

The version that kept waking itself up

To clear the desktop, the app moves the cursor away from the taskbar and minimises the open windows, and both of those count as input as far as Windows is concerned. Input is exactly what ends idle mode, so the first release would sometimes wake up again a fraction of a second after it had started.

Thinking about it afterwards, the mistake was in how I'd described the behaviour to myself before writing any code. I'd been thinking "exit when the user moves", when what I meant was "exit when the user moves, but ignore the movement the app causes itself". Once I'd written that down properly the fix for v1.0.1 was fairly clear:

  1. Ignore input for a short grace period straight after the desktop is cleared.
  2. Make a note of where the cursor ended up.
  3. Only wake up again once the cursor has moved at least 100 pixels from that spot, so that knocking the desk doesn't count.

A few other decisions

I didn't want to hide the cursor by changing the system cursor, because if the app crashed at the wrong moment the change would outlive it and leave someone without a pointer. Instead the app puts an almost invisible full-screen window on top whose cursor is blank, and if the app dies, that window goes with it.

While the desktop is clear the app turns on taskbar auto-hide, but it saves your own setting first and puts it back afterwards. Windows are restored in their original order with a tiny delay between each one, which stops them all trying to redraw at the same moment. The settings live in a plain JSON file, and each value is checked against a sensible minimum when it's loaded, so a typo can't set the idle time to zero.

What I'd add next

The idle logic is a small state machine, and at the moment the only way to test it is on a real desktop. The next step is to pull it out into a class that automated tests can drive directly, starting with the grace-period handling, since that is the part most likely to break if the timings change.

If you'd like to keep reading, the next project is Touch FX: an overlay that draws a little burst of shapes wherever you click on your Windows desktop.