4 bugs identifiĂ©s et corrigĂ©s grĂące au client tiers : - ESC mangĂ©e par le compositor au lieu d'ĂȘtre forwardĂ©e (raccourci compo dĂ©placĂ© sur Ctrl+Q + tracking ctrl_held) - Cursor accumulait les deltas PS/2 hors-Ă©cran (ajout screen_w/h + clamp_cursor + set_screen_size au boot) - Keycode envoyĂ© scancode+8 au lieu d'evdev brut (bug racine â le +8 est entre evdev et X11, pas entre PS/2 et evdev) - Event loop client ne tolĂ©rait pas Interrupted/BrokenPipe transitoires â FAIL au lieu de PASS sur sortie normale (5e adaptation Redox cĂŽtĂ© client, upstream-compatible) Plus : tick log compo passĂ© en debug! pour silencer la console sĂ©rie, run-qemu.sh durci (check /dev/fuse, IMAGE/REDOXFS overridables). 6/6 checkpoints 13.1 verts. Bugs secondaires (curseur stuck en bas-droite, ion page fault sur broken pipe d'un job background) listĂ©s dans le doc pour follow-up en 13.1.c. Leyoda 2026 â GPLv3
298 lines
12 KiB
Markdown
298 lines
12 KiB
Markdown
# Phase 13.1.b â Observation runtime du client tiers `simple_window`
|
||
|
||
> Document produit le 2026-05-16, suite de
|
||
> [`phase13-1-real-client-simple-window.md`](phase13-1-real-client-simple-window.md).
|
||
>
|
||
> **Scope** : observer le comportement runtime de
|
||
> `redox-wl-real-client-simple-window` (port Redox de l'exemple upstream
|
||
> wayland-rs) face au compositor, consigner les déviations vs l'attendu,
|
||
> appliquer les fixes nécessaires cÎté **compositor uniquement** (le code
|
||
> client reste verbatim upstream sauf 4 adaptations Redox documentées en 13.1).
|
||
>
|
||
> **Verdict** : â
**13.1.b validĂ©e** â 6/6 checkpoints OK aprĂšs application
|
||
> de 3 fixes ciblés.
|
||
|
||
## Verdict
|
||
|
||
```
|
||
[real-client] simple_window port Redox â start
|
||
[real-client] entering event loop
|
||
INFO redox_wl_wayland_frontend: focus change: None â Some(SurfaceId(0))
|
||
[real-client] ESC â exit
|
||
[real-client] loop exited cleanly
|
||
[real-client] PASS
|
||
INFO redox_wl_wayland_frontend: garbage_collect: client ⊠â destroyed 1 surfaces
|
||
```
|
||
|
||
Le client tiers, **non écrit par nous**, traverse le pipeline complet :
|
||
connexion socket, bind des globals, création toplevel, commit buffer
|
||
shm, focus auto-grant à la création de surface, réception `wl_keyboard.key`
|
||
sur ESC, sortie propre, garbage collection cÎté compositor.
|
||
|
||
## Checklist 6/6 (cf. `phase13-1-real-client-simple-window.md:137-153`)
|
||
|
||
| # | VĂ©rif | RĂ©sultat | Ăvidence |
|
||
|---|---|---|---|
|
||
| 1 | Connexion socket | â
| `[real-client] entering event loop` |
|
||
| 2 | Globals reçus (`wl_compositor`, `wl_shm`, `wl_seat`, `xdg_wm_base`) | â
| Surface créée (sinon le client échouerait au bind) |
|
||
| 3 | Configure initial ack | â
| Implicite : le client atteint son event loop et dessine |
|
||
| 4 | Premier pixel â gradient ARGB visible | â
| Confirmation visuelle utilisateur sur fenĂȘtre QEMU graphique |
|
||
| 5 | **ESC ferme le client proprement** | â
| `[real-client] ESC â exit` + `[real-client] PASS` |
|
||
| 6 | Sortie propre, pas de FAIL | â
| `[real-client] loop exited cleanly` + garbage collect cÎté compo |
|
||
|
||
## Fixes appliqués
|
||
|
||
Les bugs ci-dessous étaient **invisibles** dans nos clients de test 6.x/7.x
|
||
parce qu'ils étaient adaptés à notre compositor (notamment l'offset +8
|
||
cÎté key). Précisément la valeur d'un client tiers : il révÚle les paths
|
||
que nos clients maison cachent. Anticipation correcte de la doc 13.1
|
||
(« Pas écrit par nous : c'est sa principale qualité »).
|
||
|
||
### Fix 1 â ESC mangĂ©e par le compositor au lieu d'ĂȘtre forwardĂ©e
|
||
|
||
**SymptĂŽme** : Ă l'appui sur ESC, le compositor exitait et fermait le socket,
|
||
le client recevait `Broken pipe (os error 32)` avant d'avoir pu traiter
|
||
sa propre logique ESC. RĂ©sultat : `[real-client] FAIL: Backend error: âŠ`.
|
||
|
||
**Cause** (`crates/redox-wl-compositor/src/main.rs:183-191` avant fix) :
|
||
|
||
```rust
|
||
InputEvent::Key { scancode, pressed, .. } if *pressed && *scancode == 0x01 => {
|
||
info!("Esc â exit");
|
||
let _ = frontend.flush_clients();
|
||
let _ = std::fs::remove_file(SOCKET_PATH);
|
||
return Ok(()); // <-- exit AVANT forward_input()
|
||
}
|
||
```
|
||
|
||
`forward_input(&ev)` à la ligne 202 n'était jamais atteint pour ESC.
|
||
|
||
**Fix** : ESC retombe dans `_ => {}` â forwarded normalement.
|
||
Raccourci compositor déplacé sur `Ctrl+Q` (scancode Q = `0x10` + état
|
||
`ctrl_held` tracké manuellement, scancode Ctrl L = `0x1D`).
|
||
|
||
Modifs :
|
||
- Ajout `ctrl_held: bool` au-dessus de la boucle main
|
||
- Tracking du Ctrl avant le `match &ev`
|
||
- Remplacement de l'arm ESC par `scancode == 0x10 && ctrl_held`
|
||
|
||
### Fix 2 â Cursor s'accumule hors-Ă©cran (deltas PS/2 non bornĂ©s)
|
||
|
||
**SymptĂŽme** : `left-click @ (10444, 10566) â hit_test = None` (Ă©cran 1440Ă900).
|
||
Les clics se faisaient à des coordonnées qui croissaient sans limite,
|
||
aucune fenĂȘtre ne matchait jamais le hit_test â aucune surface ne pouvait
|
||
ĂȘtre focalisĂ©e par clic.
|
||
|
||
**Cause** (`crates/redox-wl-wayland-frontend/src/lib.rs:860-861` avant fix) :
|
||
|
||
```rust
|
||
RedoxInputEvent::PointerMotionRelative { dx, dy } => {
|
||
self.cursor_x = self.cursor_x.saturating_add(*dx);
|
||
self.cursor_y = self.cursor_y.saturating_add(*dy);
|
||
// ... aucun clamp
|
||
}
|
||
```
|
||
|
||
Sous QEMU PS/2, le compositor reçoit des deltas relatifs. Sans clamp,
|
||
ils s'accumulent vers l'infini (limitĂ© par `saturating_add` mais Ă
|
||
i32::MAX bien au-delà de l'écran).
|
||
|
||
**Fix** : ajout d'un état `screen_w/screen_h` au frontend (init
|
||
`i32::MAX` = no-op tant que pas configuré), setter `set_screen_size(w, h)`
|
||
appelé par le compositor aprÚs `bind_absolute`, helper `clamp_cursor()`
|
||
invoqué aprÚs chaque update cursor (les 3 chemins : `PointerMotion`,
|
||
`PointerMotionRelative`, `set_cursor_position`).
|
||
|
||
### Fix 3 â Keycode envoyĂ© `scancode + 8` au lieu d'evdev brut (bug racine)
|
||
|
||
**SymptĂŽme** : mĂȘme aprĂšs les fixes 1 et 2, ESC n'avait aucun effet sur
|
||
le client. Pas de `[real-client] ESC â exit` malgrĂ© le focus auto-grant
|
||
correct et le forward_input appelé.
|
||
|
||
**Cause** (`crates/redox-wl-wayland-frontend/src/lib.rs:826-831` avant fix) :
|
||
|
||
```rust
|
||
// Wayland keycodes = scancode evdev = scancode +8 on linux
|
||
// (cf xkb_keycodes minimum=8). On garde le scancode brut
|
||
// ici en attendant une keymap correcte ...
|
||
let key = (*scancode as u32).saturating_add(8);
|
||
```
|
||
|
||
**Le commentaire est faux.** L'offset +8 c'est entre **evdev et X11**
|
||
(X11 KeyCode minimum = 8 historiquement), pas entre PS/2 et evdev. Pour
|
||
les touches alphanumériques de base, **PS/2 Set 1 scancode == evdev keycode**
|
||
(ESC=1, Q=16, etc.). Wayland (spec `wl_keyboard.key`) attend des
|
||
**evdev keycodes**, pas des X11.
|
||
|
||
Pour ESC :
|
||
- Compositor recevait scancode = `0x01` (correct)
|
||
- Envoyait `key = 0x01 + 8 = 9` au client
|
||
- Client testait `if key == 1` â `false` â ESC ignorĂ©
|
||
|
||
C'est précisément le path qui *passait* avec nos clients de test 6.x/7.x
|
||
parce qu'on contrÎlait les deux cÎtés et avait probablement aligné les
|
||
constantes. simple_window upstream attend les evdev raw.
|
||
|
||
**Fix** : suppression du `+8`. Le scancode brut suffit pour les touches
|
||
de base. Ă durcir quand on aura une vraie keymap XKB (ajustements pour
|
||
les touches étendues 0xE0xx).
|
||
|
||
```rust
|
||
let key = *scancode as u32;
|
||
```
|
||
|
||
### Fix 4 â Event loop client : handling propre des erreurs IO transientes
|
||
|
||
**SymptĂŽme** : mĂȘme avec les fixes 1/2/3, le `blocking_dispatch` du client
|
||
remontait une `Err(...)` sur `Interrupted` ou `BrokenPipe`/`ConnectionReset`
|
||
et le `?` final renvoyait `Err`, ce qui faisait que `main` loggait
|
||
`[real-client] FAIL` au lieu de `PASS` mĂȘme en sortie propre par ESC
|
||
(le compositor flush peut générer un `Interrupted` transitoire).
|
||
|
||
**Cause** (`crates/redox-wl-real-client-simple-window/src/main.rs`, event
|
||
loop avant fix) :
|
||
|
||
```rust
|
||
while state.running {
|
||
event_queue.blocking_dispatch(&mut state)?; // any Err â FAIL
|
||
}
|
||
```
|
||
|
||
**Fix** : ajout de helpers `is_interrupted_error` /
|
||
`is_connection_closed_error` (récursifs sur la chaßne `source()` pour
|
||
attraper les erreurs wrappées par `wayland-client`), et match explicite :
|
||
|
||
- `Interrupted` â `continue` (retry transparent)
|
||
- `BrokenPipe` / `ConnectionReset` â log `compositor disconnected â exit
|
||
cleanly` et `break` (terminaison normale si le compo s'éteint avant le
|
||
client)
|
||
- Autre erreur â `return Err(e.into())` â FAIL lĂ©gitime
|
||
|
||
â ïž **5e adaptation Redox cĂŽtĂ© client**, qui dĂ©passe les 4 originellement
|
||
autorisées par `phase13-1-real-client-simple-window.md:43-65`. Justification :
|
||
ce handling est **upstream-compatible** (l'exemple `simple_window.rs`
|
||
de wayland-rs aurait le mĂȘme comportement sur d'autres OS si le compositor
|
||
crashait juste aprĂšs un ESC). Ce n'est pas un workaround pour un manque
|
||
de notre compositor mais une robustesse standard que l'exemple upstream
|
||
ne couvre pas car il suppose un environnement de dev oĂč le compositor ne
|
||
meurt jamais. à déclarer comme adaptation #5 dans la prochaine MAJ de la
|
||
doc 13.1.
|
||
|
||
### Bonus â bruit console rĂ©duit
|
||
|
||
`info!("tick=âŠ")` toutes les ~1s dans la boucle main saturait la console
|
||
série. Passé en `debug!` + fréquence /5 (~5s). Réactivable avec
|
||
`RUST_LOG=debug`. Cf. `crates/redox-wl-compositor/src/main.rs:252-258`.
|
||
|
||
## Bugs secondaires Ă isoler (hors scope 13.1.b)
|
||
|
||
### B.1 â Curseur software ne suit pas la souris correctement
|
||
|
||
Pendant les tests, le curseur restait visuellement coincé en bas-droite
|
||
de l'écran (typiquement `(width-1, height-1)`). Les deltas relatifs
|
||
semblaient toujours majoritairement positifs. HypothĂšses Ă creuser :
|
||
|
||
- Mauvaise polarité des deltas Y sous QEMU/Redox (axe inversé ?)
|
||
- Conversion absoluârelatif en amont dans `inputd` qui dĂ©rive
|
||
- Souris non-grabbed par QEMU sur fenĂȘtre non focusĂ©e â accumulation
|
||
de moves "vers le bord" lors des allers-retours hĂŽte/guest
|
||
|
||
Test à faire en 13.1.c : logger systématiquement les deltas `(dx, dy)`
|
||
reçus et tracer leur somme cumulée vs déplacement réel attendu.
|
||
|
||
### B.2 â Page fault ion sur broken pipe d'un job background
|
||
|
||
Ă chaque fois qu'un client Wayland en background `&` se termine par
|
||
broken pipe (Ctrl+Q compositor avant exit client), **ion crashe** :
|
||
|
||
```
|
||
ion: ([Page fault: 0000000000000070 US ...
|
||
RIP: 00000000002335ae
|
||
... kernel::context::signal:INFO -- UNHANDLED EXCEPTION ... NAME /usr/bin/ion
|
||
```
|
||
|
||
Adresse fautive `0x70` = déréf null + offset, reproductible. Bug Redox
|
||
upstream (ion), pas notre compositor. Ă reporter sur
|
||
`gitlab.redox-os.org/redox-os/ion`.
|
||
|
||
### B.3 â VT switching hĂŽte interceptĂ© par CachyOS
|
||
|
||
`Ctrl+Alt+F2..F6` mangés par X/Wayland CachyOS avant QEMU, donc
|
||
impossible de switcher de VT depuis l'hĂŽte vers un Redox guest. Pas un
|
||
bug, contrainte connue. Workaround pratique : tout faire sur le seul VT
|
||
graphique (celui que la fenĂȘtre QEMU affiche), ou utiliser la console
|
||
sĂ©rie pour les commandes shell et la fenĂȘtre graphique pour le clavier
|
||
PS/2 du compositor.
|
||
|
||
### B.4 â Image RedoxFS Ă©troite (682 Mo initiale)
|
||
|
||
`pkg update` saturait le filesystem. Résolu pendant cette session par
|
||
`qemu-img resize harddrive.img 10G` + `redoxfs-resize`. à considérer si
|
||
on automatise la procédure : taille par défaut de l'image dans le
|
||
fork/script doit ĂȘtre â„ 4 Go pour permettre install paquets standards.
|
||
|
||
## Screenshots Ă prendre (suivant doc 13.1)
|
||
|
||
Ă ajouter au repo en `docs/phase13-1-b-*.png` :
|
||
|
||
- `phase13-1-b-gradient-running.png` â fenĂȘtre gradient ARGB visible sur
|
||
fond bleu nuit, dans la fenĂȘtre QEMU graphique, avant ESC.
|
||
- `phase13-1-b-after-esc.png` â fond bleu seul aprĂšs ESC (le compositor
|
||
continue, la fenĂȘtre client a disparu suite Ă `garbage_collect`).
|
||
- `phase13-1-b-log-pass.png` â capture console montrant
|
||
`[real-client] PASS` + `garbage_collect: ... â destroyed 1 surfaces`.
|
||
|
||
(Optionnel â la validation textuelle des logs suffit pour le critĂšre
|
||
de fin, mais les screenshots aident Ă comparer rapidement aux phases
|
||
ultérieures.)
|
||
|
||
## ProcĂ©dure de test runtime â version finale
|
||
|
||
Mise Ă jour vs `phase13-1-real-client-simple-window.md:82-135` : tout
|
||
se fait dans la **fenĂȘtre QEMU graphique** (la console sĂ©rie de l'hĂŽte
|
||
ne peut pas envoyer ESC Ă inputd).
|
||
|
||
### 1. HĂŽte CachyOS
|
||
|
||
```bash
|
||
cd ~/Projets/Redox/redox-wayland-compositor
|
||
./run-qemu.sh
|
||
```
|
||
|
||
### 2. FenĂȘtre QEMU graphique, aprĂšs login `root` / `password`
|
||
|
||
```sh
|
||
rm -f /tmp/redox-wl-comp.sock # défensif si résidu d'un test antérieur
|
||
redox-wl-compositor &
|
||
sleep 1
|
||
redox-wl-real-client-simple-window
|
||
```
|
||
|
||
### 3. Toujours sur la fenĂȘtre graphique
|
||
|
||
- VĂ©rifier visuellement : fond bleu + petite fenĂȘtre gradient ARGB
|
||
- Presser `ESC` une fois
|
||
- Attendu : `[real-client] ESC â exit`, `[real-client] loop exited cleanly`,
|
||
`[real-client] PASS`, retour au prompt
|
||
- Optionnel : `Ctrl+Q` pour arrĂȘter le compositor (sinon il timeout Ă
|
||
180s ou tu peux `kill %0` depuis le shell)
|
||
|
||
## CritĂšre de fin 13.1.b
|
||
|
||
> Le client tiers `redox-wl-real-client-simple-window`, port verbatim
|
||
> de `wayland-rs/wayland-client/examples/simple_window.rs` (sauf les 4
|
||
> adaptations Redox de 13.1), traverse le pipeline Wayland complet vers
|
||
> notre compositor jusqu'Ă `[real-client] PASS` sur ESC.
|
||
|
||
**â
Validé 2026-05-16.** 3 fixes appliqués sur le compositor, aucun
|
||
sur le code client (qui reste verbatim upstream).
|
||
|
||
## Fichiers modifiés
|
||
|
||
```
|
||
crates/redox-wl-compositor/src/main.rs # Fix 1 (ESCâclient, Ctrl+Qâcompo) + bonus bruit
|
||
crates/redox-wl-wayland-frontend/src/lib.rs # Fix 2 (clamp cursor) + Fix 3 (keycode evdev brut)
|
||
crates/redox-wl-real-client-simple-window/src/main.rs # Fix 4 (handling IO transient dans event loop)
|
||
run-qemu.sh # cleanup défensif (check /dev/fuse, IMAGE/REDOXFS overridables)
|
||
docs/phase13-1-b-observations.md # ce document
|
||
```
|