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 }