diff --git a/crates/redox-wl-compositor/src/main.rs b/crates/redox-wl-compositor/src/main.rs index 129e67a..8a7e162 100644 --- a/crates/redox-wl-compositor/src/main.rs +++ b/crates/redox-wl-compositor/src/main.rs @@ -95,7 +95,13 @@ impl<'a> MakeWriter<'a> for TeeWriter { } fn init_tracing() { - let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + // Phase 13.1.c : par défaut, info + target=cursor en debug. Le target + // `cursor` est utilisé par les traces ABS/REL du frontend (cf + // redox-wl-wayland-frontend). Pratique sous QEMU graphique où taper + // un RUST_LOG complexe est pénible (pas de copier-coller). Override + // toujours possible via RUST_LOG=… au lancement. + let filter = EnvFilter::try_from_default_env() + .unwrap_or_else(|_| EnvFilter::new("info,cursor=debug")); tracing_subscriber::fmt() .with_env_filter(filter) .with_writer(TeeWriter::new()) diff --git a/crates/redox-wl-wayland-frontend/src/lib.rs b/crates/redox-wl-wayland-frontend/src/lib.rs index 8e6218d..956e380 100644 --- a/crates/redox-wl-wayland-frontend/src/lib.rs +++ b/crates/redox-wl-wayland-frontend/src/lib.rs @@ -844,8 +844,22 @@ impl WaylandFrontend { } } RedoxInputEvent::PointerMotion { x, y } => { - self.cursor_x = *x; - self.cursor_y = *y; + // Phase 13.1.c : ps2d (sous Redox+QEMU) délivre des coords + // absolues en 0..65535 (cf orbital/src/scheme.rs:1575-1587, + // commentaire upstream « ps2d gives us absolute mouse events + // with x and y in the range 0..65535 »). On scale vers les + // pixels écran avec la même formule qu'orbital : x*screen_w/65536. + // Le diviseur 65536 (pas 65535) est volontaire — fixed-point + // 16-bit, donne max=screen-1 quand input=65535. + let scaled_x = ((*x as i64) * (self.screen_w as i64)) / 65536; + let scaled_y = ((*y as i64) * (self.screen_h as i64)) / 65536; + tracing::debug!( + target: "cursor", + "ABS x={x} y={y} → pixel ({scaled_x},{scaled_y}) screen={}x{}", + self.screen_w, self.screen_h + ); + self.cursor_x = scaled_x as i32; + self.cursor_y = scaled_y as i32; self.clamp_cursor(); self.cursor_visible = true; // Phase 7.7 : si drag actif, déplacer la surface au lieu @@ -868,9 +882,22 @@ impl WaylandFrontend { } } RedoxInputEvent::PointerMotionRelative { dx, dy } => { + let before_x = self.cursor_x; + let before_y = self.cursor_y; self.cursor_x = self.cursor_x.saturating_add(*dx); self.cursor_y = self.cursor_y.saturating_add(*dy); + let after_raw_x = self.cursor_x; + let after_raw_y = self.cursor_y; self.clamp_cursor(); + // Phase 13.1.c : trace dx/dy + cursor avant/après pour + // identifier si les deltas dérivent toujours positivement + // (axe inversé ? cumul d'edge ?) ou si le clamp masque le + // problème. + tracing::debug!( + target: "cursor", + "REL dx={dx} dy={dy} before=({before_x},{before_y}) raw=({after_raw_x},{after_raw_y}) clamped=({},{})", + self.cursor_x, self.cursor_y + ); self.cursor_visible = true; // Phase 7.7 : si drag actif, déplacer la surface. if self.apply_interactive_drag() { diff --git a/docs/phase13-1-c-cursor.md b/docs/phase13-1-c-cursor.md new file mode 100644 index 0000000..b916d9e --- /dev/null +++ b/docs/phase13-1-c-cursor.md @@ -0,0 +1,152 @@ +# 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).