# Phase 5 — Window Lifecycle Polish --- ## Step 5.1 — Graceful close (WM_DELETE_WINDOW) When the user presses a keybind (e.g., `Mod4+Q`), check if the focused window supports `WM_DELETE_WINDOW` in its `WM_PROTOCOLS` property. If yes, send a `ClientMessage`. If no, call `XKillClient()`. Register the keybind with `XGrabKey()`. **Verify:** `Mod4+Q` closes `xterm` gracefully (it gets a chance to confirm). Force-kills uncooperative clients. --- ## Step 5.2 — Handle UnmapNotify and DestroyNotify properly On `UnmapNotify`: - Free the pixmap and texture. - Mark window as unmapped. - Destroy the damage object. On `DestroyNotify`: - Remove the window from the managed list entirely. - Clean up all resources. Handle re-mapping (a window that was unmapped then mapped again) by re-creating everything. **Verify:** Close and reopen clients repeatedly. No memory leaks (watch with `valgrind` or check texture count). No X errors. No stale windows in the compositor view. --- ## Step 5.3 — Manage pre-existing windows on startup After becoming the WM, call `XQueryTree()` to get all existing children of root. For each that has `map_state == IsViewable`, treat it as if we received a `MapRequest`: add to the list, set up pixmap, damage, texture. **Verify:** Start some clients in `:1` *before* the WM. Then start the WM. Pre-existing windows appear immediately in the composited view.