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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
# Phase 2 — Become a Window Manager
---
## Step 2.1 — Open an Xlib display connection alongside raylib
Before `InitWindow()`, call `XOpenDisplay(NULL)` to get a `Display*`.
Store it globally. Get the root window with `DefaultRootWindow()`. After
the raylib loop exits, `XCloseDisplay()`.
Print the display name and root window ID to confirm.
**Verify:** The output prints something like `Display: :1, Root: 0x...`.
Raylib window still works as before.
---
## Step 2.2 — Register as the window manager (SubstructureRedirect)
After opening the display, call:
```c
XSelectInput(dpy, root,
SubstructureRedirectMask |
SubstructureNotifyMask |
StructureNotifyMask);
XSync(dpy, False);
```
Set a custom X error handler that catches `BadAccess` (another WM is
already running) and prints a clear message.
**Verify:** Running in Xephyr succeeds (no other WM). Running a second
instance prints "Another window manager is already running" and exits.
---
## Step 2.3 — Process X events in the raylib loop
Inside the raylib `while (!WindowShouldClose())` loop, add a non-blocking
X event drain:
```c
while (XPending(dpy) > 0) {
XEvent ev;
XNextEvent(dpy, &ev);
printf("Event: %d\n", ev.type);
}
```
**Verify:** `./bin/run.sh --clients` — launching `xeyes` or `xterm` into
`:1` prints `MapRequest`, `ConfigureRequest`, etc. to the terminal. The
clients don't appear yet (because we don't handle `MapRequest`).
---
## Step 2.4 — Handle MapRequest and ConfigureRequest (basic)
Add a simple event handler:
- **`MapRequest`** → call `XMapWindow(dpy, ev.xmaprequest.window)`.
- **`ConfigureRequest`** → honor the request by calling
`XConfigureWindow()` with the requested values.
**Verify:** `./bin/run.sh --clients` — `xeyes`, `xclock`, and `xterm` now
appear inside the Xephyr window. They're drawn by X directly (not
composited yet), floating on top of/beside the raylib window. You can type
in `xterm`.
---
## Step 2.5 — Track managed windows in a list
Create a simple dynamic array (or linked list) of `WmWindow` structs:
```c
typedef struct {
Window xwin;
int x, y;
unsigned int width, height;
bool mapped;
} WmWindow;
```
- On `MapRequest`: add the window to the list, then `XMapWindow`.
- On `UnmapNotify`: mark `mapped = false`.
- On `DestroyNotify`: remove from the list.
- On `ConfigureRequest`: update stored geometry, then `XConfigureWindow`.
Print the window list count on each change.
**Verify:** Spawn/close clients in `:1`. The log shows windows being added
and removed. Count matches what's visible.
|