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

152 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 13.1.c — Curseur souris : conversion HID→pixel
> Document produit le 2026-05-16, suite de
> [`phase13-1-b-observations.md`](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 :
```rust
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`) :
```rust
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` :
```rust
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).