From ba304898b8e177d90afb58d201b4c3dd3c927c48 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 27 Aug 2026 17:23:34 +0200 Subject: GUI: window/event exports, paint binary, event-loop gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rsapi: WmEvent (kind=u8 enum: 0=key, 1=mouse, 2=focus, 3=close), WmKeyKind (Char/Enter/Backspace/F1-F4/…), WmMouseEvent (x/y/buttons), WindowInfo (ptr/w/h). Five new exports: wm_create, wm_buffer, wm_flush, wm_destroy, wm_recv (non-blocking TaskMsg dispatch → WmEvent). Shell: abi_wm_* wrappers bridge rsapi types to rsnix::wm and sched::recv(); wm_recv translates TaskMsg::Key/Mouse/Focus/Close into flat WmEvent union. bins/paint: gate binary — create_window + buffer + event loop with Bresenham line drawing, color select (1-8), clear (c), F4 close. All via wm_* ABI exports. Fully migrated: date, mem, pci, cat, ls, mkdir, touch, rm, klog, info, paint (11 external binaries in /bin/cli/ + 3 gate binaries). --- bins/paint/src/main.rs | 137 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 bins/paint/src/main.rs (limited to 'bins/paint/src/main.rs') diff --git a/bins/paint/src/main.rs b/bins/paint/src/main.rs new file mode 100644 index 0000000..d395a4c --- /dev/null +++ b/bins/paint/src/main.rs @@ -0,0 +1,137 @@ +//! paint — drawing canvas via the GUI exports table. +//! +//! Keys: 1-8 select color, c clears to black. Mouse draws when pressed. + +#![no_std] +#![no_main] + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop { core::hint::spin_loop(); } +} + +const W: u32 = 640; +const H: u32 = 400; + +const fn pack(r: u8, g: u8, b: u8) -> u32 { + ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) +} + +const PALETTE: [u32; 9] = [ + pack(255, 255, 255), // 1 white + pack(255, 0, 0), // 2 red + pack(0, 255, 0), // 3 green + pack(0, 0, 255), // 4 blue + pack(255, 255, 0), // 5 yellow + pack(255, 0, 255), // 6 magenta + pack(0, 255, 255), // 7 cyan + pack(255, 128, 0), // 8 orange + pack(0, 0, 0), // clear (black) +]; + +#[unsafe(no_mangle)] +pub extern "C" fn efi_main(exports: &'static rsapi::Exports, _argc: usize, _argv: *const rsapi::Arg) -> i32 { + // Create window + let title = b"paint"; + let win = (exports.wm_create)(rsapi::Line { ptr: title.as_ptr(), len: title.len() }, W, H); + if win < 0 { return 1; } + + // Get pixel buffer + let mut info = rsapi::WindowInfo { ptr: core::ptr::null_mut(), w: 0, h: 0 }; + if !(exports.wm_buffer)(win, &mut info) { + (exports.wm_destroy)(win); + return 1; + } + + let buf = info.ptr; + let bw = info.w as usize; + let bh = info.h as usize; + + let mut color: usize = 0; + let mut last_x: i32 = -1; + let mut last_y: i32 = -1; + + let mut ev = rsapi::WmEvent { + kind: 0, + key_kind: rsapi::WmKeyKind::Char, + key_char: 0, + mouse: rsapi::WmMouseEvent { x: 0, y: 0, buttons: 0 }, + focused: false, + _pad: [0; 4], + }; + + // Event loop + loop { + if !(exports.wm_recv)(&mut ev) { + continue; + } + match ev.kind { + 0 => { + // Key event + match ev.key_kind { + rsapi::WmKeyKind::Char => { + match ev.key_char { + b'1'..=b'8' => color = (ev.key_char - b'1') as usize, + b'c' => { + unsafe { + + let n = bw * bh; + let p = buf as *mut u32; + for i in 0..n { + *p.add(i) = 0; + } + } + (exports.wm_flush)(win); + } + _ => {} + } + } + rsapi::WmKeyKind::F4 => break, + _ => {} + } + } + 1 => { + // Mouse event + let m = &ev.mouse; + if m.buttons & 1 != 0 { + // Left button: draw pixel at (m.x, m.y) + if m.x >= 0 && m.y >= 0 && (m.x as usize) < bw && (m.y as usize) < bh { + unsafe { + + *buf.add(m.y as usize * bw + m.x as usize) = PALETTE[color % PALETTE.len()]; + } + // Connect with last point (line drawing) + if last_x >= 0 { + let lx = last_x; let ly = last_y; + let dx = (m.x - lx).abs(); let sx = if lx < m.x { 1 } else { -1 }; + let dy = -(m.y - ly).abs(); let sy = if ly < m.y { 1 } else { -1 }; + let mut err = dx + dy; + let mut cx = lx; let mut cy = ly; + loop { + if cx >= 0 && cy >= 0 && (cx as usize) < bw && (cy as usize) < bh { + unsafe { + *buf.add(cy as usize * bw + cx as usize) = PALETTE[color % PALETTE.len()]; } + } + if cx == m.x && cy == m.y { break; } + let e2 = 2 * err; + if e2 >= dy { err += dy; cx += sx; } + if e2 <= dx { err += dx; cy += sy; } + } + } + (exports.wm_flush)(win); + last_x = m.x; + last_y = m.y; + } + } else { + last_x = -1; last_y = -1; + } + } + 2 => {} // focus + 3 => break, // close + _ => {} + } + } + + (exports.wm_destroy)(win); + 0 +} -- cgit v1.2.3