⎇ e94023d8af790ded497f740d7abe811ce0523be9
renaser/kernel/src/compositor.rs
Ñawpa willay
Pi imata llamkarqan
ch'uya
feat(renaser): Fase 8a — el compositor teselante
1// =============================================================================
2// renaser :: kernel/src/compositor.rs — Fase 8 :: el compositor teselante
3// -----------------------------------------------------------------------------
4// Hasta la Fase 7, cada app llevaba su region escrita a mano en el manifiesto:
5// coordenadas fijas, una composicion rigida. La Fase 8 entrega esa decision a
6// un COMPOSITOR: el kernel ya no coloca las ventanas a mano, las TESELA.
7//
8// El motor de teselado es `mirada-layout` — el mismo nucleo `no_std` que
9// ordena las ventanas del compositor Wayland de brahman. Cruza la frontera de
10// workspace y se enlaza aqui sin una linea de codigo nueva: geometria pura,
11// determinista, la misma en Linux y en el bare-metal de renaser.
12//
13// Cada app conserva su tamaño NATURAL —el lienzo que sabe pintar, fijo—; el
14// compositor decide DONDE va ese lienzo. El kernel centra el fotograma natural
15// de la app dentro del marco teselado. Asi el compositor reordena la pantalla
16// sin que ninguna app cambie una sola instruccion.
17// =============================================================================
18
19use alloc::vec::Vec;
20
21use mirada_layout::{tile, LayoutMode, LayoutParams, Rect};
22
23use crate::grafico::RegionPantalla;
24
25/// Altura del strip superior reservado a la consola; las apps teselan debajo.
26/// La consola conserva ahi su registro de arranque completo —seis lineas,
27/// hasta la sonda asincrona de disco— legible sobre el teselado.
28const FRANJA_CONSOLA: usize = 296;
29
30/// El modo de teselado del compositor. Fijo por ahora — la Fase 8b lo hara
31/// conmutable en caliente desde el teclado, recorriendo los siete modos que
32/// `mirada-layout` ofrece.
33const MODO: LayoutMode = LayoutMode::MasterStack;
34
35/// Margen entre ventanas teseladas, en pixeles — el aire que separa un marco
36/// de sus vecinos.
37const MARGEN: i32 = 14;
38
39/// El area de pantalla que el compositor tesela: toda la pantalla menos la
40/// franja de la consola en la cima.
41pub fn area_apps(ancho_pantalla: usize, alto_pantalla: usize) -> RegionPantalla {
42 RegionPantalla {
43 x: 0,
44 y: FRANJA_CONSOLA.min(alto_pantalla),
45 ancho: ancho_pantalla,
46 alto: alto_pantalla.saturating_sub(FRANJA_CONSOLA),
47 }
48}
49
50/// Tesela el area de apps en `n` marcos —uno por ventana, en el orden de las
51/// apps del manifiesto— con el algoritmo de `mirada-layout`. El vector
52/// resultante tiene exactamente `n` elementos.
53pub fn disponer(n: usize, ancho_pantalla: usize, alto_pantalla: usize) -> Vec<RegionPantalla> {
54 let area = area_apps(ancho_pantalla, alto_pantalla);
55 let pantalla = Rect::new(
56 area.x as i32,
57 area.y as i32,
58 area.ancho as i32,
59 area.alto as i32,
60 );
61 let params = LayoutParams {
62 mode: MODO,
63 gap: MARGEN,
64 ..LayoutParams::default()
65 };
66 tile(pantalla, n, ¶ms)
67 .into_iter()
68 .map(rect_a_region)
69 .collect()
70}
71
72/// Traduce un `Rect` de `mirada-layout` (`i32`, en teoria con signo) a la
73/// `RegionPantalla` del kernel (`usize`). Un rectangulo degenerado queda en
74/// cero — el kernel no compondra nada en el.
75fn rect_a_region(r: Rect) -> RegionPantalla {
76 RegionPantalla {
77 x: r.x.max(0) as usize,
78 y: r.y.max(0) as usize,
79 ancho: r.w.max(0) as usize,
80 alto: r.h.max(0) as usize,
81 }
82}