redox-wayland-compositor/docs/phase13-1-c-cursor.md
Votre Nom 58ef6a85c2 🎉 Phase 13.1.c — curseur souris : conversion HID→pixel
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
2026-05-16 11:32:32 +02:00

5.9 KiB
Raw Permalink Blame History

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 :

  1. Lancer un job background Wayland (redox-wl-real-client-simple-window &)
  2. Tuer le compositor avant que le client n'exit (Ctrl+Q sans avoir pressé ESC d'abord)
  3. 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_test peut 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 second set_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).