# Phase 6.4 — Frontend Wayland : un client externe affiche ses pixels > Document produit le 2026-05-09 dans le cadre du plan directeur > `REDOX_COSMIC_XWAYLAND_RS_PLAN.md`. > > **Scope** : un client Wayland externe (process séparé, code Rust pur > via wayland-rs) se connecte au compositor binaire, lui envoie un > buffer shm peint, et le compositor l'affiche. ## Verdict **✅ Pipeline Wayland complet sur Redox, end-to-end, par-dessus notre stack `compositor-core` + `redox-wl-display` + `redox-wl-input`.** Capture preuve : ![](phase6-4-wayland-client-surface.png) — le pattern ARGB 320x240 visible dans le coin haut-gauche est écrit par le client externe et affiché par le compositor sur le display Redox. ## Architecture finale 6.4 ``` ┌──────────────────────────────────────┐ ┌─────────────────────────────┐ │ redox-wl-compositor (bin) │ │ redox-wl-test-client-shm │ │ │ │ (bin séparé) │ │ ┌────────────────┐ │ │ │ │ │ RedoxOutput │ │ │ - shm_open + pattern ARGB │ │ └────┬───────────┘ │ │ - wl_compositor │ │ │ Arc │ │ - wl_shm │ │ ▼ │ │ - wl_shm_pool.create │ │ ┌────────────────┐ │ │ - wl_buffer │ │ │ InputBackend │ │ │ - wl_surface.attach │ │ └────────────────┘ │ │ - wl_surface.commit │ │ │ │ │ │ ┌────────────────┐ │ └─────────────┬───────────────┘ │ │WaylandFrontend │ │ │ Unix socket │ │ - registry │ ◄────────────────┼──────────────────┘ + SCM_RIGHTS │ │ (compositor- │ │ │ │ core) │ │ │ │ - Display│ │ │ │ - Listener │ │ │ └────────┬───────┘ │ │ │ compose_into │ │ ▼ │ │ framebuffer Redox → écran │ └──────────────────────────────────────┘ ``` ## Globaux exposés | Global | Version | Comportement | |---|---|---| | `wl_compositor` | 5 | `create_surface` → `registry.create()` ; `create_region` no-op | | `wl_shm` | 1 | advertise `Argb8888` + `Xrgb8888` ; `create_pool(fd, size)` → mmap immédiat | | `wl_shm_pool` | — | `create_buffer` → `BufferData` (offset/w/h/stride/format) ; `resize` no-op (TODO) | | `wl_buffer` | — | (pas de request à traiter, juste destroy implicite) | | `wl_surface` | 5 | `attach`, `damage`/`damage_buffer` (no-op tracking 6.4), `commit`, `frame`, `destroy` | | `wl_callback` | — | utilisé pour `wl_surface.frame` ; `done` envoyé par `notify_frame_done` | | `wl_region` | — | no-op (pas d'input region utilisée) | ## Sémantique commit Wayland implémentée Quand un client envoie `wl_surface.commit` : 1. Récupération du `BufferData` attaché en pending (via `wl_surface.attach`) 2. Lecture des pixels du shm via `mmap` côté serveur 3. Création d'un `SurfaceBuffer` (Arc>) côté `compositor-core` 4. `registry.modify_pending(id, |s| s.buffer = Some(...))` 5. `registry.commit(id)` — pending → current 6. `registry.raise(id)` — politique simple : dernière surface commitée passe au top 7. Frame callbacks pending → queue globale, traité au `notify_frame_done` après le prochain present **Approche "copy on commit"** : on copie les pixels du shm vers un Vec owned. Plus simple que de garder une référence vivante au mmap qui peut être unmappé par le client à tout moment. Coût ≈ 320×240×4 = 300 KiB par commit pour notre client de test, négligeable. ## Validation runtime Configuration : ```toml # init.d/20_orbital → nowait VT=2 redox-wl-compositor # init.d/30_console → nowait redox-wl-test-client-shm ``` Le compositor démarre, expose le socket `/tmp/redox-wl-comp.sock`, le client a une boucle de connexion qui retry 50× × 100 ms et finit par se connecter quand le socket apparaît. Logs capturés via /scheme/debug → serial QEMU stdio : ``` [comp] Phase 6.4 — compositor Wayland démarrage [comp] display 1280x800, VT=3 [comp] CRTC pris [comp] Wayland socket : /tmp/redox-wl-comp.sock [client] connect to compositor [client] globals : compositor=true shm=true [client] shm créé, peint 320x240 ARGB [client] surface attach + damage + commit envoyés [comp] tick=30 surfaces=1 elapsed=1.2s ... [comp] tick=510 surfaces=1 elapsed=20.7s ← surface persiste 20s ``` ## Limitations / hors scope ### Pas de placement (xdg-shell absent) La surface du client est affichée à `(0, 0)` parce qu'aucun protocole de placement n'est implémenté. Pour des fenêtres positionnables / redimensionnables, il faudra `xdg_wm_base` + `xdg_toplevel` (phase 7 ou plus tard). ### Pas de damage tracking effectif `wl_surface.damage` et `damage_buffer` sont reçus mais ignorés. Chaque frame recompose tout. Pour 1-3 surfaces de petite taille c'est imperceptible ; à optimiser quand on aura beaucoup de surfaces. ### Pas de wl_buffer.release explicite Le `release` Wayland indique au client qu'il peut réutiliser un buffer. Notre approche copy-on-commit rend ce protocole inutile (on n'a plus besoin du shm après commit). Mais des clients sophistiqués pourraient attendre `release` avant d'écrire à nouveau — à vérifier au cas par cas. ### Pas de seat / input vers les clients `wl_seat`, `wl_keyboard`, `wl_pointer` ne sont pas exposés. Les events input sont seulement consommés côté compositor (pour Esc=quit). Phase 7 ajoutera la propagation des events vers la surface focalisée. ### Pas de subcompositor `wl_subcompositor` non exposé. Pas critique pour des clients simples. ## Code source ``` crates/redox-wl-wayland-frontend/ # lib (~430 lignes) ├── Cargo.toml └── src/lib.rs # WaylandFrontend, Dispatch impls crates/redox-wl-compositor/ # bin (~150 lignes) ├── Cargo.toml └── src/main.rs # boucle main display+input+frontend crates/redox-wl-test-client-shm/ # bin (~170 lignes) ├── Cargo.toml └── src/main.rs # client wayland-rs qui peint + commit ``` ## Suite phase 7 Si on veut un compositor utilisable au quotidien, il manque (par ordre de priorité) : 1. **xdg-shell** (`xdg_wm_base` + `xdg_toplevel` + `xdg_surface`) → placement, redimensionnement, fermeture propre, titres de fenêtres 2. **wl_seat + wl_keyboard + wl_pointer** → propager les events input vers la surface focalisée. Décision XKB à prendre (porter libxkbcommon / impl Rust pur / strings minimales). 3. **Curseur software** → afficher le pointeur souris à l'écran (le compositor en a déjà la position via InputBackend, mais ne le dessine pas) 4. **Gestion focus + raise on click** → utiliser hit_test + wl_seat.keyboard_enter/leave events 5. **Damage tracking effectif** → réduire le coût de composition 6. **Clipboard** → wl_data_device_manager 7. **Multiple clients simultanés**, fermeture propre, recover sur crash client Estimé phase 7 complète : 5-8 sessions. --- *Fin du document de phase 6.4.*