diff --git a/crates/redox-wl-test-introspect/Cargo.toml b/crates/redox-wl-test-introspect/Cargo.toml new file mode 100644 index 0000000..263b6d9 --- /dev/null +++ b/crates/redox-wl-test-introspect/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "redox-wl-test-introspect" +version = "0.1.0" +edition = "2021" + +[dependencies] +wayland-client = { path = "../../../wayland-rs/wayland-client", default-features = false } +wayland-backend = { path = "../../../wayland-rs/wayland-backend", default-features = false } +libc = "0.2" diff --git a/crates/redox-wl-test-introspect/src/main.rs b/crates/redox-wl-test-introspect/src/main.rs new file mode 100644 index 0000000..b19fa67 --- /dev/null +++ b/crates/redox-wl-test-introspect/src/main.rs @@ -0,0 +1,279 @@ +//! Introspection des globals Wayland exposés par le compositor. +//! +//! Se connecte à `/tmp/redox-wl-comp.sock`, fait un roundtrip pour +//! capturer tous les `wl_registry.global` events, puis : +//! 1. Liste les globals advertised (name + version) +//! 2. Compare à un catalogue de protocoles attendus pour +//! COSMIC / GTK4 / Qt5 / divers toolkits Wayland modernes +//! 3. Imprime un rapport OK / MISSING / EXTRA +//! +//! Sert à anticiper les manques avant d'attaquer un vrai toolkit. + +use std::fs::OpenOptions; +use std::io::Write; +use std::os::unix::net::UnixStream; +use std::process::ExitCode; +use std::sync::{Mutex, OnceLock}; +use std::thread; +use std::time::Duration; + +use wayland_client::{ + Connection, Dispatch, EventQueue, QueueHandle, + backend::Backend, + protocol::wl_registry, +}; + +const SOCKET_PATH: &str = "/tmp/redox-wl-comp.sock"; + +struct DebugSink(Mutex>); +impl DebugSink { + fn new() -> Self { + Self(Mutex::new( + OpenOptions::new().write(true).open("/scheme/debug").ok(), + )) + } + fn writeln(&self, s: &str) { + println!("{s}"); + if let Ok(mut g) = self.0.lock() { + if let Some(f) = g.as_mut() { + let _ = writeln!(f, "{s}"); + } + } + } +} +fn dlog(s: &str) { + static SINK: OnceLock = OnceLock::new(); + SINK.get_or_init(DebugSink::new).writeln(s); +} + +#[derive(Default)] +struct Introspect { + globals: Vec<(String, u32)>, +} + +impl Dispatch for Introspect { + fn event( + state: &mut Self, + _r: &wl_registry::WlRegistry, + event: wl_registry::Event, + _data: &(), + _conn: &Connection, + _qh: &QueueHandle, + ) { + if let wl_registry::Event::Global { + name: _, + interface, + version, + } = event + { + state.globals.push((interface, version)); + } + } +} + +/// Catalogue de protocoles attendus par les toolkits modernes. +/// Le 3e élément est une description courte de pourquoi c'est utile. +const EXPECTED: &[(&str, &str, &str)] = &[ + // --- core wayland --- + ("wl_compositor", "core", "surfaces + regions"), + ("wl_shm", "core", "shared memory buffers"), + ("wl_seat", "core", "input devices (kbd/ptr)"), + ("wl_subcompositor", "core", "sub-surfaces"), + ("wl_output", "core", "monitors info (geometry, scale, mode)"), + ("wl_data_device_manager", "core", "clipboard + DnD"), + // --- xdg-shell --- + ("xdg_wm_base", "stable", "window management (toplevel + popup)"), + // --- protocoles externes très demandés --- + ( + "zxdg_decoration_manager_v1", + "unstable v1", + "CSD vs SSD — GTK/Qt négocient ici qui dessine la barre de titre", + ), + ( + "wp_viewporter", + "stable", + "HiDPI cropping/scaling — beaucoup de toolkits l'utilisent", + ), + ( + "wp_fractional_scale_manager_v1", + "v1", + "fractional scaling (125%, 150%) — COSMIC, GNOME récent", + ), + ( + "zwp_linux_dmabuf_v1", + "unstable v1", + "dmabuf import (GPU buffers) — requis pour tout GL/Vulkan", + ), + ( + "wp_presentation", + "stable", + "timing précis de présentation — média players, jeux", + ), + ( + "zwp_tablet_manager_v2", + "unstable v2", + "tablettes graphiques + stylus", + ), + ( + "zwp_primary_selection_device_manager_v1", + "unstable v1", + "clipboard middle-click (style X11)", + ), + ( + "zxdg_output_manager_v1", + "unstable v1", + "monitor info riche (xdg_output : logical position + size)", + ), + ( + "zwlr_layer_shell_v1", + "wlroots v1", + "barres de tâches / overlays — REQUIS pour COSMIC panel", + ), + ( + "xdg_activation_v1", + "v1", + "focus stealing prevention — toolkits modernes", + ), + ( + "wp_cursor_shape_manager_v1", + "v1", + "curseurs serveur-side (alternative à set_cursor)", + ), + ( + "zxdg_exporter_v2", + "unstable v2", + "exporter de handle pour foreign-toplevel", + ), + ( + "zwp_relative_pointer_manager_v1", + "unstable v1", + "pointeur relatif (jeux, FPS)", + ), + ( + "zwp_pointer_constraints_v1", + "unstable v1", + "lock/confine pointer (jeux)", + ), +]; + +fn run() -> Result<(), Box> { + dlog("[introspect] connect to compositor"); + for _ in 0..50 { + if std::path::Path::new(SOCKET_PATH).exists() { + break; + } + thread::sleep(Duration::from_millis(100)); + } + let stream = UnixStream::connect(SOCKET_PATH)?; + let backend = Backend::connect(stream)?; + let conn = Connection::from_backend(backend); + let mut event_queue: EventQueue = conn.new_event_queue(); + let qh = event_queue.handle(); + let _registry = conn.display().get_registry(&qh, ()); + + let mut state = Introspect::default(); + // 2 roundtrips pour être sûr d'avoir tous les globals (le serveur + // peut les advertise en plusieurs batches) + event_queue.roundtrip(&mut state)?; + event_queue.roundtrip(&mut state)?; + + dlog(""); + dlog("=================================================="); + dlog("Introspection compositor Wayland — rapport"); + dlog("=================================================="); + dlog(""); + dlog(&format!( + "Globals annoncés par le compositor ({}):", + state.globals.len() + )); + let mut sorted: Vec<(String, u32)> = state.globals.clone(); + sorted.sort_by(|a, b| a.0.cmp(&b.0)); + for (iface, ver) in &sorted { + dlog(&format!(" • {iface} v{ver}")); + } + dlog(""); + dlog("Comparaison au catalogue COSMIC/GTK4/Qt5 :"); + dlog(""); + + let mut present_count = 0usize; + let mut missing_critical = Vec::new(); + let mut missing_optional = Vec::new(); + + for (iface, kind, why) in EXPECTED { + let found = state.globals.iter().find(|(i, _)| i == iface); + match found { + Some((_, v)) => { + dlog(&format!(" [ OK ] {iface} v{v} — {why}")); + present_count += 1; + } + None => { + let line = format!(" [MISS] {iface} ({kind}) — {why}"); + dlog(&line); + // Critiques pour COSMIC = layer-shell + dmabuf + decoration + if iface.contains("layer_shell") + || iface.contains("dmabuf") + || iface.contains("decoration") + || iface.contains("data_device") + || iface.contains("wl_output") + || iface.contains("wl_subcompositor") + { + missing_critical.push(*iface); + } else { + missing_optional.push(*iface); + } + } + } + } + + // Globaux exposés non listés (potentiellement spécifiques au compositor) + let extras: Vec<&(String, u32)> = state + .globals + .iter() + .filter(|(i, _)| !EXPECTED.iter().any(|(e, _, _)| e == i)) + .collect(); + if !extras.is_empty() { + dlog(""); + dlog("Globaux exposés hors catalogue (custom / non listés ici) :"); + for (i, v) in &extras { + dlog(&format!(" • {i} v{v}")); + } + } + + dlog(""); + dlog("=================================================="); + dlog(&format!( + "RÉSUMÉ : {} présents / {} attendus", + present_count, + EXPECTED.len() + )); + dlog(&format!( + " ❌ Critiques manquants pour COSMIC : {}", + missing_critical.len() + )); + for i in &missing_critical { + dlog(&format!(" - {i}")); + } + dlog(&format!( + " ⚠ Optionnels manquants (toolkits dégradent) : {}", + missing_optional.len() + )); + for i in &missing_optional { + dlog(&format!(" - {i}")); + } + dlog("=================================================="); + + Ok(()) +} + +fn main() -> ExitCode { + match run() { + Ok(()) => { + dlog("[introspect] PASS"); + ExitCode::SUCCESS + } + Err(e) => { + dlog(&format!("[introspect] FAIL: {e}")); + ExitCode::FAILURE + } + } +} diff --git a/docs/phase7-9-introspect-report.txt b/docs/phase7-9-introspect-report.txt new file mode 100644 index 0000000..0e10f55 --- /dev/null +++ b/docs/phase7-9-introspect-report.txt @@ -0,0 +1,62 @@ +QEMU done +================================================== +[introspect] connect to compositor + +================================================== +Introspection compositor Wayland — rapport +================================================== + +Globals annoncés par le compositor (4): + • wl_compositor v5 + • wl_seat v7 + • wl_shm v1 + • xdg_wm_base v5 + +Comparaison au catalogue COSMIC/GTK4/Qt5 : + + [ OK ] wl_compositor v5 — surfaces + regions + [ OK ] wl_shm v1 — shared memory buffers + [ OK ] wl_seat v7 — input devices (kbd/ptr) + [MISS] wl_subcompositor (core) — sub-surfaces + [MISS] wl_output (core) — monitors info (geometry, scale, mode) + [MISS] wl_data_device_manager (core) — clipboard + DnD + [ OK ] xdg_wm_base v5 — window management (toplevel + popup) + [MISS] zxdg_decoration_manager_v1 (unstable v1) — CSD vs SSD — GTK/Qt négocient ici qui dessine la barre de titre + [MISS] wp_viewporter (stable) — HiDPI cropping/scaling — beaucoup de toolkits l'utilisent + [MISS] wp_fractional_scale_manager_v1 (v1) — fractional scaling (125%, 150%) — COSMIC, GNOME récent + [MISS] zwp_linux_dmabuf_v1 (unstable v1) — dmabuf import (GPU buffers) — requis pour tout GL/Vulkan + [MISS] wp_presentation (stable) — timing précis de présentation — média players, jeux + [MISS] zwp_tablet_manager_v2 (unstable v2) — tablettes graphiques + stylus + [MISS] zwp_primary_selection_device_manager_v1 (unstable v1) — clipboard middle-click (style X11) + [MISS] zxdg_output_manager_v1 (unstable v1) — monitor info riche (xdg_output : logical position + size) + [MISS] zwlr_layer_shell_v1 (wlroots v1) — barres de tâches / overlays — REQUIS pour COSMIC panel + [MISS] xdg_activation_v1 (v1) — focus stealing prevention — toolkits modernes + [MISS] wp_cursor_shape_manager_v1 (v1) — curseurs serveur-side (alternative à set_cursor) + [MISS] zxdg_exporter_v2 (unstable v2) — exporter de handle pour foreign-toplevel + [MISS] zwp_relative_pointer_manager_v1 (unstable v1) — pointeur relatif (jeux, FPS) + [MISS] zwp_pointer_constraints_v1 (unstable v1) — lock/confine pointer (jeux) + +================================================== +RÉSUMÉ : 4 présents / 21 attendus + ❌ Critiques manquants pour COSMIC : 6 + - wl_subcompositor + - wl_output + - wl_data_device_manager + - zxdg_decoration_manager_v1 + - zwp_linux_dmabuf_v1 + - zwlr_layer_shell_v1 + ⚠ Optionnels manquants (toolkits dégradent) : 11 + - wp_viewporter + - wp_fractional_scale_manager_v1 + - wp_presentation + - zwp_tablet_manager_v2 + - zwp_primary_selection_device_manager_v1 + - zxdg_output_manager_v1 + - xdg_activation_v1 + - wp_cursor_shape_manager_v1 + - zxdg_exporter_v2 + - zwp_relative_pointer_manager_v1 + - zwp_pointer_constraints_v1 +================================================== +[introspect] PASS +==================================================