🎉 Phase 7.1 — xdg-shell minimal validé runtime
Capture preuve : docs/phase7-1-xdg-toplevel.png — fenêtre 320x240 du
client externe positionnée à (60, 60) par le compositor (cascade par
défaut), avec bandes verticales arc-en-ciel + bordure noire 2px.
Différence visuelle vs phase 6.4 : la fenêtre est maintenant
positionnée par le compositor (pas plaquée à 0,0).
Modifications redox-wl-wayland-frontend :
- + dep wayland-protocols (feature server)
- xdg_wm_base global v5
- XdgSurfaceData { wl_surface, last_serial, acked_serial }
- XdgToplevelData { title, app_id }
- SurfaceData.xdg_pending_initial_configure : bloque l'affichage tant
que ack-configure pas reçu (sémantique xdg-shell standard)
- WaylandFrontend.next_xdg_serial : counter monotone serial
- WaylandFrontend.next_toplevel_index : cascade position +60 par fenêtre
- DEFAULT_TOPLEVEL_SIZE = 640x480 envoyé en initial configure
- Dispatch xdg_wm_base : GetXdgSurface, CreatePositioner (no-op),
Pong (no-op), Destroy (no-op)
- Dispatch xdg_positioner + xdg_popup : no-op (out of scope)
- Dispatch xdg_surface :
- GetToplevel → cascade pos + envoie xdg_toplevel.configure(640,480)
+ xdg_surface.configure(serial)
- AckConfigure(serial) → enregistre + débloque affichage
- Destroy → cache la surface
- Dispatch xdg_toplevel :
- SetTitle / SetAppId → stocke
- tout le reste ignoré (move, resize, maximized, ...)
redox-wl-test-client-shm adapté :
- + dep wayland-protocols (feature client)
- bind 3 globals : wl_compositor, wl_shm, xdg_wm_base
- Dispatch XdgWmBase::Event::Ping → pong (au cas où)
- Dispatch XdgSurface::Event::Configure → store serial
- Dispatch XdgToplevel::Event::Configure / Close → log
- Workflow runtime :
1. create_surface + get_xdg_surface + get_toplevel
2. set_title / set_app_id
3. surface.commit (initial empty)
4. attente Configure event (timeout 5s)
5. ack_configure(serial)
6. shm + buffer + attach + commit POST-ack
7. boucle 25s
8. destroy propre
Init submodule wayland-rs/wayland-protocols/protocols (XML files
gitlab.freedesktop.org/wayland/wayland-protocols).
Validation runtime QEMU complète :
[client] globals : compositor=true shm=true xdg_wm_base=true
[client] xdg_toplevel configure suggéré : 640x480
[client] initial configure reçu, serial=1
[client] ack_configure(1)
[client] buffer attach + damage + commit POST-ack
[comp] tick=30..450 surfaces=1 elapsed=1.2..18.2s
PNG capturée à T+14s : surface visible à (60,60), bandes RGB+jaune+
violet+orange comme attendu.
Critère de fin 7.1 validé : client xdg-shell crée toplevel, reçoit
configure, ack, commit, affiche via shm, sans panic serveur, 18s
stable, destroy propre.
Limitations connues : focus, cursor, move/resize, multi-client,
robustesse — sous-tickets 7.2-7.7.
Image Redox restaurée à boot Orbital normal.
docs/phase7-1-xdg-shell.md : compte-rendu complet, cycle de vie,
limitations, plan 7.2.
Leyoda 2026 – GPLv3
This commit is contained in:
parent
8a897d975d
commit
4bff319c7f
6 changed files with 600 additions and 36 deletions
202
docs/phase7-1-xdg-shell.md
Normal file
202
docs/phase7-1-xdg-shell.md
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
# Phase 7.1 — xdg-shell minimal
|
||||
|
||||
> Document produit le 2026-05-09 dans le cadre du plan directeur
|
||||
> `REDOX_COSMIC_XWAYLAND_RS_PLAN.md`.
|
||||
>
|
||||
> **Scope strict** validé par user :
|
||||
> - implémenter `xdg_wm_base`
|
||||
> - gérer `get_xdg_surface(wl_surface)`
|
||||
> - gérer `xdg_surface.get_toplevel`
|
||||
> - envoyer `configure` (xdg_toplevel + xdg_surface)
|
||||
> - recevoir `ack_configure`
|
||||
> - gérer `commit` après configure
|
||||
> - supporter `set_title` / `set_app_id` (stockés sans usage UI)
|
||||
> - destroy propre via `xdg_toplevel.destroy` / `xdg_surface.destroy`
|
||||
>
|
||||
> **Hors scope 7.1** : focus, cursor, move/resize, decorations,
|
||||
> multi-client avancé.
|
||||
|
||||
## Verdict
|
||||
|
||||
**✅ Cycle xdg-shell complet validé runtime.**
|
||||
|
||||
Capture preuve :  — fenêtre 320×240
|
||||
positionnée à `(60, 60)` par le compositor (cascade par défaut), avec
|
||||
bandes verticales arc-en-ciel + bordure noire 2px peintes par le client.
|
||||
|
||||
## Cycle de vie xdg-shell implémenté
|
||||
|
||||
```
|
||||
client compositor
|
||||
────── ──────────
|
||||
Connection::connect_to_env
|
||||
get_registry
|
||||
◄──── wl_compositor + wl_shm + xdg_wm_base
|
||||
advertised
|
||||
bind globals
|
||||
compositor.create_surface ────►
|
||||
SurfaceData { id: registry.create(),
|
||||
xdg_pending: false }
|
||||
wm_base.get_xdg_surface ────►
|
||||
XdgSurfaceData { wl_surface, serial: 0 }
|
||||
sd.xdg_pending_initial_configure = true
|
||||
xdg_surface.get_toplevel ────►
|
||||
XdgToplevelData::default()
|
||||
next_toplevel_index += 1
|
||||
surface.x = +60, surface.y = +60 (cascade)
|
||||
next_xdg_serial = 1
|
||||
◄──── xdg_toplevel.configure(640, 480, [])
|
||||
◄──── xdg_surface.configure(serial=1)
|
||||
────────────────────────────────────────
|
||||
toplevel.set_title(...) ────► data.title = Some(...)
|
||||
toplevel.set_app_id(...) ────► data.app_id = Some(...)
|
||||
xdg_surface.ack_configure(1)────► data.acked_serial = 1
|
||||
sd.xdg_pending_initial_configure = false
|
||||
shm.create_pool(fd, size) ────► ShmPool::new(fd) → mmap
|
||||
pool.create_buffer(...) ────► BufferData { pool, offset, w, h, ... }
|
||||
surface.attach(buffer) ────► sd.pending_buffer = Some(buf)
|
||||
surface.damage_buffer(...) ────► (no-op tracking 7.1)
|
||||
surface.commit ────►
|
||||
!xdg_pending → continue
|
||||
read shm pixels via mmap
|
||||
SurfaceBuffer::from_pixels(...)
|
||||
registry.modify_pending(id, |s|
|
||||
s.buffer = Some(sb); s.visible = true)
|
||||
registry.commit(id)
|
||||
registry.raise(id)
|
||||
|
||||
(toplevel.destroy) ────► no-op (wl_surface destroy fera le reste)
|
||||
(xdg_surface.destroy) ────► surface.visible = false; commit
|
||||
(surface.destroy) ────► registry.destroy(id)
|
||||
```
|
||||
|
||||
## Modifications apportées
|
||||
|
||||
### `redox-wl-wayland-frontend`
|
||||
|
||||
Ajout dep `wayland-protocols` (feature `server`).
|
||||
|
||||
Constants :
|
||||
- `XDG_WM_BASE_VERSION: u32 = 5`
|
||||
- `DEFAULT_TOPLEVEL_SIZE: (i32, i32) = (640, 480)`
|
||||
- `CASCADE_OFFSET: i32 = 60`
|
||||
|
||||
Nouveaux UserData :
|
||||
- `XdgSurfaceData { wl_surface, last_serial, acked_serial }`
|
||||
- `XdgToplevelData { title, app_id }`
|
||||
|
||||
Modif `SurfaceData` :
|
||||
- ajout `xdg_pending_initial_configure: Mutex<bool>` qui bloque l'affichage
|
||||
tant que pas ack-configure (sémantique xdg-shell standard)
|
||||
|
||||
Modif `WaylandFrontend` :
|
||||
- `next_xdg_serial: u32` (counter monotone pour les configure serials)
|
||||
- `next_toplevel_index: u32` (counter cascading)
|
||||
|
||||
Dispatch ajoutés :
|
||||
- `GlobalDispatch<XdgWmBase>` + `Dispatch<XdgWmBase>`
|
||||
- `Dispatch<XdgPositioner>` (no-op)
|
||||
- `Dispatch<XdgPopup>` (no-op)
|
||||
- `Dispatch<XdgSurface, Arc<XdgSurfaceData>>` :
|
||||
- `GetToplevel` → cascade position + envoie initial configure
|
||||
- `AckConfigure(serial)` → débloque affichage
|
||||
- `Destroy` → cache la surface
|
||||
- `Dispatch<XdgToplevel, Arc<XdgToplevelData>>` :
|
||||
- `SetTitle`/`SetAppId` → stocke
|
||||
- reste : ignoré (move, resize, set_*, etc.)
|
||||
|
||||
### `redox-wl-test-client-shm`
|
||||
|
||||
Ajout dep `wayland-protocols` (feature `client`).
|
||||
|
||||
Bind 3 globals : `wl_compositor`, `wl_shm`, `xdg_wm_base`.
|
||||
|
||||
Séquence runtime :
|
||||
1. `compositor.create_surface()`
|
||||
2. `wm_base.get_xdg_surface(&surface)`
|
||||
3. `xdg_surface.get_toplevel()`
|
||||
4. `toplevel.set_title("Phase 7.1 client")`
|
||||
5. `toplevel.set_app_id("redox.wl.test.client.shm")`
|
||||
6. `surface.commit()` — initial commit pour signaler "ready"
|
||||
7. Attente du `xdg_surface.configure(serial)` event (avec timeout 5s)
|
||||
8. `xdg_surface.ack_configure(serial)`
|
||||
9. `shm.create_pool(fd)` + `pool.create_buffer` + pattern ARGB
|
||||
10. `surface.attach(buffer)` + `damage_buffer` + `commit`
|
||||
11. Boucle 25s vivante
|
||||
12. `toplevel.destroy()` + `xdg_surface.destroy()` + `surface.destroy()`
|
||||
|
||||
Bonus : Dispatch sur `XdgWmBase::Event::Ping` répond `pong(serial)` (le
|
||||
compositor ne l'envoie pas en 7.1 mais c'est gratuit côté client).
|
||||
|
||||
## Preuve runtime
|
||||
|
||||
Logs serial QEMU complets :
|
||||
|
||||
```
|
||||
[client] connect to compositor
|
||||
[comp] CRTC pris
|
||||
[comp] Wayland socket : /tmp/redox-wl-comp.sock
|
||||
[client] globals : compositor=true shm=true xdg_wm_base=true
|
||||
[client] xdg_toplevel créé, attente initial configure
|
||||
[client] xdg_toplevel configure suggéré : 640x480
|
||||
[client] initial configure reçu, serial=1
|
||||
[client] ack_configure(1)
|
||||
[client] buffer attach + damage + commit POST-ack
|
||||
[comp] tick=30 surfaces=1 elapsed=1.2s
|
||||
... (compositeur stable 18s avec 1 surface) ...
|
||||
[comp] tick=450 surfaces=1 elapsed=18.2s
|
||||
```
|
||||
|
||||
Capture frame T+14s : fenêtre client à `(60, 60)`, bandes RGB+orange+jaune+
|
||||
violet visibles avec bordure noire.
|
||||
|
||||
## Limitations connues (à traiter en sous-tickets ultérieurs)
|
||||
|
||||
- **Pas de focus** → toutes les surfaces sont "actives", pas de keyboard
|
||||
enter/leave events. Phase 7.4.
|
||||
- **Pas de cursor visible** côté écran. Phase 7.3.
|
||||
- **Pas de move/resize interactifs** (xdg_toplevel.Move/Resize ignorés).
|
||||
Phase 7.7.
|
||||
- **Window geometry ignoré** (utilisé pour les decorations CSD que nous
|
||||
ne supportons pas).
|
||||
- **Multi-client non testé** (1 seul client en 7.1). Phase 7.6.
|
||||
- **Pas de validation des serials** : si un client envoie un mauvais
|
||||
ack_configure, on accepte sans broncher. À durcir en phase 7.5
|
||||
(robustesse).
|
||||
|
||||
## Critère de fin 7.1
|
||||
|
||||
> Un client Wayland externe qui utilise xdg-shell peut créer une fenêtre
|
||||
> toplevel visible, recevoir son configure, ack, commit, puis afficher
|
||||
> via shm sans panic serveur.
|
||||
|
||||
**✅ Validé.** Test runtime 18+ secondes, surface visible, aucun panic
|
||||
serveur ni client, destroy propre à la fin.
|
||||
|
||||
## Code
|
||||
|
||||
```
|
||||
crates/redox-wl-wayland-frontend/ # +220 lignes pour xdg-shell (5 Dispatch + helpers)
|
||||
└── Cargo.toml # + wayland-protocols/server
|
||||
|
||||
crates/redox-wl-test-client-shm/ # adapté entièrement à xdg-shell
|
||||
└── Cargo.toml # + wayland-protocols/client
|
||||
```
|
||||
|
||||
Submodule `wayland-rs/wayland-protocols/protocols/` initialisé via
|
||||
`git submodule update --init --depth 1`.
|
||||
|
||||
## Suite phase 7.2
|
||||
|
||||
`wl_seat` + `wl_pointer` + `wl_keyboard` :
|
||||
- Routage des events `InputBackend` vers la surface focalisée
|
||||
- Décision XKB (recommandation : `xkeysym` Rust pur, layout US uniquement
|
||||
au début ; xkbcommon C reportable)
|
||||
- Premier client qui réagit aux events keyboard
|
||||
- Tester via QEMU `sendkey` avec un client qui log les events reçus
|
||||
|
||||
Estimé 2 sessions.
|
||||
|
||||
---
|
||||
|
||||
*Fin du document de phase 7.1.*
|
||||
BIN
docs/phase7-1-xdg-toplevel.png
Normal file
BIN
docs/phase7-1-xdg-toplevel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Loading…
Add table
Add a link
Reference in a new issue