feat: 图形桌面 + 独立工具应用 + Sealed Arc UI 设计系统 | desktop.elf窗口管理器/6个工具应用(bash/editor/fileman/browser/curl/ping)/desktop_app.h公共头文件/Sealed Arc设计系统/DRR完整实现/Process增强/DSK启动改为加载desktop.elf/Shell重构/开发文档

This commit is contained in:
xyou
2026-07-03 21:13:04 +08:00
parent 3662345434
commit 48dcb5568e
44 changed files with 6302 additions and 220 deletions
+374
View File
@@ -0,0 +1,374 @@
/* desktop_app.h — Deshab 独立工具应用公共头文件
*
* 独立工具应用运行在 DSK 加载的 .elf 中,全屏独占 framebuffer。
* 每个 .elf 实现 dsk_entry(dsk_boot_context *ctx) 入口点。
* 通过 kernel_api 访问块设备、网络等内核服务。
* PS/2 键盘/鼠标通过端口 I/O 直接轮询。
*/
#ifndef DESHAB_DESKTOP_APP_H
#define DESHAB_DESKTOP_APP_H
/* 基础类型 */
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
/* 端口 I/O */
static inline void outb(u16 port, u8 val) { __asm__ volatile("outb %0,%1"::"a"(val),"Nd"(port)); }
static inline u8 inb(u16 port) { u8 v; __asm__ volatile("inb %1,%0":"=a"(v):"Nd"(port)); return v; }
/* COM1 串口日志 */
#define DA_COM1 0x3F8
static inline void da_sputc(char c) { for(unsigned i=0;i<100000;i++){if(inb(DA_COM1+5)&0x20)break;} outb(DA_COM1,(u8)c); }
static inline void da_swrite(const char *s) { while(*s){if(*s=='\n')da_sputc('\r');da_sputc(*s++);} }
static inline void da_slog(const char *tag, const char *msg) { da_swrite("["); da_swrite(tag); da_swrite("] "); da_swrite(msg); da_swrite("\n"); }
/* dsk_boot_context 定义(与 dsk.h 一致,自包含避免依赖) */
#define DA_BOOT_MAGIC 0x44534B31424F4F54ULL
typedef struct {
u64 magic; u32 abi_version; u32 size; u64 flags;
u64 hhdm_offset; u64 rsdp_address;
u64 framebuffer_address; u64 framebuffer_width; u64 framebuffer_height;
u64 framebuffer_pitch; u32 framebuffer_bpp; u32 reserved_fb;
u64 boot_modules_response;
u64 dkm_kernel_api; u64 dkm_driver_table; u64 dkm_driver_count;
u64 utsm_state; u64 drr_state;
u64 memory_map; u64 memory_map_count; u64 memory_map_entry_size;
u64 kernel_stack_top; u64 reserved[8];
} da_boot_context;
/* block_read 函数类型 */
typedef int (*da_block_read_fn)(void *ctx, u64 lba, u32 count, void *buffer);
/* 应用上下文 — 从 dsk_boot_context 提取的常用数据 */
typedef struct {
u32 *fb; /* framebuffer 基址 */
u64 fb_w; /* 宽度 */
u64 fb_h; /* 高度 */
u64 fb_pitch; /* 行宽(字节) */
da_block_read_fn block_read;
const void *kernel_api;
} da_app_context;
/* 从 dsk_boot_context 初始化 da_app_context */
static inline void da_init(da_app_context *ac, const da_boot_context *ctx) {
ac->fb = (u32 *)ctx->framebuffer_address;
ac->fb_w = ctx->framebuffer_width;
ac->fb_h = ctx->framebuffer_height;
ac->fb_pitch = ctx->framebuffer_pitch;
ac->kernel_api = (const void *)ctx->dkm_kernel_api;
/* block_read 从 kernel_api + 0xA8 获取 */
u64 api = ctx->dkm_kernel_api;
ac->block_read = (da_block_read_fn)*(u64 *)(api + 0xA8);
if (ac->block_read)
ac->block_read = (da_block_read_fn)*(u64 *)((u64)ac->block_read + 16);
}
/* ========== 帧缓冲绘制 ========== */
static inline void da_pixel(da_app_context *ac, i64 x, i64 y, u32 color) {
if (x < 0 || (u64)x >= ac->fb_w || y < 0 || (u64)y >= ac->fb_h) return;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)y * ac->fb_pitch);
line[x] = color;
}
static inline u32 da_pixel_read(da_app_context *ac, i64 x, i64 y) {
if (x < 0 || (u64)x >= ac->fb_w || y < 0 || (u64)y >= ac->fb_h) return 0;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)y * ac->fb_pitch);
return line[x];
}
static inline u32 da_blend(u32 bg, u32 fg, u32 alpha) {
u32 na = 256 - alpha;
u32 r = ((bg & 0xFF) * na + (fg & 0xFF) * alpha) >> 8;
u32 g = (((bg >> 8) & 0xFF) * na + ((fg >> 8) & 0xFF) * alpha) >> 8;
u32 b = (((bg >> 16) & 0xFF) * na + ((fg >> 16) & 0xFF) * alpha) >> 8;
return 0xFF000000u | (b << 16) | (g << 8) | r;
}
static inline void da_fill_rect(da_app_context *ac, i64 x, i64 y, i64 w, i64 h, u32 color) {
for (i64 r = 0; r < h; r++) {
i64 yy = y + r;
if (yy < 0 || (u64)yy >= ac->fb_h) continue;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)yy * ac->fb_pitch);
for (i64 c = 0; c < w; c++) {
i64 xx = x + c;
if (xx < 0 || (u64)xx >= ac->fb_w) continue;
line[xx] = color;
}
}
}
static inline void da_fill_bg(da_app_context *ac, u32 color) {
da_fill_rect(ac, 0, 0, (i64)ac->fb_w, (i64)ac->fb_h, color);
}
/* 圆角矩形 */
static inline void da_fill_rounded_rect(da_app_context *ac, i64 x, i64 y, i64 w, i64 h, u32 color, i64 radius) {
i64 r = radius;
if (r > w/2) r = w/2;
if (r > h/2) r = h/2;
da_fill_rect(ac, x+r, y, w-2*r, h, color);
da_fill_rect(ac, x, y+r, r, h-2*r, color);
da_fill_rect(ac, x+w-r, y+r, r, h-2*r, color);
for (i64 dy = 0; dy < r; dy++)
for (i64 dx = 0; dx < r; dx++)
if (dx*dx+dy*dy <= r*r) {
da_pixel(ac, x+r-1-dx, y+r-1-dy, color);
da_pixel(ac, x+w-r+dx, y+r-1-dy, color);
da_pixel(ac, x+r-1-dx, y+h-r+dy, color);
da_pixel(ac, x+w-r+dx, y+h-r+dy, color);
}
}
static inline void da_rect_outline(da_app_context *ac, i64 x, i64 y, i64 w, i64 h, u32 color, i64 radius) {
i64 r = radius;
if (r > w/2) r = w/2;
if (r > h/2) r = h/2;
for (i64 c = r; c < w-r; c++) { da_pixel(ac, x+c, y, color); da_pixel(ac, x+c, y+h-1, color); }
for (i64 rr = r; rr < h-r; rr++) { da_pixel(ac, x, y+rr, color); da_pixel(ac, x+w-1, y+rr, color); }
for (i64 dy = 0; dy <= r; dy++)
for (i64 dx = 0; dx <= r; dx++) {
i64 d2 = dx*dx+dy*dy;
if (d2 <= r*r && d2 > (r-1)*(r-1)) {
da_pixel(ac, x+r-dx, y+r-dy, color);
da_pixel(ac, x+w-1-r+dx, y+r-dy, color);
da_pixel(ac, x+r-dx, y+h-1-r+dy, color);
da_pixel(ac, x+w-1-r+dx, y+h-1-r+dy, color);
}
}
}
/* ========== ASCII 字体渲染 ==========
*
* 使用方法:先 #include ascii_bitmaps.c(定义 static g_ascii/g_ascii_w/g_ascii_h),
* 再 #include desktop_app.h。da_draw_char/da_draw_string 直接引用 g_ascii。
* 与 deshab_ui.h 使用相同的包含顺序约定。
*/
static inline void da_draw_char(da_app_context *ac, char ch, i64 x, i64 y, u32 fg, u32 bg) {
u32 idx = (u32)(ch - ' ');
if (idx > 94) idx = 0;
const u8 *glyph = g_ascii[idx];
i64 gw = g_ascii_w, gh = g_ascii_h;
for (i64 r = 0; r < gh; r++) {
i64 yy = y + r;
if (yy < 0 || (u64)yy >= ac->fb_h) continue;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)yy * ac->fb_pitch);
for (i64 c = 0; c < gw; c++) {
u8 a = glyph[r * gw + c];
if (a == 0) continue;
i64 xx = x + c;
if (xx < 0 || (u64)xx >= ac->fb_w) continue;
line[xx] = (a == 255) ? fg : da_blend(bg, fg, a);
}
}
}
static inline void da_draw_string(da_app_context *ac, const char *s, i64 x, i64 y, u32 fg, u32 bg, i64 step) {
i64 cx = x;
while (*s) { da_draw_char(ac, *s, cx, y, fg, bg); cx += step; s++; }
}
/* ========== 鼠标光标 ========== */
#define DA_CURSOR_SIZE 24
static const u8 da_cursor_shape[24][24] = {
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};
typedef struct {
u32 save[DA_CURSOR_SIZE * DA_CURSOR_SIZE];
int saved;
int old_x, old_y;
int mx, my;
int btn;
} da_cursor;
static inline void da_cursor_init(da_cursor *c, i64 fb_w, i64 fb_h) {
for (int i = 0; i < DA_CURSOR_SIZE*DA_CURSOR_SIZE; i++) c->save[i] = 0;
c->saved = 0; c->old_x = -1; c->old_y = -1;
c->mx = (int)(fb_w / 2); c->my = (int)(fb_h / 2); c->btn = 0;
}
static inline void da_cursor_save(da_app_context *ac, da_cursor *c) {
for (int r = 0; r < DA_CURSOR_SIZE; r++)
for (int col = 0; col < DA_CURSOR_SIZE; col++) {
int x = c->mx + col, y = c->my + r;
c->save[r * DA_CURSOR_SIZE + col] = da_pixel_read(ac, x, y);
}
c->saved = 1; c->old_x = c->mx; c->old_y = c->my;
}
static inline void da_cursor_restore(da_app_context *ac, da_cursor *c) {
if (!c->saved) return;
for (int r = 0; r < DA_CURSOR_SIZE; r++)
for (int col = 0; col < DA_CURSOR_SIZE; col++) {
int x = c->old_x + col, y = c->old_y + r;
da_pixel(ac, x, y, c->save[r * DA_CURSOR_SIZE + col]);
}
c->saved = 0;
}
static inline void da_cursor_draw(da_app_context *ac, da_cursor *c, u32 color) {
for (int r = 0; r < DA_CURSOR_SIZE; r++)
for (int col = 0; col < DA_CURSOR_SIZE; col++)
if (da_cursor_shape[r][col])
da_pixel(ac, c->mx + col, c->my + r, color);
}
/* ========== PS/2 鼠标 ========== */
typedef struct {
u8 buf[3];
int idx;
int has_pkt;
} da_mouse;
static inline void da_mouse_init(void) {
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x64, 0xA8);
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x64, 0x20);
for (int t = 0; t < 100000; t++) { if (inb(0x64) & 1) break; }
u8 cfg = inb(0x60);
cfg |= 0x02; cfg &= ~0x20;
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x64, 0x60);
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x60, cfg);
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x64, 0xD4);
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x60, 0xFF);
for (int t = 0; t < 100000; t++) { if (inb(0x64) & 1) break; }
inb(0x60);
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x64, 0xD4);
for (int t = 0; t < 100000; t++) { if (!(inb(0x64) & 2)) break; }
outb(0x60, 0xF4);
for (int t = 0; t < 100000; t++) { if (inb(0x64) & 1) break; }
inb(0x60);
}
static inline int da_mouse_poll(da_mouse *m, da_cursor *c, i64 fb_w, i64 fb_h) {
u8 st = inb(0x64);
if (!(st & 1)) return 0;
u8 data = inb(0x60);
if (!(st & 0x20)) return 0;
m->buf[m->idx++] = data;
if (m->idx < 3) return 0;
m->idx = 0;
if (!(m->buf[0] & 0x08)) return 0;
int dx = (int)(signed char)m->buf[1];
int dy = (int)(signed char)m->buf[2];
if (m->buf[0] & 0x10) dx = -dx;
if (!(m->buf[0] & 0x20)) dy = -dy; else dy = -dy;
dy = -dy;
c->mx += dx; c->my += dy;
if (c->mx < 0) c->mx = 0;
if (c->my < 0) c->my = 0;
if (c->mx >= (int)fb_w - DA_CURSOR_SIZE) c->mx = (int)fb_w - DA_CURSOR_SIZE;
if (c->my >= (int)fb_h - DA_CURSOR_SIZE) c->my = (int)fb_h - DA_CURSOR_SIZE;
c->btn = (m->buf[0] & 0x01) ? 1 : 0;
m->has_pkt = 1;
return 1;
}
/* ========== 键盘 ========== */
static inline char da_scan_to_ascii(u8 sc, int shift) {
static const char normal[58] = {
0, 27, '1','2','3','4','5','6','7','8','9','0','-','=', 8, '\t',
'q','w','e','r','t','y','u','i','o','p','[',']','\n',0,
'a','s','d','f','g','h','j','k','l',';','\'', '`',0,'\\',
'z','x','c','v','b','n','m',',','.','/',0,'*',0,' '
};
static const char shifted[58] = {
0, 27, '!','@','#','$','%','^','&','*','(',')','_','+', 8, '\t',
'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',0,
'A','S','D','F','G','H','J','K','L',':','"','~',0,'|',
'Z','X','C','V','B','N','M','<','>','?',0,'*',0,' '
};
if (sc >= 58) return 0;
return shift ? shifted[sc] : normal[sc];
}
/* ========== 窗口概念 ========== */
/* 独立工具全屏运行时的窗口装饰:标题栏 + 关闭按钮 */
#define DA_TITLEBAR_H 28
#define DA_BORDER_W 2
#define DA_STATUSBAR_H 20
/* 色板引用(与 deshab_ui.h 一致) */
#define DA_BG_PRIMARY 0xFF0A1428u /* DP_ABYSS_900 */
#define DA_BG_SECONDARY 0xFF0F1E38u /* DP_ABYSS_800 */
#define DA_BG_TERTIARY 0xFF162848u /* DP_ABYSS_700 */
#define DA_TEXT_PRIMARY 0xFFE8E8F0u /* DP_NEUTRAL_700 */
#define DA_TEXT_DIM 0xFF6A6A88u /* DP_NEUTRAL_300 */
#define DA_ACCENT 0xFF00A8CCu /* DP_SEAL_500 */
#define DA_ACCENT_LIGHT 0xFF44CCF0u /* DP_SEAL_300 */
#define DA_BORDER 0xFF284888u /* DP_ABYSS_500 */
#define DA_BORDER_FOCUS 0xFF44CCF0u /* DP_SEAL_300 */
#define DA_CURSOR_COLOR 0xFF00A8CCu /* DP_SEAL_500 */
#define DA_PROMPT_COLOR 0xFF44CCF0u /* DP_SEAL_300 */
#define DA_SUCCESS 0xFF40C880u /* DP_SUCCESS */
#define DA_ERROR 0xFFFF4466u /* DP_ERROR */
#define DA_WARNING 0xFFF0A030u /* DP_WARNING */
static inline void da_draw_titlebar(da_app_context *ac, const char *title, i64 w) {
da_fill_rect(ac, 0, 0, w, DA_TITLEBAR_H, DA_BG_SECONDARY);
da_draw_string(ac, title, 8, (DA_TITLEBAR_H - 18) / 2, DA_TEXT_PRIMARY, DA_BG_SECONDARY, 12);
/* 关闭按钮 */
da_fill_rounded_rect(ac, w - 28, 4, 24, 20, DA_ERROR, 4);
da_draw_string(ac, "X", w - 20, 5, 0xFF0A1428u, DA_ERROR, 12);
/* 底部分隔线 */
da_fill_rect(ac, 0, DA_TITLEBAR_H, w, 1, DA_ACCENT);
}
static inline void da_draw_statusbar(da_app_context *ac, const char *text, i64 w, i64 h) {
i64 y = h - DA_STATUSBAR_H;
da_fill_rect(ac, 0, y, w, DA_STATUSBAR_H, DA_BG_SECONDARY);
da_draw_string(ac, text, 4, y + 1, DA_TEXT_DIM, DA_BG_SECONDARY, 12);
/* 顶部分隔线 */
da_fill_rect(ac, 0, y, w, 1, DA_BORDER);
}
/* ========== RTC 时钟 ========== */
static inline void da_rtc_time(u8 *h, u8 *m) {
outb(0x70, 4); *h = inb(0x71);
outb(0x70, 2); *m = inb(0x71);
*h = (u8)((*h >> 4) * 10 + (*h & 0xF));
*m = (u8)((*m >> 4) * 10 + (*m & 0xF));
}
/* ========== memset/memcpy ========== */
static inline void *da_memset(void *d, int c, u64 n) { u8 *p=(u8*)d; while(n--)*p++=(u8)c; return d; }
static inline void *da_memcpy(void *d, const void *s, u64 n) { u8 *dd=(u8*)d; const u8 *ss=(const u8*)s; while(n--)*dd++=*ss++; return d; }
#endif /* DESHAB_DESKTOP_APP_H */