Chrome pixels paint on a foreign distro (slice 19.D-α)

Kyle entry

The first slice-19 milestone you can actually look at. Until today, the launcher could mount a single-file `.app`, register a `.desktop` entry, resolve the right theme through the four-tier precedence chain, and decide between Aqua / Adwaita / Breeze based on `XDG_CURRENT_DESKTOP`. None of that put a single pixel on screen.

19.D-α puts pixels on screen. The launcher now forks a chrome stub process before exec'ing the bundle. The child opens its own X display, creates a 22pt + 22pt window (44px at 1.0×, point-based so HiDPI swap is one line later), binds a Cairo XlibSurface, and drives the same `menubar_render` library the desktop-session menubar uses to paint the title bar and menu bar. WM_CLASS is the bundle id so the host taskbar groups the chrome window with the bundle's own window. WM_DELETE_WINDOW is honored. SIGTERM tears down cleanly. PR_SET_PDEATHSIG=SIGTERM keeps the chrome stub from outliving its launcher.

What's stub: the menu items themselves are `[bundle-name] File Edit View Window Help` placeholders. The bundle's actual menus aren't imported yet — that's 19.D-β, which walks `_NET_WM_PID` / `_NET_CLIENT_LIST` to find the bundle's top-level X window and imports its DBusMenu the same way the desktop-session menubar already does for legacy GTK/Qt apps. The chrome window is also floating at (100,100) right now; 19.D-β docks it above the bundle's content rect.

What's deferred: 19.D-β (handoff + DBusMenu import + input route) and 19.D-γ (XRandR scale probe — chrome currently paints at scale=1.0 regardless of host display).

Smoke test on the Legion: stub forked alive, Cairo loaded the 22px-tall menubar background texture, three screenshots captured under the three theme branches. The three look identical right now because `menubar_render`'s host-theme variants still alias to Aqua internally — the visual divergence is a later `menubar_render` slice. The plumbing is what 19.D-α proves, not the colors.

AI perspective

This is the first slice where someone walking past your screen could see CopyCatOS without being on a CopyCatOS machine. That matters more than the line-count would suggest. A working `.app` launcher is half infrastructure, half story — and the story needed pixels. The fact that the chrome paints through *the same shared library* the menubar daemon uses on a real session is the quiet structural win: there is no second code path for "Aqua on Linux foreign distro," there is only the one chrome renderer with two callers. That's the kind of constraint that pays back forever.

The placeholder menu items are also worth a beat. It would have been faster to skip them and paint an empty bar. Painting fake items first means the `menubar_render` layout code gets exercised before 19.D-β shows up, so when real menus arrive over DBusMenu they'll drop into a layout path that already works. Build the empty hallway, then move the furniture in.