blob: 89f6a4563b3c7a5ec1c1dbff78b51d79370d4727 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# 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.
|