From 1c6aafbc24b25bc980a37cbd5c714ec64bcfd622 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 22 May 2026 14:37:03 +0000 Subject: [PATCH] =?UTF-8?q?feat(mirada):=20mirada-layout=20no=5Fstd=20?= =?UTF-8?q?=E2=80=94=20primer=20n=C3=BAcleo=20compartible=20con=20renaser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mirada-layout (el motor de teselado del compositor) pasa a `no_std + alloc` para poder compilarse también en bare-metal — es el primer crate-núcleo que brahman y renaser compartirán. - `#![cfg_attr(not(test), no_std)]` + `extern crate alloc`: usa `alloc::{vec, collections::BTreeMap}` en vez de `std`. - Matemática de punto flotante vía `libm` (`sqrt`/`ceil`/`round` viven en `std`, no en `core`). - `serde` pasa a feature opcional: los consumidores Linux (mirada-protocol/brain) la activan; un consumidor bare-metal no necesita (de)serializar el layout. - Deps declaradas directas (no `workspace = true`): un núcleo que cruzará fronteras de workspace se mantiene autocontenido. Verificado: `cargo build --target x86_64-unknown-none` compila; 32 tests verdes; mirada-protocol/brain sin regresión. Co-Authored-By: Claude Opus 4.7 --- Cargo.lock | 1 + crates/modules/mirada/mirada-brain/Cargo.toml | 4 +++- .../modules/mirada/mirada-layout/Cargo.toml | 16 +++++++++++++++- .../mirada/mirada-layout/src/geometry.rs | 6 +++++- .../mirada/mirada-layout/src/layout.rs | 19 +++++++++++++------ .../modules/mirada/mirada-layout/src/lib.rs | 6 ++++++ .../mirada/mirada-layout/src/workspace.rs | 10 ++++++++-- .../modules/mirada/mirada-protocol/Cargo.toml | 4 +++- 8 files changed, 54 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53fda81..605c158 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7889,6 +7889,7 @@ version = "0.1.0" name = "mirada-layout" version = "0.1.0" dependencies = [ + "libm", "serde", ] diff --git a/crates/modules/mirada/mirada-brain/Cargo.toml b/crates/modules/mirada/mirada-brain/Cargo.toml index bc9315b..f55109a 100644 --- a/crates/modules/mirada/mirada-brain/Cargo.toml +++ b/crates/modules/mirada/mirada-brain/Cargo.toml @@ -8,7 +8,9 @@ publish.workspace = true description = "mirada — orquestador de escritorio del compositor: mantiene salidas, escritorios virtuales, ventanas y foco; consume BodyEvent y produce BrainCommand. Agnóstico de GPUI y de smithay." [dependencies] -mirada-layout = { path = "../mirada-layout" } +# `serde` activa los `derive` de los tipos de layout (este crate +# serializa el estado del escritorio a RON). +mirada-layout = { path = "../mirada-layout", features = ["serde"] } mirada-protocol = { path = "../mirada-protocol" } serde = { workspace = true } ron = { workspace = true } diff --git a/crates/modules/mirada/mirada-layout/Cargo.toml b/crates/modules/mirada/mirada-layout/Cargo.toml index e8df6d8..e448a26 100644 --- a/crates/modules/mirada/mirada-layout/Cargo.toml +++ b/crates/modules/mirada/mirada-layout/Cargo.toml @@ -8,4 +8,18 @@ publish.workspace = true description = "mirada — motor de teselado del compositor Wayland: reparte la pantalla entre ventanas según el modo de layout. Agnóstico de Wayland y de smithay." [dependencies] -serde = { workspace = true } +# Deps declaradas directas (no `workspace = true`): mirada-layout es un +# crate-núcleo compartido entre dos workspaces de Cargo —brahman y +# renaser— así que mantiene sus dependencias autocontenidas. +# +# `libm`: `sqrt`/`ceil`/`round` viven en `std`, no en `core`; este crate +# es `no_std`, así que la matemática de punto flotante pasa por `libm`. +libm = "0.2" +# `serde` es opcional: el motor de teselado no necesita (de)serializar +# para funcionar. Los consumidores Linux (mirada-protocol/brain) activan +# la feature; el kernel bare-metal de renaser no. `default-features = +# false` evita arrastrar `std` aun con la feature activa. +serde = { version = "1", optional = true, default-features = false, features = ["derive", "alloc"] } + +[features] +serde = ["dep:serde"] diff --git a/crates/modules/mirada/mirada-layout/src/geometry.rs b/crates/modules/mirada/mirada-layout/src/geometry.rs index aa3a306..ceb12d3 100644 --- a/crates/modules/mirada/mirada-layout/src/geometry.rs +++ b/crates/modules/mirada/mirada-layout/src/geometry.rs @@ -1,10 +1,14 @@ //! Geometría — el rectángulo en coordenadas de pantalla. +use alloc::vec::Vec; + +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// Un rectángulo en píxeles de pantalla. El origen `(0,0)` es la /// esquina superior-izquierda; `x` crece a la derecha, `y` hacia abajo. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Rect { pub x: i32, pub y: i32, diff --git a/crates/modules/mirada/mirada-layout/src/layout.rs b/crates/modules/mirada/mirada-layout/src/layout.rs index 629631e..bcc1277 100644 --- a/crates/modules/mirada/mirada-layout/src/layout.rs +++ b/crates/modules/mirada/mirada-layout/src/layout.rs @@ -1,5 +1,8 @@ //! Modos de teselado — cómo se reparte la pantalla entre ventanas. +use alloc::{vec, vec::Vec}; + +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use crate::geometry::{split, Rect}; @@ -8,8 +11,9 @@ use crate::geometry::{split, Rect}; /// /// Las variantes nuevas se añaden **al final** para no mover los índices /// con que `postcard` las serializa en el API de control. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] pub enum LayoutMode { /// Una ventana maestra a la izquierda; el resto apiladas a la derecha. MasterStack, @@ -49,7 +53,8 @@ impl LayoutMode { } /// Parámetros del teselado. -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct LayoutParams { pub mode: LayoutMode, /// Fracción del ancho para la ventana maestra en `MasterStack` y @@ -108,7 +113,9 @@ fn columns(screen: Rect, count: usize) -> Vec { /// Rejilla `cols × rows` lo más cuadrada posible. fn grid(screen: Rect, count: usize) -> Vec { - let cols = (count as f64).sqrt().ceil() as usize; + // `libm` en vez de los métodos de `f64`: `sqrt`/`ceil` viven en + // `std`, no en `core` — y este crate es `no_std`. + let cols = libm::ceil(libm::sqrt(count as f64)) as usize; let rows = count.div_ceil(cols); let col_parts = split(screen.w, cols); let row_parts = split(screen.h, rows); @@ -162,7 +169,7 @@ fn centered_master(screen: Rect, count: usize, ratio: f32, master_count: usize) return master_stack(screen, count, ratio, master_count); } let ratio = ratio.clamp(0.05, 0.95); - let master_w = (screen.w as f32 * ratio).round() as i32; + let master_w = libm::roundf(screen.w as f32 * ratio) as i32; let sides = split(screen.w - master_w, 2); let (left_w, right_w) = (sides[0].1, sides[1].1); let left_n = stack / 2; @@ -194,7 +201,7 @@ fn master_stack(screen: Rect, count: usize, ratio: f32, master_count: usize) -> .collect(); } let ratio = ratio.clamp(0.05, 0.95); - let master_w = (screen.w as f32 * ratio).round() as i32; + let master_w = libm::roundf(screen.w as f32 * ratio) as i32; let stack_x = screen.x + master_w; let stack_w = screen.w - master_w; diff --git a/crates/modules/mirada/mirada-layout/src/lib.rs b/crates/modules/mirada/mirada-layout/src/lib.rs index 7f2936f..3fe0db2 100644 --- a/crates/modules/mirada/mirada-layout/src/lib.rs +++ b/crates/modules/mirada/mirada-layout/src/lib.rs @@ -12,8 +12,14 @@ //! Todo es determinista y testeable sin un servidor gráfico: la misma //! pantalla y las mismas ventanas dan siempre la misma distribución. +#![cfg_attr(not(test), no_std)] #![forbid(unsafe_code)] +// Lógica pura sobre `core` + `alloc`: sin `std`. Así el mismo motor de +// teselado compila para Linux y para el kernel bare-metal de renaser +// (`x86_64-unknown-none`); el allocator lo aporta el consumidor. +extern crate alloc; + pub mod geometry; pub mod layout; pub mod workspace; diff --git a/crates/modules/mirada/mirada-layout/src/workspace.rs b/crates/modules/mirada/mirada-layout/src/workspace.rs index dbead27..56e4f11 100644 --- a/crates/modules/mirada/mirada-layout/src/workspace.rs +++ b/crates/modules/mirada/mirada-layout/src/workspace.rs @@ -1,7 +1,12 @@ //! `Workspace` — un conjunto de ventanas, su foco y su modo de teselado. -use std::collections::BTreeMap; +use alloc::collections::BTreeMap; +use alloc::vec::Vec; +// El macro `vec!` sólo lo usan los tests de este módulo. +#[cfg(test)] +use alloc::vec; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use crate::geometry::Rect; @@ -11,7 +16,8 @@ use crate::layout::{tile, LayoutMode, LayoutParams}; pub type WindowId = u64; /// Un escritorio: ventanas en orden de teselado + la enfocada + el modo. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Workspace { /// Ventanas en orden de teselado (la 0 es la maestra en `MasterStack`). windows: Vec, diff --git a/crates/modules/mirada/mirada-protocol/Cargo.toml b/crates/modules/mirada/mirada-protocol/Cargo.toml index 73200ea..2983428 100644 --- a/crates/modules/mirada/mirada-protocol/Cargo.toml +++ b/crates/modules/mirada/mirada-protocol/Cargo.toml @@ -8,6 +8,8 @@ publish.workspace = true description = "mirada — contrato Cerebro↔Cuerpo del compositor: comandos de geometría que el Cerebro (GPUI) envía y eventos de hardware/superficies que el Cuerpo (smithay) reporta. Marco postcard con prefijo de longitud." [dependencies] -mirada-layout = { path = "../mirada-layout" } +# `serde` activa los `derive` de los tipos de layout — este crate los +# (de)serializa con postcard. +mirada-layout = { path = "../mirada-layout", features = ["serde"] } serde = { workspace = true } postcard = { workspace = true }