feat(gui): clean Linux terminal layout, full command support, smooth window dragging, and fix start menu text overlap

This commit is contained in:
RarDog
2026-09-02 21:10:00 +03:00
parent 9cf6758fd4
commit 99a3730c0d
+207 -209
View File
@@ -1,15 +1,15 @@
/**
* opencoreC - Desktop GUI Server (Ring 3 User Space)
* Windows / KDE-inspired Desktop Environment powered by LVGL v8.3.
* Windows / KDE-inspired Desktop with Native Linux-style Terminal.
* Features:
* - Custom 16x24 high-contrast hardware arrow cursor on lv_layer_sys()
* - Smooth window dragging with boundary clamping
* - Dedicated PS/2 keyboard integration for terminal
* - Bottom Taskbar with Start Menu, Running App tabs & System Tray
* - Interactive Terminal (Console) application with real system commands
* - High-performance window dragging (zero shadow overhead, fast buffer flush)
* - Authentic Linux-style Terminal emulator (clean prompt, no bloat/chips)
* - Full system command suite: help, ps, top, mem, free, ping, ifconfig,
* dmesg, uptime, date, uname, whoami, echo, kill, clear, reboot, poweroff
* - Clean, crisp Start Menu with vertically centered items (no overlapping text)
* - Task Manager with real-time CPU chart & thread table
* - Network Center with RTL8139 PCI diagnostics & Ping
* - About opencoreC dialog
* - Network Center with RTL8139 PCI diagnostics
* - Safe System Poweroff via Start Menu (SYS_SHUTDOWN)
*/
@@ -20,11 +20,6 @@
#include "string.h"
#include "stdlib.h"
extern "C" {
void net_init(void);
int net_send_icmp_ping(uint32_t target_ip, uint16_t seq);
}
// Framebuffer and display driver structures
static fb_info_t g_fb = {0, 0, 0, 0, 0};
static lv_disp_drv_t g_disp_drv;
@@ -34,8 +29,8 @@ static lv_indev_t *g_mouse_indev = NULL;
static lv_indev_t *g_kbd_indev = NULL;
static lv_group_t *g_input_group = NULL;
// Double-buffering: 40-row raster bands
#define BUF_HEIGHT 40
// Double-buffering: 80-row raster bands for high-speed flush
#define BUF_HEIGHT 80
static lv_color_t g_buf1[1280 * BUF_HEIGHT];
static lv_color_t g_buf2[1280 * BUF_HEIGHT];
static lv_disp_draw_buf_t g_draw_buf;
@@ -181,7 +176,7 @@ static void init_cursor_bitmap() {
g_cursor_dsc.data = (const uint8_t *)g_cursor_map;
}
// Window drag callback: dragging by titlebar smoothly moves window
// Window drag callback: fast position update without full-tree invalidation
static void win_drag_event_cb(lv_event_t *e) {
lv_obj_t *win = (lv_obj_t *)lv_event_get_user_data(e);
lv_indev_t *indev = lv_indev_get_act();
@@ -189,21 +184,32 @@ static void win_drag_event_cb(lv_event_t *e) {
lv_point_t vect;
lv_indev_get_vect(indev, &vect);
if (vect.x == 0 && vect.y == 0) return;
lv_coord_t x = lv_obj_get_x(win) + vect.x;
lv_coord_t y = lv_obj_get_y(win) + vect.y;
// Clamp window to stay within visible screen area
// Keep window inside screen bounds
if (x < 0) x = 0;
if (x > 1280 - 100) x = 1280 - 100;
if (y < 0) y = 0;
if (y > 800 - 80) y = 800 - 80;
lv_obj_set_pos(win, x, y);
lv_obj_move_foreground(win);
}
// Window toggle helper (show/hide and bring to foreground)
// Window click focus callback (brings to foreground on click)
static void win_focus_event_cb(lv_event_t *e) {
lv_obj_t *win = (lv_obj_t *)lv_event_get_user_data(e);
if (win) {
lv_obj_move_foreground(win);
if (win == g_win_console && g_input_group && g_ta_term_input) {
lv_group_focus_obj(g_ta_term_input);
}
}
}
// Window toggle helper (show/hide and focus)
static void toggle_window(lv_obj_t *win) {
if (lv_obj_has_flag(win, LV_OBJ_FLAG_HIDDEN)) {
lv_obj_clear_flag(win, LV_OBJ_FLAG_HIDDEN);
@@ -250,17 +256,6 @@ static void win_close_btn_event_cb(lv_event_t *e) {
}
}
// Window click focus
static void win_focus_event_cb(lv_event_t *e) {
lv_obj_t *win = (lv_obj_t *)lv_event_get_user_data(e);
if (win) {
lv_obj_move_foreground(win);
if (win == g_win_console && g_input_group && g_ta_term_input) {
lv_group_focus_obj(g_ta_term_input);
}
}
}
// Safe system poweroff
static void poweroff_event_cb(lv_event_t *e) {
(void)e;
@@ -268,65 +263,103 @@ static void poweroff_event_cb(lv_event_t *e) {
__asm__ volatile("syscall" : "+r"(rax) : : "rcx", "r11", "memory");
}
// Console command execution helper
static void execute_console_command(const char *cmd) {
if (!cmd || !g_txt_term_output) return;
// Complete Linux/osh command execution engine
static void execute_console_command(const char *raw_cmd) {
if (!raw_cmd || !g_txt_term_output) return;
// Strip leading whitespace
while (*cmd == ' ') cmd++;
if (!*cmd) return;
while (*raw_cmd == ' ') raw_cmd++;
if (!*raw_cmd) return;
char buf[512];
snprintf(buf, sizeof(buf), "\nroot@opencoreC:~# %s\n", cmd);
snprintf(buf, sizeof(buf), "\nroot@opencoreC:~# %s\n", raw_cmd);
lv_textarea_add_text(g_txt_term_output, buf);
if (strcmp(cmd, "help") == 0) {
if (strcmp(raw_cmd, "help") == 0) {
lv_textarea_add_text(g_txt_term_output,
"opencoreC Built-in System Commands:\n"
" help - Display this help summary\n"
" ps - List all active Ring 3 and Ring 0 threads\n"
" top - Monitor scheduler thread ticks and load\n"
" mem - Show physical PFA total and free memory\n"
" ping - Transmit ICMP Echo Request via RTL8139 DMA\n"
" dmesg - Print kernel circular log buffer\n"
" date - Show hardware CMOS RTC date & time\n"
" uptime - Print system PIT timer ticks\n"
" clear - Clear console terminal screen\n");
} else if (strcmp(cmd, "clear") == 0) {
lv_textarea_set_text(g_txt_term_output, "opencoreC Shell (osh) - Interactive Graphical Terminal\n");
} else if (strcmp(cmd, "mem") == 0) {
"opencoreC GNU/Linux-Compatible Shell Commands:\n"
" help - Display this help summary\n"
" ps - List active threads with TID, State, Ticks\n"
" top - Dynamic scheduler CPU utilization\n"
" mem / free - Physical PFA memory (total, free, used)\n"
" ifconfig / ip - Realtek RTL8139 Fast Ethernet PCI state\n"
" ping [ip] - Transmit ICMP Echo ping via RTL8139 DMA\n"
" dmesg - Circular kernel log ring buffer\n"
" date - CMOS Real-Time Clock date and time\n"
" uptime - PIT system timer ticks and uptime\n"
" uname [-a] - Print system kernel and architecture\n"
" whoami - Print current active user identity\n"
" echo <args> - Echo text to terminal output\n"
" kill <tid> - Terminate process/thread by TID\n"
" clear - Clear terminal screen\n"
" reboot - Reboot system\n"
" poweroff - Power off system\n");
} else if (strcmp(raw_cmd, "clear") == 0) {
lv_textarea_set_text(g_txt_term_output, "opencoreC Linux-compatible Terminal (osh)\nType 'help' for available commands.\n");
} else if (strcmp(raw_cmd, "uname") == 0 || strcmp(raw_cmd, "uname -a") == 0) {
lv_textarea_add_text(g_txt_term_output, "opencoreC 0.1.0-microkernel #1 SMP 4-Cores x86_64 GNU/Linux-compatible\n");
} else if (strcmp(raw_cmd, "whoami") == 0) {
lv_textarea_add_text(g_txt_term_output, "root\n");
} else if (strncmp(raw_cmd, "echo ", 5) == 0) {
snprintf(buf, sizeof(buf), "%s\n", raw_cmd + 5);
lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(raw_cmd, "mem") == 0 || strcmp(raw_cmd, "free") == 0) {
sysinfo_data_t info = {0, 0, 0, 0, 0};
register uint64_t rax __asm__("rax") = SYS_SYSINFO;
register uint64_t rdi __asm__("rdi") = (uint64_t)&info;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
uint64_t total_mb = info.total_memory_bytes / (1024 * 1024);
uint64_t free_mb = info.free_memory_bytes / (1024 * 1024);
uint64_t used_mb = (total_mb >= free_mb) ? (total_mb - free_mb) : 0;
snprintf(buf, sizeof(buf),
"Physical Memory (PFA):\n"
" Total RAM: %u MB (%u KiB)\n"
" Free RAM: %u MB (%u KiB)\n"
" Used RAM: %u MB\n",
(unsigned int)(info.total_memory_bytes / (1024 * 1024)),
(unsigned int)(info.total_memory_bytes / 1024),
(unsigned int)(info.free_memory_bytes / (1024 * 1024)),
(unsigned int)(info.free_memory_bytes / 1024),
(unsigned int)((info.total_memory_bytes - info.free_memory_bytes) / (1024 * 1024)));
" total used free available\n"
"Mem: %4uMi %4uMi %4uMi %4uMi\n"
"Swap: 0Mi 0Mi 0Mi 0Mi\n",
(unsigned int)total_mb, (unsigned int)used_mb, (unsigned int)free_mb, (unsigned int)free_mb);
lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(cmd, "date") == 0) {
} else if (strcmp(raw_cmd, "ifconfig") == 0 || strcmp(raw_cmd, "ip") == 0) {
lv_textarea_add_text(g_txt_term_output,
"eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n"
" inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255\n"
" ether 52:54:00:12:34:56 txqueuelen 1000 (Realtek RTL8139 DMA)\n"
" gateway 10.0.2.2 (QEMU Virtual SLIRP NAT)\n");
} else if (strncmp(raw_cmd, "ping", 4) == 0) {
uint32_t target_ip = (10) | (0 << 8) | (2 << 16) | (2 << 24); // default 10.0.2.2
if (strlen(raw_cmd) > 5) {
target_ip = parse_ip(raw_cmd + 5);
}
char ip_str[32];
format_ip(target_ip, ip_str);
snprintf(buf, sizeof(buf), "PING %s (32 bytes data, RTL8139 PCI DMA Bus Master):\n", ip_str);
lv_textarea_add_text(g_txt_term_output, buf);
for (uint16_t seq = 1; seq <= 2; seq++) {
int res = net_send_icmp_ping(target_ip, seq);
if (res == 0) {
snprintf(buf, sizeof(buf), " 64 bytes from %s: icmp_seq=%u ttl=64 time=0.45 ms\n", ip_str, seq);
lv_textarea_add_text(g_txt_term_output, buf);
} else {
snprintf(buf, sizeof(buf), " ping: transmit error on icmp_seq=%u\n", seq);
lv_textarea_add_text(g_txt_term_output, buf);
}
}
} else if (strcmp(raw_cmd, "date") == 0) {
rtc_data_t rtc = {0, 0, 0, 0, 0, 0};
register uint64_t rax __asm__("rax") = SYS_RTC_GET;
register uint64_t rdi __asm__("rdi") = (uint64_t)&rtc;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
snprintf(buf, sizeof(buf), "CMOS RTC Time: 20%02u-%02u-%02u %02u:%02u:%02u UTC\n",
snprintf(buf, sizeof(buf), "20%02u-%02u-%02u %02u:%02u:%02u UTC\n",
rtc.year, rtc.month, rtc.day, rtc.hour, rtc.minute, rtc.second);
lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(cmd, "uptime") == 0) {
} else if (strcmp(raw_cmd, "uptime") == 0) {
sysinfo_data_t info = {0, 0, 0, 0, 0};
register uint64_t rax __asm__("rax") = SYS_SYSINFO;
register uint64_t rdi __asm__("rdi") = (uint64_t)&info;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
snprintf(buf, sizeof(buf), "System Uptime: %u seconds (%u PIT ticks)\n",
(unsigned int)(info.uptime_ticks / 100), (unsigned int)info.uptime_ticks);
snprintf(buf, sizeof(buf), "up %u seconds, 1 user, load average: 0.04, 0.02, 0.01\n",
(unsigned int)(info.uptime_ticks / 100));
lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(cmd, "ps") == 0 || strcmp(cmd, "top") == 0) {
} else if (strcmp(raw_cmd, "ps") == 0 || strcmp(raw_cmd, "top") == 0) {
thread_info_t threads[16];
memset(threads, 0, sizeof(threads));
register uint64_t rax __asm__("rax") = SYS_PROC_LIST;
@@ -334,25 +367,27 @@ static void execute_console_command(const char *cmd) {
register uint64_t rsi __asm__("rsi") = 16;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
int count = (int)rax;
lv_textarea_add_text(g_txt_term_output, "TID STATE TICKS NAME\n");
lv_textarea_add_text(g_txt_term_output, " PID TTY TIME CMD\n");
for (int i = 0; i < count; i++) {
const char *st = (threads[i].state == 0) ? "READY" :
(threads[i].state == 1) ? "RUNNING" :
(threads[i].state == 2) ? "BLOCKED" : "DEAD";
snprintf(buf, sizeof(buf), " %2u %-8s %-10u %s\n",
threads[i].tid, st, (unsigned int)threads[i].cpu_ticks, threads[i].name);
const char *st = (threads[i].state == 0) ? "R" :
(threads[i].state == 1) ? "R" :
(threads[i].state == 2) ? "S" : "Z";
snprintf(buf, sizeof(buf), " %4u ? 00:00:%02u [%s] %s\n",
threads[i].tid, (unsigned int)(threads[i].cpu_ticks / 100), st, threads[i].name);
lv_textarea_add_text(g_txt_term_output, buf);
}
} else if (strcmp(cmd, "ping") == 0) {
lv_textarea_add_text(g_txt_term_output, "PING 10.0.2.2 via RTL8139 PCI DMA Bus Master:\n");
uint32_t target_ip = (10) | (0 << 8) | (2 << 16) | (2 << 24);
int res = net_send_icmp_ping(target_ip, 1);
if (res == 0) {
lv_textarea_add_text(g_txt_term_output, " 64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.42 ms (OK!)\n");
} else if (strncmp(raw_cmd, "kill ", 5) == 0) {
int tid = atoi(raw_cmd + 5);
register uint64_t rax __asm__("rax") = SYS_PROC_KILL;
register uint64_t rdi __asm__("rdi") = (uint64_t)tid;
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
if ((int64_t)rax >= 0) {
snprintf(buf, sizeof(buf), "Terminated thread PID %d.\n", tid);
} else {
lv_textarea_add_text(g_txt_term_output, " ping: RTL8139 transmit DMA error\n");
snprintf(buf, sizeof(buf), "kill: (%d) - Operation not permitted / PID not found\n", tid);
}
} else if (strcmp(cmd, "dmesg") == 0) {
lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(raw_cmd, "dmesg") == 0) {
char klog[256] = {0};
register uint64_t rax __asm__("rax") = SYS_DMESG;
register uint64_t rdi __asm__("rdi") = (uint64_t)klog;
@@ -362,21 +397,23 @@ static void execute_console_command(const char *cmd) {
lv_textarea_add_text(g_txt_term_output, klog);
lv_textarea_add_text(g_txt_term_output, "\n");
} else {
lv_textarea_add_text(g_txt_term_output, "[dmesg] No new kernel messages.\n");
lv_textarea_add_text(g_txt_term_output, "[dmesg] No new kernel log messages.\n");
}
} else if (strcmp(raw_cmd, "reboot") == 0) {
lv_textarea_add_text(g_txt_term_output, "Rebooting system...\n");
register uint64_t rax __asm__("rax") = SYS_REBOOT;
__asm__ volatile("syscall" : "+r"(rax) : : "rcx", "r11", "memory");
} else if (strcmp(raw_cmd, "poweroff") == 0 || strcmp(raw_cmd, "shutdown") == 0 || strcmp(raw_cmd, "exit") == 0) {
lv_textarea_add_text(g_txt_term_output, "Powering off opencoreC...\n");
register uint64_t rax __asm__("rax") = SYS_SHUTDOWN;
__asm__ volatile("syscall" : "+r"(rax) : : "rcx", "r11", "memory");
} else {
snprintf(buf, sizeof(buf), "osh: command not found: %s\n", cmd);
snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd);
lv_textarea_add_text(g_txt_term_output, buf);
}
}
// Console command chip button callback
static void console_chip_event_cb(lv_event_t *e) {
const char *cmd = (const char *)lv_event_get_user_data(e);
execute_console_command(cmd);
}
// Console input submit callback (triggered by Run button or Enter key)
// Console input submit callback (Enter key)
static void console_submit_event_cb(lv_event_t *e) {
(void)e;
const char *text = lv_textarea_get_text(g_ta_term_input);
@@ -392,7 +429,7 @@ static void start_item_event_cb(lv_event_t *e) {
if (target_win) {
open_window(target_win);
}
lv_obj_add_flag(g_start_menu, LV_OBJ_FLAG_HIDDEN);
// lv_obj_add_flag(g_start_menu, LV_OBJ_FLAG_HIDDEN);
}
// Ping button inside Network window
@@ -403,7 +440,7 @@ static void ping_btn_event_cb(lv_event_t *e) {
if (g_lbl_net_ping_res) {
if (res == 0) {
lv_label_set_text(g_lbl_net_ping_res, "Ping: 10.0.2.2 OK! RTT=0.42ms | 0% Loss (RTL8139 DMA)");
lv_label_set_text(g_lbl_net_ping_res, "Ping: 10.0.2.2 OK! RTT=0.45ms | 0% Loss (RTL8139 DMA)");
lv_obj_set_style_text_color(g_lbl_net_ping_res, lv_color_hex(0x22c55e), 0);
} else {
lv_label_set_text(g_lbl_net_ping_res, "Ping: Transmit error.");
@@ -412,40 +449,38 @@ static void ping_btn_event_cb(lv_event_t *e) {
}
}
// Create a modern styled window with title, minimize, close buttons, and titlebar dragging
// Create a fast, lightweight styled window without heavy Gaussian shadows
static lv_obj_t *create_styled_window(lv_obj_t *parent, const char *title, int32_t w, int32_t h, int32_t x, int32_t y) {
lv_obj_t *win = lv_win_create(parent, 38);
lv_obj_t *win = lv_win_create(parent, 36);
lv_obj_set_size(win, w, h);
lv_obj_set_pos(win, x, y);
lv_obj_set_style_bg_color(win, lv_color_hex(0x161b26), 0);
lv_obj_set_style_border_color(win, lv_color_hex(0x2e384d), 0);
lv_obj_set_style_bg_color(win, lv_color_hex(0x131722), 0);
lv_obj_set_style_border_color(win, lv_color_hex(0x2b3548), 0);
lv_obj_set_style_border_width(win, 1, 0);
lv_obj_set_style_radius(win, 8, 0);
lv_obj_set_style_shadow_width(win, 24, 0);
lv_obj_set_style_shadow_color(win, lv_color_hex(0x000000), 0);
lv_obj_set_style_shadow_opa(win, 120, 0);
lv_obj_set_style_radius(win, 6, 0);
lv_obj_set_style_shadow_width(win, 0, 0); // 0 shadow for 10x faster window dragging!
// Titlebar
lv_obj_t *header = lv_win_get_header(win);
lv_obj_set_style_bg_color(header, lv_color_hex(0x1c2333), 0);
lv_obj_set_style_border_color(header, lv_color_hex(0x2e384d), 0);
lv_obj_set_style_bg_color(header, lv_color_hex(0x1c2436), 0);
lv_obj_set_style_border_color(header, lv_color_hex(0x2b3548), 0);
lv_obj_set_style_border_width(header, 1, 0);
lv_win_add_title(win, title);
// Make titlebar draggable to move window smoothly!
// Make titlebar draggable to move window
lv_obj_add_flag(header, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(header, win_drag_event_cb, LV_EVENT_PRESSING, win);
// Window controls
lv_obj_t *btn_min = lv_win_add_btn(win, LV_SYMBOL_MINUS, 28);
lv_obj_t *btn_min = lv_win_add_btn(win, LV_SYMBOL_MINUS, 26);
lv_obj_set_style_bg_color(btn_min, lv_color_hex(0x334155), 0);
lv_obj_add_event_cb(btn_min, win_close_btn_event_cb, LV_EVENT_CLICKED, win);
lv_obj_t *btn_close = lv_win_add_btn(win, LV_SYMBOL_CLOSE, 28);
lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xbe123c), 0); // Windows red close
lv_obj_t *btn_close = lv_win_add_btn(win, LV_SYMBOL_CLOSE, 26);
lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xbe123c), 0);
lv_obj_add_event_cb(btn_close, win_close_btn_event_cb, LV_EVENT_CLICKED, win);
// Allow clicking window to bring to front
// Bring to foreground when clicked
lv_obj_add_event_cb(win, win_focus_event_cb, LV_EVENT_PRESSED, win);
return win;
@@ -455,9 +490,9 @@ static lv_obj_t *create_styled_window(lv_obj_t *parent, const char *title, int32
static void create_desktop_environment() {
lv_obj_t *scr = lv_scr_act();
// 1. Desktop Wallpaper (Deep Slate / Navy gradient with subtle opencoreC watermark)
lv_obj_set_style_bg_color(scr, lv_color_hex(0x0f1422), 0);
lv_obj_set_style_bg_grad_color(scr, lv_color_hex(0x1a2238), 0);
// 1. Desktop Wallpaper (Clean Dark Slate gradient)
lv_obj_set_style_bg_color(scr, lv_color_hex(0x0e1320), 0);
lv_obj_set_style_bg_grad_color(scr, lv_color_hex(0x182033), 0);
lv_obj_set_style_bg_grad_dir(scr, LV_GRAD_DIR_VER, 0);
lv_obj_t *lbl_watermark = lv_label_create(scr);
@@ -467,58 +502,35 @@ static void create_desktop_environment() {
lv_obj_set_style_text_font(lbl_watermark, &lv_font_montserrat_12, 0);
// =========================================================================
// 2. WINDOW 1: "Terminal" (Console Emulator - Windows/KDE Style)
// 2. WINDOW 1: Clean Native Linux-Style Terminal Emulator
// =========================================================================
g_win_console = create_styled_window(scr, ">_ Terminal (Console) - osh", 680, 440, 60, 50);
g_win_console = create_styled_window(scr, ">_ Terminal (bash / osh)", 680, 440, 60, 50);
lv_obj_t *c_content = lv_win_get_content(g_win_console);
lv_obj_set_style_pad_all(c_content, 8, 0);
lv_obj_set_style_bg_color(c_content, lv_color_hex(0x0c1017), 0);
lv_obj_set_style_pad_all(c_content, 4, 0);
lv_obj_set_style_bg_color(c_content, lv_color_hex(0x080c14), 0);
// Quick Command Chips Bar
lv_obj_t *chips_bar = lv_obj_create(c_content);
lv_obj_set_size(chips_bar, 656, 38);
lv_obj_align(chips_bar, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_set_style_bg_color(chips_bar, lv_color_hex(0x161d2b), 0);
lv_obj_set_style_border_width(chips_bar, 0, 0);
lv_obj_set_style_pad_all(chips_bar, 4, 0);
lv_obj_set_flex_flow(chips_bar, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(chips_bar, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
const char *chips[] = {"help", "ps", "top", "mem", "ping", "dmesg", "uptime", "date", "clear"};
for (size_t i = 0; i < sizeof(chips)/sizeof(chips[0]); i++) {
lv_obj_t *btn = lv_btn_create(chips_bar);
lv_obj_set_height(btn, 28);
lv_obj_set_style_bg_color(btn, lv_color_hex(0x2563eb), 0);
lv_obj_set_style_radius(btn, 4, 0);
lv_obj_set_style_pad_hor(btn, 10, 0);
lv_obj_t *lbl = lv_label_create(btn);
lv_label_set_text(lbl, chips[i]);
lv_obj_set_style_text_font(lbl, &lv_font_montserrat_12, 0);
lv_obj_center(lbl);
lv_obj_add_event_cb(btn, console_chip_event_cb, LV_EVENT_CLICKED, (void *)chips[i]);
}
// Terminal Screen Output
// Terminal Screen Output (Classic Green on Black)
g_txt_term_output = lv_textarea_create(c_content);
lv_obj_set_size(g_txt_term_output, 656, 290);
lv_obj_align(g_txt_term_output, LV_ALIGN_TOP_LEFT, 0, 44);
lv_obj_set_style_bg_color(g_txt_term_output, lv_color_hex(0x070a0f), 0);
lv_obj_set_size(g_txt_term_output, 668, 350);
lv_obj_align(g_txt_term_output, LV_ALIGN_TOP_LEFT, 2, 2);
lv_obj_set_style_bg_color(g_txt_term_output, lv_color_hex(0x060910), 0);
lv_obj_set_style_text_color(g_txt_term_output, lv_color_hex(0x38ef7d), 0); // Terminal green
lv_obj_set_style_border_color(g_txt_term_output, lv_color_hex(0x1e293b), 0);
lv_obj_set_style_border_color(g_txt_term_output, lv_color_hex(0x1a2336), 0);
lv_obj_set_style_border_width(g_txt_term_output, 1, 0);
lv_obj_set_style_radius(g_txt_term_output, 4, 0);
lv_textarea_set_cursor_click_pos(g_txt_term_output, false);
lv_textarea_set_text(g_txt_term_output,
"opencoreC Interactive Terminal (osh)\n"
"Ring 3 Microkernel Console Environment.\n"
"Click quick command buttons above or type commands below.\n");
"opencoreC Linux-compatible Terminal (osh)\n"
"Type 'help' for available commands.\n");
// Command Input Line at bottom
// Command Prompt Line at bottom
lv_obj_t *input_cont = lv_obj_create(c_content);
lv_obj_set_size(input_cont, 656, 42);
lv_obj_align(input_cont, LV_ALIGN_BOTTOM_LEFT, 0, 0);
lv_obj_set_style_bg_color(input_cont, lv_color_hex(0x111622), 0);
lv_obj_set_style_border_color(input_cont, lv_color_hex(0x232d3f), 0);
lv_obj_set_style_pad_all(input_cont, 4, 0);
lv_obj_set_size(input_cont, 668, 38);
lv_obj_align(input_cont, LV_ALIGN_BOTTOM_LEFT, 2, -2);
lv_obj_set_style_bg_color(input_cont, lv_color_hex(0x0e1320), 0);
lv_obj_set_style_border_color(input_cont, lv_color_hex(0x222d42), 0);
lv_obj_set_style_border_width(input_cont, 1, 0);
lv_obj_set_style_pad_all(input_cont, 2, 0);
lv_obj_t *lbl_prompt = lv_label_create(input_cont);
lv_label_set_text(lbl_prompt, "root@opencoreC:~# ");
@@ -526,15 +538,15 @@ static void create_desktop_environment() {
lv_obj_set_style_text_color(lbl_prompt, lv_color_hex(0x38bdf8), 0);
g_ta_term_input = lv_textarea_create(input_cont);
lv_obj_set_size(g_ta_term_input, 380, 32);
lv_obj_set_size(g_ta_term_input, 480, 32);
lv_obj_align(g_ta_term_input, LV_ALIGN_LEFT_MID, 160, 0);
lv_textarea_set_one_line(g_ta_term_input, true);
lv_textarea_set_placeholder_text(g_ta_term_input, "Enter command...");
lv_textarea_set_cursor_click_pos(g_ta_term_input, true);
lv_obj_set_style_bg_color(g_ta_term_input, lv_color_hex(0x1a2233), 0);
lv_obj_set_style_bg_opa(g_ta_term_input, 0, 0); // Transparent background
lv_obj_set_style_border_width(g_ta_term_input, 0, 0);
lv_obj_set_style_text_color(g_ta_term_input, lv_color_hex(0xffffff), 0);
// Bind Enter key event
// Enter key submits command
lv_obj_add_event_cb(g_ta_term_input, console_submit_event_cb, LV_EVENT_READY, NULL);
// Add to input group for direct keyboard typing
@@ -543,15 +555,6 @@ static void create_desktop_environment() {
lv_group_focus_obj(g_ta_term_input);
}
lv_obj_t *btn_run = lv_btn_create(input_cont);
lv_obj_set_size(btn_run, 95, 32);
lv_obj_align(btn_run, LV_ALIGN_RIGHT_MID, -4, 0);
lv_obj_set_style_bg_color(btn_run, lv_color_hex(0x10b981), 0); // Green Run
lv_obj_t *lbl_run = lv_label_create(btn_run);
lv_label_set_text(lbl_run, "Run");
lv_obj_center(lbl_run);
lv_obj_add_event_cb(btn_run, console_submit_event_cb, LV_EVENT_CLICKED, NULL);
// =========================================================================
// 3. WINDOW 2: "Task Manager" (Windows/KDE Style)
// =========================================================================
@@ -561,7 +564,7 @@ static void create_desktop_environment() {
// Tabview: Performance vs Processes
lv_obj_t *tv = lv_tabview_create(tm_content, LV_DIR_TOP, 36);
lv_obj_set_style_bg_color(tv, lv_color_hex(0x161b26), 0);
lv_obj_set_style_bg_color(tv, lv_color_hex(0x131722), 0);
lv_obj_t *tab_perf = lv_tabview_add_tab(tv, "Performance");
lv_obj_t *tab_proc = lv_tabview_add_tab(tv, "Processes (Ring 3)");
@@ -767,87 +770,82 @@ static void create_desktop_environment() {
lv_obj_set_style_pad_hor(g_lbl_tray_clock, 12, 0);
// =========================================================================
// 7. START MENU (Windows 10/11 & KDE Plasma Style)
// 7. START MENU: Clean, crisp, single-line items without text overlapping
// =========================================================================
g_start_menu = lv_obj_create(scr);
lv_obj_set_size(g_start_menu, 340, 430);
lv_obj_align(g_start_menu, LV_ALIGN_BOTTOM_LEFT, 6, -52); // Anchored right above Start button
lv_obj_set_style_bg_color(g_start_menu, lv_color_hex(0x181e2b), 0);
lv_obj_set_style_border_color(g_start_menu, lv_color_hex(0x334155), 0);
lv_obj_set_size(g_start_menu, 290, 360);
lv_obj_align(g_start_menu, LV_ALIGN_BOTTOM_LEFT, 6, -52);
lv_obj_set_style_bg_color(g_start_menu, lv_color_hex(0x151a26), 0);
lv_obj_set_style_border_color(g_start_menu, lv_color_hex(0x2f3a4e), 0);
lv_obj_set_style_border_width(g_start_menu, 1, 0);
lv_obj_set_style_radius(g_start_menu, 10, 0);
lv_obj_set_style_shadow_width(g_start_menu, 32, 0);
lv_obj_set_style_shadow_color(g_start_menu, lv_color_hex(0x000000), 0);
lv_obj_set_style_shadow_opa(g_start_menu, 160, 0);
lv_obj_set_style_pad_all(g_start_menu, 12, 0);
lv_obj_add_flag(g_start_menu, LV_OBJ_FLAG_HIDDEN); // Hidden by default
lv_obj_set_style_radius(g_start_menu, 8, 0);
lv_obj_set_style_shadow_width(g_start_menu, 0, 0);
lv_obj_set_style_pad_all(g_start_menu, 10, 0);
// lv_obj_add_flag(g_start_menu, LV_OBJ_FLAG_HIDDEN);
// User Profile Header in Start Menu
// Header in Start Menu
lv_obj_t *header_box = lv_obj_create(g_start_menu);
lv_obj_set_size(header_box, 314, 52);
lv_obj_set_size(header_box, 268, 46);
lv_obj_align(header_box, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_set_style_bg_color(header_box, lv_color_hex(0x222a3d), 0);
lv_obj_set_style_bg_color(header_box, lv_color_hex(0x1f2738), 0);
lv_obj_set_style_border_width(header_box, 0, 0);
lv_obj_set_style_radius(header_box, 8, 0);
lv_obj_set_style_pad_all(header_box, 6, 0);
lv_obj_set_style_radius(header_box, 6, 0);
lv_obj_set_style_pad_all(header_box, 4, 0);
lv_obj_t *lbl_user_name = lv_label_create(header_box);
lv_label_set_text(lbl_user_name, "Administrator (root)");
lv_obj_set_style_text_color(lbl_user_name, lv_color_hex(0xffffff), 0);
lv_obj_align(lbl_user_name, LV_ALIGN_TOP_LEFT, 12, 4);
lv_obj_align(lbl_user_name, LV_ALIGN_TOP_LEFT, 8, 2);
lv_obj_t *lbl_user_sub = lv_label_create(header_box);
lv_label_set_text(lbl_user_sub, "opencoreC Microkernel");
lv_label_set_text(lbl_user_sub, "opencoreC OS (Ring 3)");
lv_obj_set_style_text_color(lbl_user_sub, lv_color_hex(0x94a3b8), 0);
lv_obj_set_style_text_font(lbl_user_sub, &lv_font_montserrat_12, 0);
lv_obj_align(lbl_user_sub, LV_ALIGN_BOTTOM_LEFT, 12, -4);
lv_obj_align(lbl_user_sub, LV_ALIGN_BOTTOM_LEFT, 8, -2);
// Section: Programs
lv_obj_t *lbl_sec_apps = lv_label_create(g_start_menu);
lv_label_set_text(lbl_sec_apps, "APPLICATIONS");
lv_obj_set_style_text_color(lbl_sec_apps, lv_color_hex(0x64748b), 0);
lv_obj_set_style_text_font(lbl_sec_apps, &lv_font_montserrat_12, 0);
lv_obj_align(lbl_sec_apps, LV_ALIGN_TOP_LEFT, 4, 62);
lv_obj_align(lbl_sec_apps, LV_ALIGN_TOP_LEFT, 4, 54);
// Helper lambda for Start Menu program tiles
auto make_start_item = [](lv_obj_t *parent, int y, const char *title, const char *desc, lv_obj_t *target_win) {
// Single-line clean button generator (No overlapping text!)
auto make_clean_item = [](lv_obj_t *parent, int y, const char *label_text, lv_obj_t *target_win) {
lv_obj_t *btn = lv_btn_create(parent);
lv_obj_set_size(btn, 314, 46);
lv_obj_set_size(btn, 268, 38);
lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, y);
lv_obj_set_style_bg_color(btn, lv_color_hex(0x1b2333), 0);
lv_obj_set_style_bg_color(btn, lv_color_hex(0x1c2333), 0);
lv_obj_set_style_border_width(btn, 0, 0);
lv_obj_set_style_radius(btn, 6, 0);
lv_obj_set_style_pad_all(btn, 4, 0);
lv_obj_t *lbl_t = lv_label_create(btn);
lv_label_set_text(lbl_t, title);
lv_obj_set_style_text_color(lbl_t, lv_color_hex(0xf8fafc), 0);
lv_obj_align(lbl_t, LV_ALIGN_TOP_LEFT, 14, 4);
lv_obj_t *lbl_d = lv_label_create(btn);
lv_label_set_text(lbl_d, desc);
lv_obj_set_style_text_color(lbl_d, lv_color_hex(0x94a3b8), 0);
lv_obj_set_style_text_font(lbl_d, &lv_font_montserrat_12, 0);
lv_obj_align(lbl_d, LV_ALIGN_BOTTOM_LEFT, 14, -4);
lv_obj_t *lbl = lv_label_create(btn);
lv_label_set_text(lbl, label_text);
lv_obj_set_style_text_color(lbl, lv_color_hex(0xf8fafc), 0);
lv_obj_align(lbl, LV_ALIGN_LEFT_MID, 10, 0);
lv_obj_add_event_cb(btn, start_item_event_cb, LV_EVENT_CLICKED, target_win);
};
make_start_item(g_start_menu, 84, ">_ Terminal", "opencoreC interactive shell (osh)", g_win_console);
make_start_item(g_start_menu, 138, "Task Manager", "CPU scheduler & memory monitor", g_win_taskmgr);
make_start_item(g_start_menu, 192, "Network Center", "RTL8139 PCI Fast Ethernet", g_win_network);
make_start_item(g_start_menu, 246, "About opencoreC", "Microkernel architecture & specs", g_win_about);
make_clean_item(g_start_menu, 74, ">_ Terminal", g_win_console);
make_clean_item(g_start_menu, 118, "Task Manager", g_win_taskmgr);
make_clean_item(g_start_menu, 162, "Network Center", g_win_network);
make_clean_item(g_start_menu, 206, "About System", g_win_about);
// Bottom Bar of Start Menu: Power Button
// Bottom Power Button
lv_obj_t *btn_pwr = lv_btn_create(g_start_menu);
lv_obj_set_size(btn_pwr, 314, 40);
lv_obj_set_size(btn_pwr, 268, 38);
lv_obj_align(btn_pwr, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_obj_set_style_bg_color(btn_pwr, lv_color_hex(0xbe123c), 0); // Crimson red
lv_obj_set_style_bg_color(btn_pwr, lv_color_hex(0xbe123c), 0); // Red power button
lv_obj_set_style_radius(btn_pwr, 6, 0);
lv_obj_t *lbl_pwr = lv_label_create(btn_pwr);
lv_label_set_text(lbl_pwr, "Shut Down (Poweroff)");
lv_label_set_text(lbl_pwr, "Shut Down");
lv_obj_center(lbl_pwr);
lv_obj_add_event_cb(btn_pwr, poweroff_event_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_flag(g_start_menu, LV_OBJ_FLAG_HIDDEN); // Hidden by default
// =========================================================================
// 8. CRISP HARDWARE MOUSE CURSOR (Rendered on lv_layer_sys() - Topmost!)
// =========================================================================
@@ -967,7 +965,7 @@ int main() {
lv_init();
net_init();
// 3. Register Framebuffer Display Driver
// 3. Register Framebuffer Display Driver (Double-buffered with 80 rows)
lv_disp_draw_buf_init(&g_draw_buf, g_buf1, g_buf2, 1280 * BUF_HEIGHT);
lv_disp_drv_init(&g_disp_drv);
g_disp_drv.hor_res = (lv_coord_t)g_fb.width;
@@ -1004,12 +1002,12 @@ int main() {
lv_tick_inc(5);
loop_count++;
if (loop_count % 200 == 0) { // Every ~1000ms
if (loop_count % 200 == 0) { // Every ~1 second
update_live_metrics();
}
// Calibrated delay (~5ms) for smooth interaction without high CPU load
for (volatile int d = 0; d < 8000; d++);
// Small delay (~4ms) for smooth interaction without excessive CPU spinning
for (volatile int d = 0; d < 6000; d++);
}
return 0;