Bug B.1 13.1.b résolu : ps2d sous Redox+QEMU délivre les coords absolues du pointer dans 0..65535 (16-bit virtuel HID), pas en pixels écran. Notre PointerMotion faisait une assignation directe → clamp permanent à (width-1, height-1) → cursor coincé bas-droite, hit_test toujours None. Fix : conversion fixed-point x*screen_w/65536 (algo orbital upstream, cf orbital/src/scheme.rs:1583). Le clamp_cursor de 13.1.b reste comme garde-fou pour valeurs hors-spec. Validation runtime : curseur suit fidèlement la souris dans toute l'aire écran 1280×800, clics en (370,239), (522,303), (746,175), (1260,142), etc. Plus jamais de (1279,799) systématique. Bonus DX : filtre tracing par défaut « info,cursor=debug » pour éviter d'avoir à taper RUST_LOG complexe dans la fenêtre QEMU graphique (pas de copier-coller). Instrumentation `target="cursor"` laissée en place pour debug futur des événements pointer. Bug B.2 (page fault ion) non traité, reste à reporter upstream. Leyoda 2026 – GPLv3
5.9 KiB
Phase 13.1.c — Curseur souris : conversion HID→pixel
Document produit le 2026-05-16, suite de
phase13-1-b-observations.md.Scope : isoler et corriger le bug B.1 listé en 13.1.b — « curseur software ne suit pas la souris correctement, reste coincé en bas-droite de l'écran à
(width-1, height-1)». Diagnostic via instrumentation ciblée, fix conforme à l'algo d'orbital upstream, validation runtime.Verdict : ✅ 13.1.c validée — le curseur suit fidèlement la souris, les coordonnées de clic sont dans la plage écran.
Cause racine
Sous Redox + QEMU, ps2d délivre les coords absolues du pointer dans
un espace virtuel 16-bit (0..65535), pas en pixels écran. Notre
branche PointerMotion faisait une assignation directe :
self.cursor_x = *x; // x ∈ 0..65535 ⇒ cursor_x ∈ 0..65535
Le clamp_cursor() ajouté en 13.1.b saturait alors à screen_w - 1 à
chaque event → cursor coincé en bas-droite. Le bug B.1 13.1.b n'était
pas une dérive de deltas accumulés mais une mauvaise interprétation de
l'unité d'entrée.
Diagnostic
Instrumentation tracing::debug!(target: "cursor", ...) ajoutée dans les
deux branches motion de WaylandFrontend::forward_input pour logger les
valeurs brutes reçues. Avec RUST_LOG=info,cursor=debug (devenu le filtre
par défaut de init_tracing), une session de tests motion délibérés a
révélé :
DEBUG cursor: ABS x=61642 y=15564 screen=1280x800
DEBUG cursor: ABS x=50174 y=20970 screen=1280x800
DEBUG cursor: ABS x=43006 y=23592 screen=1280x800
DEBUG cursor: ABS x=42084 y=23918 screen=1280x800
Valeurs maximales observées ≈ 62000 / 24000 sur écran 1280×800, ratio ~50× pour x et ~30× pour y. Hypothèse 16-bit confirmée par la doc upstream orbital :
// orbital/src/scheme.rs:1576
// ps2d gives us absolute mouse events with x and y in the range 0..65535.
Fix
Conversion fixed-point en pixel via la même formule qu'orbital
(orbital/src/scheme.rs:1583-1586) :
let scaled_x = ((*x as i64) * (self.screen_w as i64)) / 65536;
let scaled_y = ((*y as i64) * (self.screen_h as i64)) / 65536;
self.cursor_x = scaled_x as i32;
self.cursor_y = scaled_y as i32;
self.clamp_cursor(); // garde-fou pour valeurs hors-spec
Diviseur 65536 (pas 65535) volontaire — fixed-point 16-bit, donne
max output = screen - 1 quand input = 65535. Cohérent avec
l'arithmétique d'orbital.
Le clamp_cursor ajouté en 13.1.b reste utile comme garde-fou (si un
device sort de la plage 0..65535) mais ne masque plus le bug principal.
Validation runtime
Test sur écran 1280×800 (fenêtre QEMU graphique, après reboot Redox frais). Mouvement délibéré de la souris du coin haut-gauche au coin bas-droit en passant par le centre. Logs filtrés :
DEBUG cursor: ABS x=18994 y=19660 → pixel (370,239) screen=1280x800 ← haut-gauche
DEBUG cursor: ABS x=33176 y=33094 → pixel (647,403) screen=1280x800 ← centre
DEBUG cursor: ABS x=64560 y=11714 → pixel (1260,142) screen=1280x800 ← haut-droit
DEBUG cursor: ABS x=37476 y=33176 → pixel (731,404) screen=1280x800 ← retour centre
Coordonnées pixel cohérentes avec la position physique de la souris,
toutes dans la plage 0..1279 × 0..799. Pas de saturation au coin.
Clics au passage :
DEBUG redox_wl_wayland_frontend: left-click @ (522, 303) → hit_test = None
DEBUG redox_wl_wayland_frontend: left-click @ (746, 175) → hit_test = None
DEBUG redox_wl_wayland_frontend: left-click @ (370, 239) → hit_test = None
hit_test = None attendu : aucun client n'était lancé pendant ce test.
Les coords sont en revanche bien dans l'espace écran et pourront matcher
un toplevel quand un client tournera.
Bonus DX (developer experience)
Type pénible de taper RUST_LOG=info,redox_wl_wayland_frontend::cursor=debug
dans la fenêtre QEMU graphique (pas de copier-coller possible).
Modification du filtre par défaut dans init_tracing :
EnvFilter::new("info,cursor=debug")
Tu tapes juste redox-wl-compositor, tu vois les traces cursor sans
spam des ticks. Override toujours possible via RUST_LOG= au launch.
Sous-bug B.2 (page fault ion) — non traité
Reste documenté pour follow-up upstream. Repro fiable :
- Lancer un job background Wayland (
redox-wl-real-client-simple-window &) - Tuer le compositor avant que le client n'exit (
Ctrl+Qsans avoir pressé ESC d'abord) - ion crashe avec page fault
0x70
À reporter sur gitlab.redox-os.org/redox-os/ion. Hors scope du compositor.
Critère de fin 13.1.c
Le curseur software du compositor suit fidèlement les déplacements souris dans toute l'aire de la fenêtre QEMU graphique, sans saturer à un bord, sans dérive monotone. Les coordonnées de clic sont dans la plage écran et
hit_testpeut matcher une surface visible.
✅ Validé 2026-05-16. Conversion HID→pixel alignée sur l'algo upstream d'orbital, instrumentation laissée en place pour debug futur.
Fichiers modifiés
crates/redox-wl-wayland-frontend/src/lib.rs # Conversion 0..65535 → pixels écran dans PointerMotion
# Traces tracing target="cursor"
crates/redox-wl-compositor/src/main.rs # Filtre tracing par défaut "info,cursor=debug"
docs/phase13-1-c-cursor.md # ce document
Limites connues
PointerMotionRelative(deltas relatifs) reste instrumenté mais n'a jamais été observé sous QEMU PS/2 + qemu-xhci. Si un jour Redox passe à de la souris purement relative, on aura un secondset_screen_size- clamp à valider.
- L'aspect ratio entre l'espace HID 65536² et l'écran 1280×800 n'est pas carré (1.6 vs 1) — la précision diagonale peut sembler légèrement décalée. Strictement OK pour 13.1.c, à observer en 13.2+ avec un vrai client graphique qui dessine sous le curseur (drag, drawing).