6 min read
A desktop charm with real physics that costs nothing to run
It has to feel physical enough to be worth having, and cost so little that you never think about closing it. Those pull in opposite directions.
- Engineering
- Desktop apps
Dangle hangs a small charm on a string from the top of your screen. You can grab it, swing it and let go. That is the entire product.
The interesting part is that a thing like this has to clear two bars that pull in opposite directions. It has to feel physical enough to be worth having, and it has to cost so close to nothing that you never think about closing it. An ornament that makes your fan spin up gets uninstalled the same afternoon.
Here is how we got both.
The string is a real simulation, not an animation
The first version could have been a looping animation of a swinging charm. It would have looked fine in a screenshot and been obviously fake within two seconds of touching it, because the thing that makes a hanging object convincing is how it responds to you.
So the string is a Verlet simulation: a chain of points, each one remembering where it was last frame, with constraints keeping the segments at a fixed length. The charm at the bottom is heavy relative to the string, which is what produces the behaviour people recognise without being able to name it.
- Grab it and the string follows with a delay, because the points are catching up.
- Throw it and it keeps going, because release velocity comes from the actual movement of your cursor, not a preset.
- Toss it upward and the string goes slack, because there is nothing to pull the segments taut and gravity has not caught them yet.
- Let it be and it settles, because damping takes energy out every step.
None of those are special cases in the code. They fall out of the simulation, which is the main argument for doing it properly: the behaviours you did not think of are already there.
Fixed timestep, variable everything else
Physics that advances by however much time passed since the last frame will behave differently on a 60Hz display and a 120Hz one, and will explode entirely if the machine stalls for half a second. So the simulation runs at a fixed 120Hz step regardless of what the display is doing.
That decouples the two questions. How often we simulate is a physics decision. How often we draw is a performance decision. They no longer have to agree.
The thing that makes it free: stopping
This is the whole trick, and it is not clever. It is just discipline.
The render loop stops completely once the charm settles. Not slows down. Stops. When nothing is moving there is no frame to draw, so we do not draw one. A charm hanging still at the top of your screen costs nothing at all, because nothing is running.
The obvious problem with a perfectly still ornament is that it stops reading as a physical object and starts reading as an image someone pasted on your desktop. So every 6 to 14 seconds, at random, a tiny breeze wakes it for a few seconds and then lets it settle again.
That randomness matters more than it should. A perfectly regular twitch is legible as a timer within about a minute. An irregular one reads as a draught.
Clicks have to pass through, except when they do not
An overlay sitting above your windows that eats clicks is not a charm, it is an obstruction. But a charm you cannot grab is a picture.
So the overlay window ignores the mouse by default, and a small thread polls the cursor position, testing it against the hit circle the charm reports. The window accepts the mouse only while the cursor is actually over the charm. Everywhere else, clicks land in whatever is underneath, exactly as if the overlay were not there.
Polling is a deliberate choice, and it is rate-adaptive: roughly 20 times a second normally, rising to about 80 near the charm. Far away, precision does not matter and the extra checks would be waste. Close up, the difference between grabbing it and missing is a few pixels, so it is worth the samples.
When you let go, focus returns to the application you were using. Without that, every play with the charm would steal your keyboard and you would notice immediately.
Keeping the interface out of the hot path
The control window is React. The charm is not, and the physics state does not live in React at all.
Putting simulation state into component state is one of the easier performance mistakes to make, because it works fine in a demo. At 120 steps a second it means 120 re-renders a second of a tree that did not need to change. The physics lives outside, the canvas draws from it directly, and React only hears about it when something a person can see in the interface actually changes.
Charm artwork is rasterized once per size rather than re-drawn from vectors every frame, for the same reason. Work that produces an identical result every time is work you should do once.
What this adds up to
The charm is idle almost always, and idle genuinely means idle. It wakes for a few seconds when the breeze hits, or for as long as you are playing with it, then stops. There is no network access at any point, no account, and no analytics, so there is no background chatter either. Settings and custom charms are files on your own disk.
That last part was not a performance decision, but it has the same effect. Software that does not phone home has nothing to do when you are not using it.
Try it, or read it
Dangle runs on macOS and Windows, it is free, and the whole source is public.
The download and install steps are here, and the code is on
GitHub if you would rather read src/physics than
take our word for any of the above.
We build client software the same way we built this: at GM Software Labs we do AI automation, web and mobile products, and the occasional small thing that exists because it should.
Written by the team at GM Software Labs. We build AI automations, web and mobile products for businesses. See what we build.
Read next
How much a website actually costs in India
Ask five agencies and you get five ranges, all ending in “it depends”. Here is the version with actual numbers in it.
AI agents, chatbots and automations are not the same thing
Most disappointing AI projects are a case of buying one of these and needing another. Here is how to tell them apart before you spend anything.