feat(desktop): home app (system-only launch cap, LAUNCH_BADGE: apps+launch only), pm starts it with session (relaunch <=5); display keys F1/Alt+Tab next, F2 home, F4 close app (ROLE from launcher, terminal exempt), close returns to previous window; closed window -> app exits; shell 'name &'; launch by id; pm stack 8, storage 16 clients

This commit is contained in:
2026-10-28 15:50:05 +01:00
parent c3eb70191b
commit 18e8b3ecb8
29 changed files with 520 additions and 68 deletions

View File

@@ -140,8 +140,11 @@ fn refused(what: &str, r: Refused) {
}
/// Runs app `args[0]` with `args` in the current folder, and waits for it
/// to finish or Ctrl+C.
/// to finish or Ctrl+C; with a last argument `&`, does not wait.
fn run_program(sh: &mut Shell, args: &[&str]) {
if let Some((&"&", args)) = args.split_last() {
return start_program(sh, args);
}
let folder = sh.fs.grant(sh.cwd.as_bytes(), false).ok();
// A Ctrl+C typed since the last program is not for this one.
let _ = syscall::poll(sh.done);
@@ -166,6 +169,21 @@ fn run_program(sh: &mut Shell, args: &[&str]) {
}
}
/// Starts app `args[0]` and lets it run on its own (its window, if it has
/// one, is closed with F4). It does not get the current folder: nobody
/// would be there to take the grant back when it is done.
fn start_program(sh: &mut Shell, args: &[&str]) {
let Some(name) = args.first() else { return println!("usage: <app> [args] &") };
match sh.apps.launch(args, Some(TERMINAL), None) {
Ok((process, _)) => {
// Not waited on: the handle is not needed.
syscall::drop_cap(process);
println!("{} started", name);
}
Err(r) => refused(name, r),
}
}
/// Installs the app in folder `from` (its manifest and binary); the owner
/// is asked on the terminal.
fn install(sh: &mut Shell, from: &str) {
@@ -232,6 +250,7 @@ fn run(sh: &mut Shell, line: &str) {
println!("anything else runs an app: try ls, cat readme.txt, snake");
println!("apps see the current directory, read-only, and only what you allowed");
println!("Ctrl+C stops a running program; snake quits with q");
println!("end with & to leave it running (snake &); F4 closes the app in front");
}
Some("apps") => list(sh),
Some("install") => match args.get(1) {