🎉 Phase 13.1.b — simple_window upstream validé runtime sur Redox

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
This commit is contained in:
Votre Nom 2026-05-16 10:59:35 +02:00
parent 0d8032b5ff
commit 18391c85f7
5 changed files with 401 additions and 15 deletions

View file

@ -138,6 +138,10 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
// Wayland frontend
let socket_path = PathBuf::from(SOCKET_PATH);
let mut frontend = WaylandFrontend::bind_absolute(&socket_path)?;
// Phase 13.1.b : déclarer les bornes écran AVANT toute manipulation
// de la position curseur, sinon les deltas relatifs (PS/2 sous QEMU)
// s'accumulent hors-écran et hit_test ne trouve jamais les surfaces.
frontend.set_screen_size(fb_w as i32, fb_h as i32);
// Phase 7.3 : curseur visible dès le démarrage, placé au centre du fb.
frontend.set_cursor_initial_position((fb_w as i32) / 2, (fb_h as i32) / 2);
info!("Wayland socket : {SOCKET_PATH}");
@ -154,6 +158,11 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
let frame_period = Duration::from_millis(33); // ~30 fps
let mut last_frame = Instant::now();
let mut tick: u32 = 0;
// Phase 13.1.b : Ctrl tenu, pour le raccourci compositor Ctrl+Q.
// ESC n'est plus interceptée — elle est forwardée aux clients afin que
// les apps tierces (cf. simple_window upstream) puissent décider elles-mêmes
// de se terminer sur ESC sans race avec la fermeture du socket compositor.
let mut ctrl_held = false;
while start.elapsed() < total {
tick = tick.wrapping_add(1);
@ -179,12 +188,23 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
tracing::debug!("{} input events from inputd", events.len());
}
for ev in events {
// Track Ctrl (scancode 0x1D, set 1) avant le match : nécessaire
// pour le raccourci Ctrl+Q et OK à dupliquer côté clients via
// forward_input — wl_keyboard.key reste la source de vérité pour eux.
if let InputEvent::Key {
scancode: 0x1D,
pressed,
..
} = ev
{
ctrl_held = pressed;
}
match &ev {
InputEvent::Key {
scancode, pressed, ..
} if *pressed && *scancode == 0x01 => {
// Esc → exit
info!("Esc → exit");
} if *pressed && *scancode == 0x10 && ctrl_held => {
// Ctrl+Q → exit compositor (ESC est réservé aux clients)
info!("Ctrl+Q → exit compositor");
let _ = frontend.flush_clients();
let _ = std::fs::remove_file(SOCKET_PATH);
return Ok(());
@ -229,9 +249,11 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
error!("flush err: {e}");
}
// Log occasionnel
if tick % 30 == 0 {
info!(
// Phase 13.1.b : tick log en debug! (saturait la console série).
// Réactivable avec RUST_LOG=debug. Fréquence réduite à toutes les
// 5s (~150 ticks @ 30fps) pour limiter encore le bruit.
if tick % 150 == 0 {
tracing::debug!(
"tick={tick} surfaces={nb} elapsed={:.1}s",
start.elapsed().as_secs_f32()
);