# llimphi-wawa > The [llimphi](../README.md) shell over the kernel framebuffer. Closes the `View → mount → layout → paint → blit` cycle **without winit, without a GPU and without `std`**. It is the `llimphi-ui` twin for wawa: same compositor, same composition, different skin. W3.c of [`PLAN-LLIMPHI.md`](../../../03_ukupacha/wawa/PLAN-LLIMPHI.md). Deliberately thin: it does not reimplement a single line of the compositor. The tree, taffy layout, paint and hit-test are the **same code** that runs on Linux, compiled with different features. ## Usage ```rust let mut cascara = Cascara::new(width, height); // Per frame: let montado = cascara.fotograma(my_view); cascara.volcar(framebuffer, stride_bytes, Formato::Bgra8); // When a click arrives from the kernel: if let Some(msg) = cascara.click(&montado, x, y) { model = App::update(model, msg); } ``` ## What it does NOT do, on purpose - **No loop of its own.** The kernel's cooperative reactor is in charge; the shell offers `fotograma()` and `click()` for it to call when appropriate. A loop here would fight the one outside. - **It does not know the time.** The frame instant arrives as an argument (the kernel reads it off its PIT) — the same discipline `llimphi_compositor::Instant` imposes by having no `now()`. - **It does not touch hardware.** It takes a `&mut [u8]` and its stride. Who mapped that memory — firmware GOP, virtio-gpu scanout — is the kernel's business. ## The other path: scenes arriving over the wire (W4) `fotograma()` takes a `View` and mounts it here. But a `.wasm` app composes **on the far side of the boundary** and ships the finished result as a [`llimphi-wire-escena`](../llimphi-wire-escena/README.md). That's what the twin is for: ```rust let recibida: EscenaWire = postcard::from_bytes(&bytes)?; let st = cascara.fotograma_wire(&recibida); // st.textos = how many strings were shaped on THIS side — the point of W4.1 ``` From `pintar` down it is the same code: the kernel needs no second rasterizer because there are no two kinds of drawing. Three things worth knowing about this path: - **The `Typesetter` is the shell's**, not a fresh one. Text arrives unshaped and is resolved here, so the cache must survive between frames — a new one per frame would make every frame "cold" (3.4 fps instead of 53, per W4.1). - **It does not trust the wire.** The scene comes from a sandboxed app: out-of-range style indices and images without a blob are counted in `EstadisticasReproduccion` and skipped. An `unwrap` there would be a Ring 0 panic triggerable from userspace. - **There is no hit-testing, and that is correct.** The node tree stayed on the far side of the boundary; the app is who knows what sits under the pointer. Input travels back as a coordinate. ## Deps - `llimphi-compositor` (feature `cpu`) · `llimphi-cpu` · `llimphi-text` · `llimphi-layout` · `llimphi-wire-escena` Feature `std`: run the shell on the host, for tests. The default is `libm` — the bare-metal profile this crate exists for.