diff --git a/renaser/CHANGELOG.md b/renaser/CHANGELOG.md index 9a5d1f8..081628c 100644 --- a/renaser/CHANGELOG.md +++ b/renaser/CHANGELOG.md @@ -946,3 +946,65 @@ enfocar y arrastre del marco de las ventanas flotantes. envuelve a `pulso`. `Alt+F` la flota; el ratón la agarra y la arrastra de la esquina superior izquierda al centro-abajo de la pantalla con el botón sostenido. El kernel sigue estable a través de los gestos. + +## Mapeador MMIO en el kernel — 2026-05-23 + +OVMF aloja los BAR prefetchables 64-bit de virtio en la ventana PCI de 64 +bits, que el `bootloader_api` no mapea. `KernelHal::mmio_phys_to_virt` +devolvía `phys + offset` a ciegas y el primer registro MMIO leído reventaba +con #PF, dejando una franja roja sin pista visible. La autopsia: el commit +anterior añadió el dump del panic-handler por COM1, que sacó a la luz el IP +en `unchecked_mul::precondition_check` y la dirección de fallo +`offset + 0x800000014` — phys 32 GiB, donde OVMF había puesto el BAR. + +### Añadido +- `memory::mmio`: envuelve la tabla L4 activa (vía `Cr3` + el mapeo de + memoria física del cargador) en un `OffsetPageTable`. `mapear(fisica, + tam)` abre páginas hacia la región pedida con `PRESENT | WRITABLE | + NO_CACHE | WRITE_THROUGH`, tratando `PageAlreadyMapped` y + `ParentEntryHugePage` como éxito silencioso. +- Los marcos para tablas intermedias salen del banco DMA del disco + (`asignar_marco_para_tabla`, sin pánico). +- `KernelHal::mmio_phys_to_virt` llama a `memory::mmio::mapear` antes de + devolver el puntero, asegurándose de que el BAR sea accesible. + +### Cambiado +- `baliza::Serie` es ahora `pub(crate)`: cualquier módulo puede dejar + trazas por COM1. El panic-handler y el OOM-handler dejan en COM1 su + mensaje y ubicación además de pintar la franja. `kernel_main` traza + cada hito del arranque para diagnóstico remoto. + +## Fase 14 — La identidad del escritorio: nombres y barra de tareas — 2026-05-23 + +Las ventanas eran anónimas: el escritorio reía con sus colores pero no sabía +cómo se llama lo que muestra. La Fase 14 le da nombre a cada cuarto y una +barra al pie con la lista de quien vive en la casa. + +### Añadido +- Cada `Ventana` lleva un `nombre: String` —el que dicta su `EntradaApp` del + manifiesto, o el que el orquestador pasa al engendrarla en vivo (Fase 10)—. + `Plantilla` se acuerda del nombre para los lanzamientos posteriores. +- **`FRANJA_TASKBAR`** (40 px al pie) y `area_taskbar`: la barra de tareas + vive en su propia franja. `area_apps` la descuenta — las ventanas teselan + y flotan SIN tapar la barra ni la consola de la cima. +- `consola`: tipos `Taskbar` y `CeldaTaskbar`; métodos `pintar_taskbar` + (fondo + línea divisoria + una pestaña por ventana viva) y + `pintar_etiqueta` (rasteriza una cadena en un punto fijo, sin tocar la + pluma de la consola). La pestaña enfocada lleva el índigo del foco; las + desalojadas, su color de baliza; las demás, el slate del panel. +- `compositor::recomponer` arma la lista de celdas y la pasa a la consola + junto con las capas: un único repintado, una única presentación. +- `atender_raton`: un clic dentro de la franja de la barra busca su pestaña + con `celda_taskbar_en` y enfoca la ventana correspondiente (sin iniciar + arrastre). El comportamiento sobre el área de apps queda intacto. + +### Cambiado +- `compositor::fundar` y `nacer_ventana` exigen un nombre para cada ventana. + `cargar_userspace` lo toma de `EntradaApp.nombre`; `lanzar_app`, de + `Plantilla.nombre`. + +### Verificado +- QEMU. Tras arrancar se ve la barra al pie con las 7 pestañas (`tonada` + enfocada, índigo), las desalojadas en sus colores de baliza. Un clic + sobre `pulso` cambia el foco al instante: el borde índigo del compositor + deja la maestra y envuelve a `pulso`, y la pestaña `pulso` se ilumina. diff --git a/renaser/CLAUDE.md b/renaser/CLAUDE.md index 8ed7150..fe80f58 100644 --- a/renaser/CLAUDE.md +++ b/renaser/CLAUDE.md @@ -81,9 +81,11 @@ COMPLETA —orden-Z y ventanas flotantes: composición con solapamiento (`Alt+F` la Fase 10 COMPLETA —alta y baja de aplicaciones en vivo (`Alt+N` / `Alt+Q`)—, la Fase 11 COMPLETA —el reloj del sistema como capacidad de host (`sys_tiempo_mono`) + la app `pulso`—, la Fase 12 COMPLETA —la bocina del PC -como capacidad de host (`sys_tono`) + la app `tonada`— y la Fase 13 COMPLETA -—ratón PS/2, puntero, clic-para-enfocar y arrastre de ventanas flotantes—. -Todo verificado en QEMU. Ver `ROADMAP.md`. +como capacidad de host (`sys_tono`) + la app `tonada`—, la Fase 13 COMPLETA +—ratón PS/2, puntero, clic-para-enfocar y arrastre de ventanas flotantes—, +infraestructura `memory::mmio` (mapeador propio de regiones MMIO en la tabla +L4) y la Fase 14 COMPLETA —nombres en cada ventana y barra de tareas con +clic-para-enfocar—. Todo verificado en QEMU. Ver `ROADMAP.md`. ## Flujo de trabajo diff --git a/renaser/DIARIO.md b/renaser/DIARIO.md index 55661ef..5b70cff 100644 --- a/renaser/DIARIO.md +++ b/renaser/DIARIO.md @@ -496,6 +496,23 @@ maceta de un balcón al otro. La mano suelta, el cuarto se queda donde lo dejó. Por fin la disposición no la dicta sólo la casa: también la conversación entre quien vive dentro y quien habita fuera. +## Los nombres — un cartel en cada puerta + +La casa tenía buen olfato para colorear, pero un vicio antiguo: nunca decía cómo +se llamaba lo que mostraba. Las ventanas eran rectángulos sin etiqueta —«¿cuál +era la que cantaba?», «¿cuál la que cuenta los arranques?»—. La casa entendía, +nosotros adivinábamos. Hoy, al pie de la pantalla, le ha brotado un zócalo +estrecho con un cartel por cada inquilino: el nombre escrito, ordenadito, de +izquierda a derecha. La que tiene la mirada de la casa luce su cartel con el +índigo del foco; las que se rompieron, con su color de luto —violeta o crema +según la causa—; las demás, en gris discreto, esperando turno. + +Y la barra no sólo dice: también ESCUCHA. Tocar un cartel con el dedo es ir al +cuarto que ese cartel nombra. La casa entiende sin más explicaciones: cambia la +mirada al inquilino elegido, su borde se ilumina, y el escritorio se recoloca +para honrarlo. Por fin la casa no se navega sólo a tientas con flechas: tiene un +directorio en su umbral. + --- *El diario continúa. La próxima página la escribirá la próxima jornada.* diff --git a/renaser/ROADMAP.md b/renaser/ROADMAP.md index f352c68..08d87dd 100644 --- a/renaser/ROADMAP.md +++ b/renaser/ROADMAP.md @@ -228,6 +228,33 @@ clic-para-enfocar y arrastre del marco de las flotantes. Verificada en QEMU cualquier ventana viva); si la enfocada flota, arranca un ARRASTRE con el desfase de agarre; el botón sostenido la sigue al puntero; al soltar, fin. +## Fase 14 — la identidad del escritorio: nombres y barra de tareas (completada) + +Las ventanas eran anónimas; el escritorio no sabía nombrar lo que mostraba. La +Fase 14 le pone un nombre a cada cuarto y una barra al pie con la lista de +quienes lo habitan. Verificada en QEMU. + +- Cada `Ventana` lleva un `nombre: String` —el del manifiesto, o el del + orquestador al engendrarla en vivo—. `Plantilla` lo guarda para las copias. +- Una franja de 40 px al pie reservada como `area_taskbar`. `area_apps` la + descuenta — las ventanas teselan y flotan sin tapar la barra ni la consola. +- `consola` gana los tipos `Taskbar` / `CeldaTaskbar` y los métodos + `pintar_taskbar` y `pintar_etiqueta`. La pestaña enfocada lleva el índigo del + foco; la desalojada, su color de baliza; el resto, el slate. +- Un clic dentro de la barra enfoca la ventana de la pestaña pulsada, sin + iniciar arrastre. El compositor encuentra la celda con `celda_taskbar_en`. + +## Mejora estructural — mapeador MMIO en el kernel (entre fases 13 y 14) + +Los BAR prefetchables 64-bit que OVMF aloja en la ventana PCI de 64 bits NO +los mapea `bootloader_api`. El kernel gana `memory::mmio`, que envuelve la +tabla L4 activa y abre páginas hacia las regiones MMIO que virtio-drivers le +pide. `KernelHal::mmio_phys_to_virt` llama al mapeador antes de devolver el +puntero. Trata `PageAlreadyMapped` y `ParentEntryHugePage` como éxito +silencioso. Los marcos para tablas intermedias salen del banco DMA. Esta +mejora resolvió el #PF inexplicable en máquinas con un OVMF que coloca el BAR +del virtio-blk fuera de los primeros 4 GiB. + Líneas abiertas posteriores: reciclado de las ranuras de ventana cerradas; audio con varias voces (PCM) más allá del tono único de la bocina. diff --git a/renaser/kernel/src/compositor.rs b/renaser/kernel/src/compositor.rs index d8d4240..ec75a64 100644 --- a/renaser/kernel/src/compositor.rs +++ b/renaser/kernel/src/compositor.rs @@ -47,6 +47,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; +use alloc::string::{String, ToString}; use alloc::vec; use alloc::vec::Vec; @@ -54,7 +55,7 @@ use crossbeam_queue::ArrayQueue; use mirada_layout::{tile, LayoutMode, LayoutParams, Rect}; use spin::{Mutex, Once}; -use crate::consola::{self, Capa, Contenido}; +use crate::consola::{self, Capa, CeldaTaskbar, Contenido, Taskbar}; use crate::grafico::{Color, RegionPantalla}; /// Altura del strip superior reservado a la consola; las apps teselan debajo. @@ -62,6 +63,17 @@ use crate::grafico::{Color, RegionPantalla}; /// hasta la sonda asincrona de disco— legible sobre el teselado. const FRANJA_CONSOLA: usize = 296; +/// Altura de la barra de tareas inferior (Fase 14): cada ventana viva tiene +/// ahi una pestaña con su nombre, que el clic enfoca. +const FRANJA_TASKBAR: usize = 40; + +/// Anchura de cada celda de la barra de tareas, en pixeles. +const CELDA_TASKBAR_ANCHO: usize = 156; +/// Hueco entre celdas adyacentes de la barra. +const CELDA_TASKBAR_HUECO: usize = 6; +/// Margen izquierdo de la primera celda. +const CELDA_TASKBAR_MARGEN: usize = 16; + /// El modo de teselado con que arranca el escritorio. El teclado lo cicla. const MODO_INICIAL: LayoutMode = LayoutMode::MasterStack; @@ -116,6 +128,9 @@ struct Arrastre { /// Una ventana del escritorio: una app, su geometria y su ultimo fotograma. struct Ventana { + /// Nombre legible de la app — el que dicta su `EntradaApp` del manifiesto. + /// Aparece en la pestaña de la barra de tareas (Fase 14). + nombre: String, /// Tamaño natural del lienzo de la app — lo que sabe pintar, fijo. natural_ancho: usize, natural_alto: usize, @@ -190,12 +205,13 @@ static PARTOS: AtomicUsize = AtomicUsize::new(0); /// Funda el escritorio: crea una ventana por app, con su marco teselado inicial /// y su cache de respaldo ya reservada al tamaño natural. `naturales` da el /// `(ancho, alto)` del lienzo de cada app, en el orden del manifiesto. -pub fn fundar(ancho: usize, alto: usize, naturales: &[(usize, usize)]) { +pub fn fundar(ancho: usize, alto: usize, naturales: &[(usize, usize, &str)]) { MANDOS.call_once(|| ArrayQueue::new(CAPACIDAD_MANDOS)); let mut ventanas = Vec::with_capacity(naturales.len()); - for &(nat_ancho, nat_alto) in naturales { + for &(nat_ancho, nat_alto, nombre) in naturales { ventanas.push(Ventana { + nombre: nombre.to_string(), natural_ancho: nat_ancho, natural_alto: nat_alto, // Marco provisional; `aplicar_teselado` lo fija enseguida. @@ -581,7 +597,77 @@ fn recomponer(escritorio: &Escritorio) { enfocada: indice == foco, }); } - consola::recomponer(area, &capas); + + // FASE 14 :: armar las celdas de la barra de tareas. Una pestaña por + // ventana viva (no cerrada), de izquierda a derecha, con el nombre de la + // app; la enfocada lleva el color indigo del foco, las desalojadas su + // baliza, las demas el slate del panel. El clic sobre una pestaña enfoca + // su ventana. + let area_bar = area_taskbar(escritorio.ancho, escritorio.alto); + let mut celdas: Vec = Vec::new(); + let mut cx = area_bar.x + CELDA_TASKBAR_MARGEN; + let cy = area_bar.y + 4; + let calto = area_bar.alto.saturating_sub(8); + for (indice, ventana) in escritorio.ventanas.iter().enumerate() { + if ventana.cerrada { + continue; + } + if cx + CELDA_TASKBAR_ANCHO > area_bar.x + area_bar.ancho { + break; + } + let fondo = match ventana.baliza { + Some(color) => color, + None if indice == foco => Color::FOCO, + None => Color::PANEL, + }; + celdas.push(CeldaTaskbar { + region: RegionPantalla { + x: cx, + y: cy, + ancho: CELDA_TASKBAR_ANCHO, + alto: calto, + }, + nombre: &ventana.nombre, + fondo, + tinta: Color::TEXTO, + }); + cx += CELDA_TASKBAR_ANCHO + CELDA_TASKBAR_HUECO; + } + let taskbar = Taskbar { + area: area_bar, + celdas: &celdas, + }; + consola::recomponer(area, &capas, &taskbar); +} + +/// Localiza la celda de la barra de tareas bajo la coordenada x: itera las +/// ventanas vivas en orden de creacion y devuelve la N-esima donde la N es la +/// posicion en la barra. `None` si el clic cae en un hueco entre celdas, antes +/// del margen, o pasada la ultima. +fn celda_taskbar_en(escritorio: &Escritorio, x: usize) -> Option { + let area_bar = area_taskbar(escritorio.ancho, escritorio.alto); + let margen_izq = area_bar.x + CELDA_TASKBAR_MARGEN; + if x < margen_izq { + return None; + } + let rel = x - margen_izq; + let paso = CELDA_TASKBAR_ANCHO + CELDA_TASKBAR_HUECO; + let posicion = rel / paso; + let offset = rel % paso; + if offset >= CELDA_TASKBAR_ANCHO { + return None; + } + let mut k = 0; + for (indice, ventana) in escritorio.ventanas.iter().enumerate() { + if ventana.cerrada { + continue; + } + if k == posicion { + return Some(indice); + } + k += 1; + } + None } // ============================================================================= @@ -642,13 +728,14 @@ fn cerrar() { /// con su cache de respaldo al tamaño natural, la añade al final del orden de /// teselado, recalcula el teselado y recompone. La invoca el orquestador del /// kernel justo antes de instanciar el WASM de la app, que necesita ese indice. -pub fn nacer_ventana(nat_ancho: usize, nat_alto: usize) -> usize { +pub fn nacer_ventana(nat_ancho: usize, nat_alto: usize, nombre: &str) -> usize { let Some(escritorio) = ESCRITORIO.get() else { return 0; }; let mut escritorio = escritorio.lock(); let indice = escritorio.ventanas.len(); escritorio.ventanas.push(Ventana { + nombre: nombre.to_string(), natural_ancho: nat_ancho, natural_alto: nat_alto, marco: RegionPantalla { @@ -716,8 +803,24 @@ pub fn atender_raton() { let y = evento.y as usize; let izq_antes = escritorio.raton_izq; if izq && !izq_antes { - // Boton bajó: un CLIC sobre el punto (x, y). - if let Some(v) = ventana_en(&escritorio, x, y) { + // Boton bajó: un CLIC. Si cae en la barra de tareas, enfocar la + // pestaña pulsada SIN iniciar arrastre. Si no, comportamiento + // habitual: enfocar la ventana topmost bajo el puntero. + let area_bar = area_taskbar(escritorio.ancho, escritorio.alto); + if y >= area_bar.y && y < area_bar.y + area_bar.alto { + if let Some(v) = celda_taskbar_en(&escritorio, x) { + let viva = { + let w = &escritorio.ventanas[v]; + w.baliza.is_none() && !w.cerrada + }; + if viva { + FOCO.store(v, Ordering::Relaxed); + crate::drivers::altavoz::tono(0); + alzar_si_flota(&mut escritorio, v); + cambio = true; + } + } + } else if let Some(v) = ventana_en(&escritorio, x, y) { let viva = { let w = &escritorio.ventanas[v]; w.baliza.is_none() && !w.cerrada @@ -835,13 +938,26 @@ pub fn refrescar_puntero() { // ============================================================================= /// El area de pantalla que el compositor tesela: toda la pantalla menos la -/// franja de la consola en la cima. +/// franja de la consola en la cima y la barra de tareas al pie. pub fn area_apps(ancho_pantalla: usize, alto_pantalla: usize) -> RegionPantalla { + let cabeza = FRANJA_CONSOLA.min(alto_pantalla); + let pie = FRANJA_TASKBAR.min(alto_pantalla.saturating_sub(cabeza)); RegionPantalla { x: 0, - y: FRANJA_CONSOLA.min(alto_pantalla), + y: cabeza, ancho: ancho_pantalla, - alto: alto_pantalla.saturating_sub(FRANJA_CONSOLA), + alto: alto_pantalla.saturating_sub(cabeza).saturating_sub(pie), + } +} + +/// El area de la barra de tareas: una franja al pie de la pantalla. +fn area_taskbar(ancho_pantalla: usize, alto_pantalla: usize) -> RegionPantalla { + let pie = FRANJA_TASKBAR.min(alto_pantalla); + RegionPantalla { + x: 0, + y: alto_pantalla.saturating_sub(pie), + ancho: ancho_pantalla, + alto: pie, } } diff --git a/renaser/kernel/src/consola.rs b/renaser/kernel/src/consola.rs index 8fa6800..daf542d 100644 --- a/renaser/kernel/src/consola.rs +++ b/renaser/kernel/src/consola.rs @@ -67,6 +67,24 @@ pub(crate) struct Capa<'a> { pub(crate) enfocada: bool, } +/// Una pestaña de la barra de tareas (Fase 14): una región de pantalla, el +/// nombre de la app y los colores con que pintarla. Las arma el compositor +/// con una pestaña por ventana viva. +pub(crate) struct CeldaTaskbar<'a> { + pub(crate) region: RegionPantalla, + pub(crate) nombre: &'a str, + /// Color de fondo: indigo del foco, slate del panel, o color de baliza. + pub(crate) fondo: Color, + /// Color de la tinta del texto. + pub(crate) tinta: Color, +} + +/// La barra de tareas del escritorio (Fase 14): su area y sus pestañas. +pub(crate) struct Taskbar<'a> { + pub(crate) area: RegionPantalla, + pub(crate) celdas: &'a [CeldaTaskbar<'a>], +} + /// La consola grafica de renaser: doble bufer, pantalla fisica y pluma. pub(crate) struct Consola { lienzo: Lienzo, @@ -224,7 +242,7 @@ impl Consola { /// flotantes se resuelve por si solo, sin recortes ni mascaras. Cada capa /// pinta primero su panel —el cromo de la ventana— y, encima, su contenido; /// una sola presentacion cierra la pasada. - fn recomponer(&mut self, area: RegionPantalla, capas: &[Capa]) { + fn recomponer(&mut self, area: RegionPantalla, capas: &[Capa], taskbar: &Taskbar) { self.lienzo.rellenar_rect( area.x, area.y, @@ -252,9 +270,72 @@ impl Consola { } self.dibujar_borde(m, capa.enfocada); } + self.pintar_taskbar(taskbar); self.presentar(); } + /// Pinta la barra de tareas como ultima capa del escritorio (Fase 14): el + /// fondo de la franja, una linea fina arriba que la separa de las apps, y + /// las pestañas —cada una su rectángulo y su nombre—. + fn pintar_taskbar(&mut self, taskbar: &Taskbar) { + // Fondo de la barra y linea de separacion. + self.lienzo.rellenar_rect( + taskbar.area.x, + taskbar.area.y, + taskbar.area.ancho, + taskbar.area.alto, + Color::PANEL, + ); + self.lienzo + .rellenar_rect(taskbar.area.x, taskbar.area.y, taskbar.area.ancho, 1, Color::SIN_FOCO); + // Las pestañas. + for celda in taskbar.celdas { + let r = celda.region; + self.lienzo + .rellenar_rect(r.x, r.y, r.ancho, r.alto, celda.fondo); + // El nombre, alineado a la izquierda de la pestaña, vertical- + // centrado a la altura visible de la franja. + let base_y = r.y + (r.alto + 14) / 2; + self.pintar_etiqueta(r.x + 10, base_y, celda.nombre, 16.0, celda.fondo, celda.tinta); + } + } + + /// Rasteriza una cadena de texto a un tamaño dado, en (x, base_y), sobre + /// un fondo conocido —del que toma la mezcla por cobertura del glifo—. Es + /// la version sin estado de la pluma: el llamante decide donde escribir. + fn pintar_etiqueta( + &mut self, + x: usize, + base_y: usize, + texto: &str, + tamaño: f32, + fondo: Color, + tinta: Color, + ) { + let mut cursor = x; + for caracter in texto.chars() { + let (metricas, cobertura) = texto::rasterizar(caracter, tamaño); + let inicio_x = cursor as isize + metricas.xmin as isize; + let inicio_y = base_y as isize - metricas.ymin as isize - metricas.height as isize; + for fila in 0..metricas.height { + for col in 0..metricas.width { + let opacidad = cobertura[fila * metricas.width + col]; + if opacidad == 0 { + continue; + } + let px = inicio_x + col as isize; + let py = inicio_y + fila as isize; + if px < 0 || py < 0 { + continue; + } + let color = mezclar(fondo, tinta, opacidad); + self.lienzo.pintar_pixel(px as usize, py as usize, color); + } + } + cursor += metricas.advance_width as usize; + } + } + /// Inunda una region entera con un color plano —la baliza de desalojo: una /// app que falla tatua su marco de purpura— y le traza su borde de foco. fn pintar_region(&mut self, region: RegionPantalla, color: Color, enfocada: bool) { @@ -328,9 +409,9 @@ pub(crate) fn volcar_marco( /// La invoca `compositor` al arrancar y siempre que hay ventanas flotantes: el /// solapamiento obliga a repintar el escritorio en bloque, no ventana a /// ventana. Las capas llegan ya ordenadas de atras hacia adelante. -pub(crate) fn recomponer(area: RegionPantalla, capas: &[Capa]) { +pub(crate) fn recomponer(area: RegionPantalla, capas: &[Capa], taskbar: &Taskbar) { if let Some(consola) = CONSOLA.get() { - consola.lock().recomponer(area, capas); + consola.lock().recomponer(area, capas, taskbar); } } diff --git a/renaser/kernel/src/main.rs b/renaser/kernel/src/main.rs index 5d53b35..b2a2816 100644 --- a/renaser/kernel/src/main.rs +++ b/renaser/kernel/src/main.rs @@ -105,6 +105,9 @@ fn traza(rotulo: &str) { /// su bytecode —cacheado en RAM al arrancar, para no volver al disco despues— /// y la geometria y la cuota de memoria con que instanciarla. struct Plantilla { + /// Nombre legible de la app — el del manifiesto, que la barra de tareas + /// (Fase 14) muestra en la pestaña. + nombre: alloc::string::String, bytecode: Vec, nat_ancho: usize, nat_alto: usize, @@ -227,6 +230,7 @@ fn encender_app( // un molde en RAM con que `Alt+N` instanciara copias en vivo, sin volver al // disco —que la E/S por sondeo en mitad del reactor seria un mal vecino—. Some(Plantilla { + nombre: entrada.nombre.clone(), bytecode, nat_ancho: natural.ancho, nat_alto: natural.alto, @@ -252,7 +256,7 @@ fn lanzar_app() { // La ventana nace primero: el compositor le entrega su indice —su // identidad—, que el WASM necesita para hallar su ventana y su canal. - let indice = compositor::nacer_ventana(plantilla.nat_ancho, plantilla.nat_alto); + let indice = compositor::nacer_ventana(plantilla.nat_ancho, plantilla.nat_alto, &plantilla.nombre); match wasm::AplicacionWasm::cargar( &plantilla.bytecode, plantilla.nat_ancho, @@ -318,10 +322,10 @@ fn cargar_userspace(ejecutor: &mut Executor, ancho_pantalla: usize, alto_pantall // con su cache de respaldo y su marco teselado por `mirada-layout`— y // pintar el escenario antes de encender las apps: el teselado se ve // aunque alguna app no llegue a pintar su primer fotograma. - let naturales: Vec<(usize, usize)> = m + let naturales: Vec<(usize, usize, &str)> = m .apps .iter() - .map(|e| (e.region_ancho as usize, e.region_alto as usize)) + .map(|e| (e.region_ancho as usize, e.region_alto as usize, e.nombre.as_str())) .collect(); compositor::fundar(ancho_pantalla, alto_pantalla, &naturales); compositor::componer_escenario();