diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-20 13:47:10 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-20 13:47:10 +0200 |
| commit | cb17c57452ccd2ccca77e99098402d4b9f61c0a5 (patch) | |
| tree | 6566e0ddaa764c6675e9a56f03772de345170992 /shell/src | |
| parent | wm: integrate home terminal as window 0 + fix console focus after close (diff) | |
| download | rs-dos-cb17c57452ccd2ccca77e99098402d4b9f61c0a5.tar.gz rs-dos-cb17c57452ccd2ccca77e99098402d4b9f61c0a5.zip | |
wm: F1 spawns a windowed shell — real shell, not a duplicate
Architecture:
- vt: ACTIVE terminal redirect — when set, all gop_print!/put_char/write_str
go there instead of HOME. Terminal::from_buffer() renders into a
WM-owned pixel buffer.
- tty: read_line_from_queue() — canonical-mode line input from the task's
own message queue (TaskMsg::Key). Returns None on Close.
- shell: run_windowed() — same shell as the console but reads from the
message queue. Returns on ^D or window close.
- wm: F1 calls SPAWN_TERMINAL_CB (set by rsdos). No shell logic in the WM.
- rsdos: terminal_task callback + terminal_entry task — creates a 640x400
chrome window, wires up Terminal::from_buffer, sets ACTIVE, runs
shell::run_windowed(), cleans up on exit.
- shell: 'term' debug command that invokes the callback directly and
logs each step to serial.
Diffstat (limited to 'shell/src')
| -rw-r--r-- | shell/src/lib.rs | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/shell/src/lib.rs b/shell/src/lib.rs index f1addd9..6077f35 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs | |||
| @@ -93,6 +93,30 @@ pub fn run() -> ! { | |||
| 93 | } | 93 | } |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /// Run a shell instance inside a windowed terminal. Same as `run()` but | ||
| 97 | /// reads from the task's message queue (Fed by the WM input pump) and | ||
| 98 | /// writes to the active terminal (set by the caller via `vt::set_active`). | ||
| 99 | /// Returns when the window is closed (Close message or ^D on empty line). | ||
| 100 | pub fn run_windowed() { | ||
| 101 | term_println(&alloc::format!("rs-dos v{}", env!("CARGO_PKG_VERSION"))); | ||
| 102 | loop { | ||
| 103 | rsnix::vt::sync_scroll(); | ||
| 104 | term_print("> "); | ||
| 105 | match tty::read_line_from_queue() { | ||
| 106 | None => return, // window closed | ||
| 107 | Some(LineInput::Interrupted) => continue, | ||
| 108 | Some(LineInput::Eof) => return, // ^D in windowed mode = close | ||
| 109 | Some(LineInput::Line(line)) => { | ||
| 110 | let trimmed = line.trim(); | ||
| 111 | if trimmed.is_empty() { | ||
| 112 | continue; | ||
| 113 | } | ||
| 114 | execute(trimmed); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 96 | // --------------------------------------------------------------------------- | 120 | // --------------------------------------------------------------------------- |
| 97 | // Diagnostics and command output go straight to terminal + serial, never | 121 | // Diagnostics and command output go straight to terminal + serial, never |
| 98 | // through the filter pipeline and never into a file sink. These helpers | 122 | // through the filter pipeline and never into a file sink. These helpers |
| @@ -741,6 +765,7 @@ write `{} <path> TIL <marker>`", | |||
| 741 | "rm" => cmd_rm(&parsed), | 765 | "rm" => cmd_rm(&parsed), |
| 742 | "edit" => cmd_edit(&parsed), | 766 | "edit" => cmd_edit(&parsed), |
| 743 | "draw" => cmd_draw(&parsed), | 767 | "draw" => cmd_draw(&parsed), |
| 768 | "term" => cmd_term(&parsed), | ||
| 744 | "windows" => cmd_windows(&parsed), | 769 | "windows" => cmd_windows(&parsed), |
| 745 | "restore" => cmd_restore(&parsed), | 770 | "restore" => cmd_restore(&parsed), |
| 746 | "bg" => cmd_bg(&parsed), | 771 | "bg" => cmd_bg(&parsed), |
| @@ -800,6 +825,7 @@ fn cmd_help(_p: &Parsed) { | |||
| 800 | touch - create an empty file | 825 | touch - create an empty file |
| 801 | rm - remove a file or empty dir | 826 | rm - remove a file or empty dir |
| 802 | edit - full-screen editor (^S save, ^X exit, ^W search) | 827 | edit - full-screen editor (^S save, ^X exit, ^W search) |
| 828 | term - spawn a windowed terminal (F1 also works) | ||
| 803 | halt - halt the system (hlt loop) | 829 | halt - halt the system (hlt loop) |
| 804 | poweroff - shut down via ACPI (ResetSystem) | 830 | poweroff - shut down via ACPI (ResetSystem) |
| 805 | exit - alias for poweroff | 831 | exit - alias for poweroff |
| @@ -1401,6 +1427,26 @@ fn cmd_draw(_p: &Parsed) { | |||
| 1401 | } | 1427 | } |
| 1402 | } | 1428 | } |
| 1403 | 1429 | ||
| 1430 | fn cmd_term(_p: &Parsed) { | ||
| 1431 | // Debug: check if the callback is registered. | ||
| 1432 | let cb_set = unsafe { core::ptr::addr_of!(rsnix::wm::SPAWN_TERMINAL_CB).read().is_some() }; | ||
| 1433 | term_println(&alloc::format!("term: SPAWN_TERMINAL_CB set = {}", cb_set)); | ||
| 1434 | if !cb_set { | ||
| 1435 | term_err("term: callback not registered — cannot spawn"); | ||
| 1436 | return; | ||
| 1437 | } | ||
| 1438 | // Invoke the callback directly (same as F1). | ||
| 1439 | let (cw, ch) = rsnix::gop::pixel_dims(); | ||
| 1440 | let w = 640usize.min(cw); | ||
| 1441 | let h = 400usize.min(ch); | ||
| 1442 | term_println(&alloc::format!("term: requesting window {}x{}", w, h)); | ||
| 1443 | unsafe { | ||
| 1444 | let cb = core::ptr::addr_of!(rsnix::wm::SPAWN_TERMINAL_CB).read().unwrap(); | ||
| 1445 | cb("term dbg", w, h); | ||
| 1446 | } | ||
| 1447 | term_println("term: callback returned (task should be spawning)"); | ||
| 1448 | } | ||
| 1449 | |||
| 1404 | fn cmd_windows(_p: &Parsed) { | 1450 | fn cmd_windows(_p: &Parsed) { |
| 1405 | let list = rsnix::wm::list(); | 1451 | let list = rsnix::wm::list(); |
| 1406 | if list.is_empty() { | 1452 | if list.is_empty() { |
