diff options
| author | Adam Malczewski <[email protected]> | 2026-04-11 19:06:35 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-04-11 19:06:35 +0900 |
| commit | 93f50d20a021150a0b95242be0d5dd5cae9d0185 (patch) | |
| tree | 48054581d580974651260900d1ef79d370872952 /.rules/plan/phase-03-compositing.md | |
| download | winman-raylib-93f50d20a021150a0b95242be0d5dd5cae9d0185.tar.gz winman-raylib-93f50d20a021150a0b95242be0d5dd5cae9d0185.zip | |
plan and researchmain
Diffstat (limited to '.rules/plan/phase-03-compositing.md')
| -rw-r--r-- | .rules/plan/phase-03-compositing.md | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/.rules/plan/phase-03-compositing.md b/.rules/plan/phase-03-compositing.md new file mode 100644 index 0000000..a85d12b --- /dev/null +++ b/.rules/plan/phase-03-compositing.md @@ -0,0 +1,106 @@ +# Phase 3 — Compositing: Redirect & Capture Window Contents + +--- + +## Step 3.1 — Query and enable the Composite extension + +At startup (after becoming WM), call: + +```c +XCompositeQueryExtension(dpy, &composite_event, &composite_error); +XCompositeQueryVersion(dpy, &major, &minor); +XCompositeRedirectSubwindows(dpy, root, CompositeRedirectManual); +``` + +Print the extension version to confirm. + +**Verify:** Prints "Composite extension: 0.4" (or similar). Clients +launched into `:1` are now **invisible** (redirected to off-screen pixmaps +but nobody is painting them). This is expected — the WM is responsible for +compositing now. + +--- + +## Step 3.2 — Name window pixmaps + +When a window is mapped (in the `MapRequest` handler or after +`XMapWindow`), call: + +```c +Pixmap pixmap = XCompositeNameWindowPixmap(dpy, win->xwin); +``` + +Store the `Pixmap` in the `WmWindow` struct. On `ConfigureNotify` (resize), +free the old pixmap and re-obtain it. + +**Verify:** No visual change yet (windows are still invisible), but no X +errors are printed. Confirm pixmap handles are non-zero via log output. + +--- + +## Step 3.3 — Read pixmap into a raylib Texture (CPU copy path) + +For each mapped window with a valid pixmap: + +1. Call `XGetImage(dpy, pixmap, 0, 0, width, height, AllPlanes, ZPixmap)` + to read the pixel data. +2. Convert the BGRA data (X11 format) to RGBA. +3. Create a raylib `Image` from the buffer, then `LoadTextureFromImage()`. +4. Store the `Texture2D` in the `WmWindow` struct. + +In the raylib draw loop, draw each managed window's texture at its +position using `DrawTexture()`. + +**Verify:** `./bin/run.sh --clients` — `xeyes`, `xclock`, and `xterm` +appear as textured quads rendered by raylib on the dark blue background. +They are static snapshots (no live updates yet). The raylib window is the +compositor. + +--- + +## Step 3.4 — Enable the Damage extension for live updates + +At startup, query and enable Damage: + +```c +XDamageQueryExtension(dpy, &damage_event, &damage_error); +``` + +For each managed window, create a damage object: + +```c +win->damage = XDamageCreate(dpy, win->xwin, XDamageReportNonEmpty); +``` + +In the event loop, handle `DamageNotify`: + +```c +if (ev.type == damage_event + XDamageNotify) { + // mark the window dirty + win->dirty = true; +} +``` + +When a window is dirty, before drawing, re-read the pixmap via +`XGetImage`, update the texture with `UpdateTexture()`, then call +`XDamageSubtract(dpy, win->damage, None, None)`. + +**Verify:** `xeyes` follows your mouse cursor in real-time. `xclock` +ticks. Typing in `xterm` is visible immediately. This is a working (CPU- +copied) compositor. + +--- + +## Step 3.5 — Handle window stacking order + +Draw windows in the correct stacking order (bottom to top). Maintain the +list order to match X's stacking order. Use `XQueryTree()` at startup to +get the initial order, and update on `ConfigureNotify` with +`Above`/`Below` sibling fields, or re-query when the stack changes. + +Also handle `XRaiseWindow` / `XLowerWindow` requests via +`ConfigureRequest`. + +**Verify:** Overlapping windows draw in the correct order. Clicking +`xterm` (if focus-follows-click is wired) or manually calling +`DISPLAY=:1 xdotool windowraise <id>` changes the draw order. |
