🎉 Phase 13.2.a — wl_output v3 complet (gating v1/v2/v3 validé en natif)
Dette protocolaire transversale comblée : wl_output n'était pas déclaré comme global, plusieurs toolkits client (sctk, GTK, Qt) le considèrent implicitement requis. Maintenant exposé à v3 avec gating conforme : - geometry, mode : envoyés à toutes les versions (>= 1) - scale : seulement si bind >= 3 (gating conservateur) - done : seulement si bind >= 2 Mode flags = CURRENT | PREFERRED, refresh 60 000 mHz, scale_factor=1, transform Normal, subpixel Unknown, make=Redox, model=redox-wl-output:0. Position (0,0), single output, taille pixel issue de screen_w/screen_h (setté par set_screen_size au boot compositor). Nouveau crate de validation : redox-wl-test-wl-output. Deux niveaux : 1. Client autonome pour test runtime dans QEMU (bind aux 3 versions, dump events, PASS/FAIL via exit code) 2. Test natif (cargo test, tourne sur l'hôte sans QEMU) qui simule serveur+client en-process via UnixStream::pair() et valide les 11 assertions du gating. Vérifié PASS le 2026-05-16 sur CachyOS. Le test natif sert de garde-fou anti-régression pour CI ultérieur. Plus besoin de relancer QEMU pour valider ce path. run-qemu.sh : copie maintenant aussi le test client si compilé (skip silencieux sinon). Leyoda 2026 – GPLv3
This commit is contained in:
parent
095d7e5550
commit
7413745dbe
5 changed files with 651 additions and 2 deletions
|
|
@ -36,8 +36,8 @@ use wayland_protocols::xdg::shell::server::{
|
|||
use wayland_server::{
|
||||
backend::{ClientData, ClientId, DisconnectReason},
|
||||
protocol::{
|
||||
wl_buffer, wl_callback, wl_compositor, wl_keyboard, wl_pointer, wl_region, wl_seat, wl_shm,
|
||||
wl_shm_pool, wl_surface,
|
||||
wl_buffer, wl_callback, wl_compositor, wl_keyboard, wl_output, wl_pointer, wl_region,
|
||||
wl_seat, wl_shm, wl_shm_pool, wl_surface,
|
||||
},
|
||||
Client, DataInit, Display as WlDisplay, DisplayHandle, GlobalDispatch, Resource,
|
||||
};
|
||||
|
|
@ -48,6 +48,9 @@ const COMPOSITOR_VERSION: u32 = 5;
|
|||
const SHM_VERSION: u32 = 1;
|
||||
const XDG_WM_BASE_VERSION: u32 = 5;
|
||||
const SEAT_VERSION: u32 = 7;
|
||||
// Phase 13.2.a : wl_output v3 (couvre geometry + mode + scale + done +
|
||||
// release request, sans v4 name/description qu'on ne fournit pas encore).
|
||||
const OUTPUT_VERSION: u32 = 3;
|
||||
|
||||
/// Taille suggérée par défaut pour les nouvelles fenêtres xdg_toplevel.
|
||||
/// Le client peut respecter ou non ; on utilise sa propre taille de buffer
|
||||
|
|
@ -434,6 +437,11 @@ impl WaylandFrontend {
|
|||
dh.create_global::<Self, wl_shm::WlShm, _>(SHM_VERSION, ());
|
||||
dh.create_global::<Self, xdg_wm_base::XdgWmBase, _>(XDG_WM_BASE_VERSION, ());
|
||||
dh.create_global::<Self, wl_seat::WlSeat, _>(SEAT_VERSION, ());
|
||||
// Phase 13.2.a : wl_output déclaré comme global. Single output
|
||||
// mappé au framebuffer du compositor. Les events init (geometry/
|
||||
// mode/scale/done) sont envoyés dans le bind, cf GlobalDispatch
|
||||
// plus bas.
|
||||
dh.create_global::<Self, wl_output::WlOutput, _>(OUTPUT_VERSION, ());
|
||||
|
||||
let listener = wayland_server::ListeningSocket::bind_absolute(socket_path.to_path_buf())?;
|
||||
|
||||
|
|
@ -2157,6 +2165,88 @@ impl wayland_server::Dispatch<xdg_toplevel::XdgToplevel, Arc<XdgToplevelData>> f
|
|||
}
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// wl_output (phase 13.2.a)
|
||||
// =====================================================================
|
||||
//
|
||||
// Single output mappé sur le framebuffer du compositor. Les events
|
||||
// d'init (geometry / mode / scale / done) sont envoyés dans `bind` à
|
||||
// chaque nouvelle resource bound par un client, gated par la version
|
||||
// négociée :
|
||||
// - geometry, mode : v1+, toujours envoyés
|
||||
// - scale : v3+ (gating conservateur ; spec autorise v2+ mais on évite
|
||||
// l'ambiguïté sur les clients v2 qui pourraient mal gérer)
|
||||
// - done : v2+
|
||||
// La taille pixel vient de `screen_w / screen_h`, setté par
|
||||
// `set_screen_size()` au démarrage du compositor. Refresh hardcodé à
|
||||
// 60 Hz (60000 mHz) — notre boucle main tourne à ~30 fps mais les apps
|
||||
// modernes ignorent largement ce champ, et 60 Hz est un standard sûr.
|
||||
|
||||
impl GlobalDispatch<wl_output::WlOutput, ()> for WaylandFrontend {
|
||||
fn bind(
|
||||
state: &mut Self,
|
||||
_handle: &DisplayHandle,
|
||||
_client: &Client,
|
||||
resource: wayland_server::New<wl_output::WlOutput>,
|
||||
_data: &(),
|
||||
data_init: &mut DataInit<'_, Self>,
|
||||
) {
|
||||
let output = data_init.init(resource, ());
|
||||
let version = output.version();
|
||||
|
||||
// geometry : position dans l'espace logique multi-écran (0,0
|
||||
// ici), taille physique inconnue (0 mm, valeur "ne sait pas" par
|
||||
// convention Wayland), subpixel/make/model/transform placeholders.
|
||||
output.geometry(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
wl_output::Subpixel::Unknown,
|
||||
"Redox".to_string(),
|
||||
"redox-wl-output:0".to_string(),
|
||||
wl_output::Transform::Normal,
|
||||
);
|
||||
|
||||
// mode : taille pixel courante = framebuffer. Flags Current +
|
||||
// Preferred (un seul mode, c'est de facto le préféré).
|
||||
let mode_flags = wl_output::Mode::Current | wl_output::Mode::Preferred;
|
||||
output.mode(mode_flags, state.screen_w, state.screen_h, 60_000);
|
||||
|
||||
// scale v3+ : facteur 1 (pas de HiDPI pour notre framebuffer).
|
||||
if version >= 3 {
|
||||
output.scale(1);
|
||||
}
|
||||
|
||||
// done v2+ : signale la fin du batch init pour que le client
|
||||
// ne dispatche son OutputInfo qu'une fois tous les events arrivés.
|
||||
if version >= 2 {
|
||||
output.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl wayland_server::Dispatch<wl_output::WlOutput, ()> for WaylandFrontend {
|
||||
fn request(
|
||||
_state: &mut Self,
|
||||
_client: &Client,
|
||||
_r: &wl_output::WlOutput,
|
||||
request: wl_output::Request,
|
||||
_data: &(),
|
||||
_dh: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, Self>,
|
||||
) {
|
||||
match request {
|
||||
wl_output::Request::Release => {
|
||||
// v3+ : le client libère son binding wl_output. La resource
|
||||
// est nettoyée automatiquement par wayland-server quand on
|
||||
// ne traite pas d'autre request — on no-op simplement.
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests unitaires xdg-shell (sprint 0 point 4).
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue