feat(mirada): acción spawn — lanzar programas desde el compositor

Un escritorio sin forma de abrir una terminal no es usable. Ahora el
keymap puede lanzar programas:

- `mirada-protocol`: nuevo `BrainCommand::Spawn(String)`.
- `mirada-brain`: `DesktopAction::Spawn(String)` con forma textual
  `spawn:<comando>` (`Display`/`FromStr`); `Desktop::apply` la traduce
  a `BrainCommand::Spawn`. El keymap por defecto trae
  `Super+Shift+Return` → `spawn:foot`. `DesktopAction` deja de ser
  `Copy` (lleva el comando) — `Keymap::lookup` clona en vez de copiar.
- `mirada-body`: `BodyOp::Spawn(String)`.
- `mirada-compositor`: `exec_op` ejecuta el spawn con un helper
  `spawn_command` (`sh -c`, hereda `WAYLAND_DISPLAY`), que también
  recoge el lanzamiento de `MIRADA_STARTUP` — antes duplicado.

`spawn:foot --title x` también funciona desde `mirada-ctl`. Tests
nuevos del round-trip textual y del flujo atajo→comando.

Nota: un keymap.ron ya existente no recibe el atajo nuevo; hay que
añadir la línea a mano o borrar el archivo para regenerarlo.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 03:59:37 +00:00
parent 90bffec3f1
commit fb3091d995
10 changed files with 76 additions and 16 deletions
@@ -67,7 +67,7 @@ impl Keymap {
/// La acción asociada a una combinación, si la hay.
pub fn lookup(&self, combo: &str) -> Option<DesktopAction> {
self.bindings.get(combo).copied()
self.bindings.get(combo).cloned()
}
/// Las combinaciones a interceptar — el contenido de un `GrabKeys`.
@@ -250,6 +250,7 @@ const KEYMAP_HEADER: &str = "\
// focus-output-next pasa el foco al siguiente monitor
// workspace:N activa el escritorio N (1..9)
// send-to-workspace:N manda la enfocada al escritorio N
// spawn:<comando> lanza un programa (p. ej. spawn:foot)
// quit apaga el compositor
//
// Edita y guarda: mirada recarga el keymap en caliente, sin reiniciar.";