fix: a background app must not outlive the app that launched it

An app launched with `background: true` gets a real window from the moment it
starts, just hidden. Nothing ever took it down: when the app that launched it
closed, the child kept running with no way to reach it and no reason to be
there. On the dashboard the only sign was a running dot on a tile the user had
never lit up, and clicking that tile did nothing at all.

Three things were wrong, and all three had to go:

A window nobody has seen now dies with its launcher. UIWindow's close path
closes hidden children the closing app launched, keyed on a marker stamped at
creation. makeWindowVisible drops that marker the first time the window becomes
visible — showing itself with `puter.ui.showWindow()`, or the user showing it —
because from then on the window is the user's, and keeps running.

The dashboard tile is a real handle again. focusExistingAppWindow only routed
MINIMIZED windows through showWindow(); a hidden one fell through to
focusWindow(), which leaves it invisible while handing it the keyboard. With no
taskbar in dashboard mode the tile is the only handle on a background app, so
that click had nowhere else to go. It now asks whether the window is on screen
at all. The Files tab's row-click had the same one-line defect.

And a background instance can't take a tile from the user's own session: an
on-screen window wins, then a window the user has seen, then a hidden one.

Removing the child then hit a crash of its own: ExecService's `remove` handler
dereferenced the launcher's iframe to say goodbye, and the launcher was already
gone. Throwing there aborts jQuery's remove() itself, so the window stayed in
the DOM — running dot and all. That one also hit anyone closing a background app
from the taskbar after its launcher had closed.

The predicates behind all of this live in one helper, window_visibility.js, with
showWindow() reading the same `hidden, not minimized` rule it spelled out inline
before.
This commit is contained in:
Nariman Jelveh
2026-08-13 14:36:08 -07:00
parent 08f075d774
commit d18ea1adb5
8 changed files with 227 additions and 16 deletions
+5
View File
@@ -49,6 +49,11 @@ The app still appears in the taskbar, so the user can see it is running, show it
or close it, and it can show itself at any time with
[`puter.ui.showWindow()`](/UI/showWindow). Defaults to `false`.
A background app closes when the app that launched it closes: it was launched to
serve that app, and the user never saw it. Once it has been shown — by
[`puter.ui.showWindow()`](/UI/showWindow) or by the user, from the taskbar — it is
an ordinary window and keeps running on its own.
## Return value
A `Promise` that will resolve to an [`AppConnection`](/Objects/AppConnection) once the app is launched.