// SPDX-License-Identifier: LCL-1.0 // Copyright (c) 2026 Markus Maiwald // Stewardship: Self Sovereign Society Foundation // // This file is part of the Nexus Commonwealth. // See legal/LICENSE_COMMONWEALTH.md for license terms. //! Rumpk HAL: UI Layer (The Persona) //! //! Bridges microui (C) with the Zig HAL and Framebuffer. //! Handles GUI rendering, layout management, and the boot animation loop. //! //! SAFETY: Integrates with a C-based GUI library via @cImport. //! Global context is initialized by `init()` before use in the UI fiber. const std = @import("std"); const fb = @import("framebuffer.zig"); // GPU Driver (extern) extern fn virtio_gpu_flush() void; pub const c = @cImport({ @cInclude("microui.h"); }); // --- STATIC MEMORY --- // SAFETY(UI): Context is initialized by `c.mu_init(&ctx)` in `init()`. var ctx: c.mu_Context = undefined; // --- FONT (The "8-bit" classic) --- // Minimal placeholder font (0-127 ascii) - 1KB const font_bitmap: [128][8]u8 = [_][8]u8{[_]u8{0xFF} ** 8} ** 128; // Blocks for now // --- CALL BACKS --- fn text_width_cb(font: ?*anyopaque, str: [*c]const u8, len: c_int) callconv(.c) c_int { _ = font; // assuming 8x8 monospaced // If len is -1, treat as null terminated var l = len; if (l == -1 and str != null) { l = 0; var s = str; while (s[0] != 0) { l += 1; s += 1; } } return l * 8; } fn text_height_cb(font: ?*anyopaque) callconv(.c) c_int { _ = font; return 8; } // --- THE RENDERER (The Paint Brush) --- pub fn render() void { var cmd: [*c]c.mu_Command = null; // Iterate over microui command list // Note: mu_next_command takes pointers while (c.mu_next_command(&ctx, &cmd) != 0) { switch (cmd.*.type) { c.MU_COMMAND_TEXT => { // draw_text(cmd.text.str, cmd.text.pos, cmd.text.color); // For now, ignore text drawing to avoid font complexity in step 1 }, c.MU_COMMAND_RECT => { draw_rect(cmd.*.rect.rect, cmd.*.rect.color); }, c.MU_COMMAND_ICON => { // TODO: Draw simple icons (close button X) draw_rect(cmd.*.icon.rect, cmd.*.icon.color); // Placeholder }, c.MU_COMMAND_CLIP => { // fb.set_clip(cmd.clip.rect); // Adaptation needed for C to Zig struct fb.set_clip(.{ .x = cmd.*.clip.rect.x, .y = cmd.*.clip.rect.y, .w = cmd.*.clip.rect.w, .h = cmd.*.clip.rect.h, }); }, else => {}, } } // PUSH TO HOST (The Retina) virtio_gpu_flush(); } // --- HELPER: Draw Rect --- fn draw_rect(r: c.mu_Rect, color: c.mu_Color) void { // Convert microui Color to ARGB const argb = (@as(u32, 255) << 24) | (@as(u32, color.r) << 16) | (@as(u32, color.g) << 8) | @as(u32, color.b); // Plot to L0 Framebuffer fb.fill_rect(r.x, r.y, r.w, r.h, argb); } // --- INITIALIZATION --- pub fn init() void { c.mu_init(&ctx); // Hook up text width callback (Required by microui) ctx.text_width = text_width_cb; ctx.text_height = text_height_cb; } // --- KERNEL IMPORTS --- extern fn fiber_yield() void; extern fn fiber_sleep(ms: i32) void; extern fn matrix_init() void; extern fn matrix_update() bool; // --- THE UI LOOP (Fiber Entry) --- export fn ui_fiber_entry() void { init(); matrix_init(); var matrix_alive: bool = true; while (true) { if (matrix_alive) { // --- THE GREETING (High Compute) --- matrix_alive = matrix_update(); // Push the Rain to the GPU virtio_gpu_flush(); // 33ms Frame Time (~30 FPS) fiber_sleep(33); } else { // --- THE HUD / VOID (Low Compute) --- // 1. Begin Frame c.mu_begin(&ctx); // 2. Define Layout (The Logic) if (c.mu_begin_window(&ctx, "Nexus HUD", c.mu_rect(10, 10, 300, 200)) != 0) { c.mu_layout_row(&ctx, 1, &[_]i32{-1}, 0); c.mu_label(&ctx, "System Status: ONLINE"); c.mu_layout_row(&ctx, 2, &[_]i32{ 80, -1 }, 0); c.mu_label(&ctx, "CPU:"); c.mu_draw_rect(&ctx, c.mu_rect(100, 50, 150, 20), c.mu_color(0, 255, 0, 255)); // Mock bar if (c.mu_button(&ctx, "REBOOT") != 0) { // hal_reboot(); } c.mu_end_window(&ctx); } // 3. End Frame & Paint c.mu_end(&ctx); render(); // 1s Sleep - No need to render UI every 30ms if static fiber_sleep(1000); } } }