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
+461
View File
@@ -0,0 +1,461 @@
# Deshab 桌面环境架构设计
## 1. 概述
Deshab 桌面环境(Deshab Desktop Environment, DDE)是基于 UTSM/DSK 内核的图形桌面系统,
运行在 SAS-R0(单地址空间 Ring0)任务模型上,使用 "Sealed Arc" 视觉风格系统。
**设计原则**:
- **SAS-R0 适配**:无内存隔离,所有应用共享地址空间,信任模型为 Ring0 全信任
- **单屏幕协作**:初期采用"多窗口前台 + 桌面后台"模式,桌面管理器始终驻留
- **应用独立开发**:内置应用使用回调模式;未来工具应用为独立 .elf,通过 ELF 加载方式载入
- **帧缓冲直绘**:无 GPU 加速,所有渲染通过 du_context 直接写 framebuffer
**当前实现状态**:desktop.elf 已实现完整的桌面管理器框架,包括窗口管理、事件路由、
PS/2 鼠标初始化+轮询、光标 save/restore、任务栏、桌面图标和 3 个内置应用。
## 2. 系统架构
```
┌─────────────────────────────────────────────────────┐
│ Framebuffer │
│ ┌─────────────────────────────────────────────┐ │
│ │ Desktop Manager (desktop.elf) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Window 1 │ │ Window 2 │ │ Window 3 │ │ │
│ │ │ (bash) │ │ (editor) │ │ (calc) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────┐│ │
│ │ │ Taskbar (40px) ││ │
│ │ └─────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
```
## 3. 启动流程
```
UEFI → Limine → utsm.elf → DKM 驱动加载
→ deshab.elf (DSK) → spinner → firstInit.txt 检查
→ mouseInit.elf → netman.elf → [首次] FirstInit.elf
→ desktop.elf ← 桌面管理器
```
DSK 在 FirstInit 完成或 firstInit=1 时,加载 `desktop.elf`。
desktop.elf 通过 `dsk_entry(dsk_boot_context *ctx)` 入口接收系统上下文,
自行初始化 PS/2 鼠标、注册应用、进入主事件循环。
## 4. Desktop Manager 核心设计
### 4.1 窗口模型
```c
typedef struct desktop_window {
int id; /* 窗口 ID(自增分配) */
int x, y, w, h; /* 窗口位置和尺寸 */
int visible; /* 可见性 */
int focused; /* 焦点 */
int minimized; /* 最小化 */
char title[48]; /* 窗口标题 */
/* 应用关联 */
int app_id; /* 关联的应用 ID(g_apps 索引) */
void *app_state; /* 应用私有状态(on_create 返回值) */
int closing; /* 关闭中标记 */
int dirty; /* 脏标记(需要重绘) */
} desktop_window;
```
**Z 序**:窗口按数组顺序排列,数组末尾的窗口在最上层。`win_bring_to_front()` 将窗口移到数组末尾。
**窗口限制**:最多 8 个窗口(`MAX_WINDOWS`)。
**固定地址分配**:当前内置应用使用固定地址分配状态结构,避免堆依赖:
- `0x4000000` — bash_state(终端)
- `0x5000000` — editor_state(编辑器)
- `0x6000000` — calc_state(计算器)
### 4.2 事件系统
```c
typedef enum {
EV_MOUSE_MOVE = 1,
EV_MOUSE_DOWN,
EV_MOUSE_UP,
EV_KEY_DOWN,
EV_KEY_UP,
} ev_type;
typedef struct {
ev_type type;
int mx, my; /* 鼠标全局坐标 */
int button; /* 0=左, 1=右 */
u8 scancode;
int shift, ctrl, alt;
} desktop_event;
```
**事件路由**:
1. **鼠标事件** → 从后往前命中测试 → 找到目标窗口 → 检查关闭按钮/标题栏/客户区 → 路由到窗口回调
2. **键盘事件** → 当前焦点窗口的 `on_event` 回调
3. **任务栏点击** → 桌面管理器直接处理(快速启动/窗口按钮)
4. **桌面图标点击** → 桌面管理器处理(`launch_app()`)
**拖拽机制**:
- 鼠标按下 + 命中标题栏 → 进入拖拽模式(`g_dragging=1`)
- 拖拽期间鼠标移动 → 更新窗口位置(`w->x = mouse_x - offset`)
- 鼠标释放 → 退出拖拽模式
**关闭机制**:
- 鼠标点击窗口右上角红色 X 按钮(24×20 圆角矩形,DP_ERROR 底色)
- `win_destroy()` 调用应用的 `on_destroy`,从窗口数组移除,焦点转移到最后一个窗口
### 4.3 应用 ABI(回调模式)
```c
typedef struct app_ctx {
du_context *fb; /* 全局帧缓冲渲染上下文 */
desktop_win *win; /* 关联窗口 */
int client_x, client_y, client_w, client_h; /* 客户区坐标 */
int should_exit; /* 退出标志 */
desktop_block_read_fn block_read; /* FAT32 块读取函数 */
const void *kernel_api; /* DKM kernel_api 分发表 */
} app_ctx;
typedef void *(*app_create_fn)(app_ctx *ctx);
typedef void (*app_event_fn)(void *state, app_ctx *ctx, desktop_event *ev);
typedef void (*app_draw_fn)(void *state, app_ctx *ctx);
typedef void (*app_destroy_fn)(void *state);
typedef struct {
const char *name; /* 应用标识名 */
const char *display_name; /* UI 显示名 */
u32 default_w, default_h; /* 默认窗口尺寸 */
app_create_fn on_create;
app_event_fn on_event;
app_draw_fn on_draw;
app_destroy_fn on_destroy;
} app_descriptor;
```
**应用生命周期**:
1. 用户点击桌面图标或快速启动 → `launch_app(app_id)`
2. 创建窗口 → 构建 `app_ctx` → 调用 `on_create(ctx)` → 返回 `app_state`
3. 事件循环中:`on_event(state, ctx, ev)` 处理输入
4. 绘制时:`on_draw(state, ctx)` 渲染客户区
5. 关闭窗口 → `on_destroy(state)` 清理
**当前注册的应用**:
| app_id | name | display_name | 默认尺寸 | 状态 |
|--------|------|-------------|----------|------|
| 0 | bash | Terminal | 640×440 | 已实现 |
| 1 | editor | Editor | 600×450 | 已实现 |
| 2 | fileman | Files | 500×400 | 占位(无回调) |
| 3 | calc | Calculator | 280×400 | 已实现 |
### 4.4 任务栏 (Taskbar)
位置:屏幕底部,高度 40px。
布局:
```
┌──────────────────────────────────────────────────────────┐
│ [D] │ 🖥️ 📝 📁 🧮 │ │ 12:34 │
│Start│ 快速启动(4图标) │ 窗口按钮 │ RTC时钟 │
└──────────────────────────────────────────────────────────┘
```
分区:
- **Start 按钮**(48×32,DP_ABYSS_600 圆角矩形):显示 "D" 字符(DS_DARK_ACCENT_LIGHT)
- **快速启动**(4 图标 × 40px):按 app_id 顺序绘制程序化图标(终端/编辑器/文件夹/计算器)
- **窗口按钮区**:每个打开窗口一个 100×32 按钮,焦点窗口用 DS_DARK_ACCENT 底色,其余用 DP_ABYSS_600
- **RTC 时钟**(右侧 80px 区域):通过 CMOS I/O(端口 0x70/0x71)读取 BCD 时分,转换为 HH:MM 格式
### 4.5 桌面图标
位置:桌面右侧垂直排列。
参数:
- 列宽 80px(`DESKTOP_ICON_W`),行高 72px(`DESKTOP_ICON_H`)
- 左边距 16px(`ICON_GUTTER_X`),上边距 16px(`ICON_GUTTER_Y`)
- 起始 X = `fb_width - 80 - 16`
图标:32×32 像素,程序化生成(无需位图文件),通过 `draw_icon_*` 函数绘制:
- **终端图标**:DP_ABYSS_700 圆角矩形 + DP_SEAL_300 的 >_ 符号 + DP_SEAL_500 边框
- **编辑器图标**:DP_ABYSS_700 圆角矩形 + DP_SEAL_500 文本行 + DP_SEAL_300 边框
- **文件夹图标**:DP_ARC_500 圆角矩形 + DP_ARC_300 文件夹形状 + DP_ARC_700 边框
- **计算器图标**:DP_ABYSS_700 圆角矩形 + DP_WARNING 按键 + DP_NEUTRAL_400 网格
标签:图标下方 36px 处,居中绘制应用 display_name,使用 DS_DARK_TEXT_PRIMARY 颜色。
### 4.6 窗口装饰
**标题栏**(28px,`TITLEBAR_H`):
- 焦点窗口:DP_ABYSS_600 背景
- 非焦点窗口:DP_ABYSS_800 背景
- 标题文字:左侧 DU_SPACE_SM 偏移,DS_DARK_TEXT_PRIMARY 颜色
- 关闭按钮:右上角,窗口右边 -28px 处,24×20 圆角矩形,DP_ERROR (红色) 底色 + 白色 "X"
**边框**(2px,`BORDER_W`):
- 焦点窗口:DS_DARK_BORDER(Seal Cyan 发光效果)
- 非焦点窗口:DS_DARK_BORDER
- 焦点发光:`du_rect_glow()` 3px 扩展范围,10px 衰减
**标题栏底线**:1px 分隔线,颜色同边框色。
**圆角**:窗口主体使用 `DU_RADIUS_LG` 圆角,关闭按钮使用 `DU_RADIUS_SM` 圆角。
### 4.7 应用加载模型
**方式一:回调式(当前实现)**
应用编译进 desktop.elf 内部,通过 `app_descriptor` 注册回调函数。
桌面管理器在事件循环中调用 `on_event()`/`on_draw()`,应用通过 `app_ctx` 访问系统服务。
特点:
- 应用与桌面管理器在同一 ELF 中,共享代码和全局变量
- 应用状态使用固定地址分配(避免堆依赖)
- 应用可以直接访问 g_fb 全局帧缓冲
**方式二:独立 ELF 加载式(未来实现)**
工具应用独立开发为单独 .elf 文件(如 `CODE/tools/bash/`),通过 DSK 的 FAT32 + ELF loader 加载。
独立工具实现 `dsk_entry(dsk_boot_context *ctx)` 入口点,接收与 DSK 相同的系统上下文。
未来桌面管理器将通过 ELF 加载方式载入工具 .elf,需要实现:
- ELF 加载到内存 + PIE 重定位
- 传入 dsk_boot_context(framebuffer、kernel_api、block_read 等)
- 返回机制(在 ELF 入口点保存返回地址)
- 独立工具的公共辅助代码(`CODE/tools/desktop_app.h`)
## 5. 渲染管线
```
redraw_all() 完整管线:
1. 渐变背景(du_fill_bg_gradient: DP_ABYSS_900 → DP_ABYSS_800)
2. 桌面图标(draw_desktop_icons)
3. 窗口循环(从底到顶):
a. 应用 on_draw() 绘制客户区内容
b. draw_window_frame() 绘制窗口装饰(在应用内容之上)
4. 任务栏(draw_taskbar)
5. 鼠标光标(cursor_save_bg + cursor_draw)
```
**渲染策略**:
- 每帧全屏重绘(无增量更新)
- 鼠标光标使用 save/restore 机制:移动前恢复旧位置背景,重绘后保存新位置背景
- 应用直接写入全局 framebuffer(无窗口后缓冲),窗口装饰在应用内容之上绘制
- 重绘触发:鼠标移动/点击、键盘事件、窗口状态变化
## 6. 像素格式
与现有 framebuffer 一致:32bpp ARGB(0xAARRGGBB),小端存储。
所有颜色值使用 deshab_ui.h 中的语义色令牌。
## 7. 鼠标光标
24×24 像素箭头光标:
- 热点在左上角 (0,0)
- 形状定义:`cursor_shape[24][24]` 位图数组(1=前景,0=透明)
- 前景色:DS_DARK_TEXT_PRIMARY
- save/restore 实现无闪烁移动:
- `cursor_save_bg()`: 保存光标位置 24×24 像素到 `g_cursor_save[]`
- `cursor_restore_bg()`: 恢复上次保存的像素
- 每帧重绘时:先 restore 旧位置 → 全屏绘制 → save + draw 新位置
- 边界限制:光标不超出屏幕范围(减去 CURSOR_SIZE)
## 8. 输入处理
### 8.1 PS/2 鼠标
**初始化**(`ps2_mouse_init()`):
1. 启用 AUX 设备(命令 0xA8 → 0x64)
2. 读取控制器配置字节(0x20 → 0x64),设置 bit1(AUX IRQ12)+ 清除 bit5(AUX clock)
3. 写回配置(0x60 → 0x64)
4. 复位鼠标(0xD4 → 0x64,0xFF → 0x60)
5. 启用 streaming(0xD4 → 0x64,0xF4 → 0x60)
**轮询**(`ps2_mouse_poll()`):
- 读取端口 0x64 状态,检查 bit0(数据就绪)和 bit5(AUX 标记)
- 读取 0x60 数据,累积 3 字节组成一个鼠标包
- 校验 byte0 bit3 同步位
- 解析 X/Y 位移(带符号扩展)和左键状态(byte0 bit0)
- Y 轴翻转处理(鼠标 Y 向上为正,屏幕 Y 向下为正)
- 边界裁剪:光标限制在屏幕范围内
### 8.2 PS/2 键盘
- IRQ1 → scan code set 1
- 扩展键 E0 前缀追踪(`g_e0` 标记)
- Shift 修饰键追踪(0x2A/0x36 按下,0xAA/0xB6 释放)
- `scan_to_ascii()` 映射:normal[58] + shifted[58] 查找表
- 键盘事件发送到焦点窗口的 `on_event` 回调
**全局快捷键**(规划中):
- Alt+Tab:窗口切换
- Alt+F4:关闭窗口
## 9. 文件系统接口
工具应用通过 `app_ctx.block_read` 访问 FAT32 文件系统。
`block_read` 函数类型:
```c
typedef int (*desktop_block_read_fn)(void *ctx, unsigned long long lba, unsigned int count, void *buffer);
```
从 `dkm_kernel_api + 0xA8` 偏移处获取函数指针。
暂不实现 VFS 系统调用——所有文件操作通过直接 FAT32 路径解析完成。
## 10. 网络接口
网络工具(curl、ping、browser)依赖 netman 已实现的:
- DHCP 客户端
- ARP 解析
- DNS 查询
- e1000/virtio_net TX/RX
工具应用通过 `kernel_api.net` 访问网络功能。
## 11. 内置应用详情
### 11.1 终端 (Bash)
- 状态结构:`bash_state` @ 0x4000000
- 终端缓冲:80 列 × 40 行(TERM_MAX_COLS × TERM_MAX_ROWS)
- 每格存储:字符(u8) + 前景色(u32)
- 输入缓冲:256 字节,支持插入模式和光标移动
- 提示符:`deshab# `
- 命令:help, clear, echo, version/ver, uname, date, about, reboot, halt, pwd, whoami, id
- 渲染:先绘制历史内容,再绘制当前输入行+光标
- 光标:2px 高下划线,DS_DARK_CURSOR 颜色
- 配色:DS_DARK_* 暗色主题
### 11.2 文本编辑器 (Editor)
- 状态结构:`editor_state` @ 0x5000000
- 文本缓冲:65536 字节(EDITOR_BUF_SIZE)
- 编辑操作:插入/删除字符、换行、方向键移动、Home/End
- 行号:3 位数字 + 分隔线(DS_DARK_TEXT_DIM 颜色)
- 自动滚动:光标超出可视区域时调整 scroll_y
- 状态栏:底部 20px,显示 L:行 C:列 + 修改标记(*)
- 光标:2px 宽竖线,DS_DARK_CURSOR 颜色
- 编辑区背景:DS_DARK_BG_SECONDARY
- 窗口标题:`Editor - untitled`
### 11.3 计算器 (Calculator)
- 状态结构:`calc_state` @ 0x6000000
- 运算:四则运算(+/-/×/÷),i64 精度
- 显示屏:圆角矩形,右对齐数字
- 按钮网格:4×5 布局(C/+/-/%/÷, 7/8/9/×, 4/5/6/-, 1/2/3/+, 0/./=)
- 按键颜色:功能键 DP_ABYSS_600,运算符 DS_DARK_ACCENT,等号 DP_SUCCESS
- 输入:键盘数字键 + 运算符,C 清零,Enter/= 计算
## 12. 分阶段实现计划
### Phase 1 — 桌面基础(已完成)
- ✅ Desktop Manager 核心框架
- ✅ 任务栏 + 时钟 + 桌面图标
- ✅ 窗口管理(创建/销毁/移动/焦点/拖拽)
- ✅ 事件路由系统
- ✅ PS/2 鼠标初始化 + 轮询
- ✅ 光标 save/restore
- ✅ 终端应用(Bash)
- ✅ 文本编辑器(Editor)
- ✅ 计算器(Calculator)
### Phase 2 — 文件操作与独立应用
- 工具应用独立开发框架(CODE/tools/ + desktop_app.h)
- FAT32 路径解析增强(目录遍历)
- 文件管理器(独立 .elf)
- 编辑器独立化(从内置 → 独立 tools/editor/)
- 文件打开器(关联 .txt → 编辑器)
- Ctrl+S 保存(需 FAT32 write API)
### Phase 3 — 网络
- TCP/IP 最小实现(基于 e1000/virtio_net)
- ping 工具(ICMP Echo)
- curl 工具(HTTP GET)
### Phase 4 — 高级应用
- 浏览器(HTTP + 简单 HTML 渲染)
- Bash 增强版(命令历史↑↓、ls、cat、Tab 补全)
- 更多系统工具
## 13. 目录结构
```
CODE/
desktop/ 桌面管理器(当前实现)
main.c 主循环、事件路由、compositing、3个内置应用
linker.ld PIE 链接脚本
MAKEFILE 构建脚本(输出 desktop.elf)
tools/ 独立工具应用(未来实现)
desktop_app.h 公共辅助头文件
bash/ 独立终端
main.c
MAKEFILE
linker.ld
editor/ 独立文本编辑器
main.c
MAKEFILE
linker.ld
fileman/ 文件管理器
main.c
MAKEFILE
linker.ld
browser/ 浏览器
main.c
MAKEFILE
linker.ld
curl/ HTTP 客户端
main.c
MAKEFILE
linker.ld
ping/ ICMP 工具
main.c
MAKEFILE
linker.ld
```
## 14. 构建与打包
### 当前构建
desktop.elf 编译输出到 `SYSTEM/system/deshab64/desktop.elf`。
编译参数(与 DSK / shell / FirstInit 一致):
```
clang -target x86_64-unknown-none -std=c11 -ffreestanding -fno-builtin
-fno-stack-protector -fpie -mno-red-zone -mno-sse -mno-sse2
-mno-mmx -msoft-float -m64 -Wall -Wextra -I../UTSM/include -O2
ld.lld -nostdlib -static -pie -z max-page-size=0x1000 -T linker.ld
```
### 未来工具应用构建
独立工具 .elf 将输出到 `SYSTEM/system/deshab64/tools/`,构建集成:
- 每个工具有独立 MAKEFILE(与 desktop 相同模式)
- build.ps1 中添加工具构建步骤
- mkfat32.c 中添加工具 .elf 入口
```
SYSTEM/system/deshab64/
desktop.elf ← 桌面管理器
tools/
bash.elf ← 独立终端
editor.elf ← 独立文本编辑器
fileman.elf ← 文件管理器
browser.elf ← 浏览器
curl.elf ← HTTP 客户端
ping.elf ← ICMP 工具
```
DSK 启动流程:
- 首次启动:mouseInit → netman → FirstInit → desktop
- 非首次启动:mouseInit → netman → desktop
+528
View File
@@ -0,0 +1,528 @@
# Deshab 工具应用设计文档
## 1. 概述
Deshab 工具应用是独立开发、独立编译的 .elf 可执行文件,运行在桌面管理器(Desktop Manager)环境中。
每个工具在 `CODE/tools/{name}/` 下拥有独立的 `main.c` + `MAKEFILE` + `linker.ld`,
通过 DSK 的 FAT32 + ELF loader 加载,接收 `dsk_boot_context` 系统上下文。
**核心约束**:
- 所有应用运行在 Ring0,单地址空间,无内存隔离
- 独立工具通过 `dsk_entry(dsk_boot_context *ctx)` 入口点启动
- 工具可以直接访问 framebuffer、PS/2 输入、kernel_api
- 网络工具依赖 kernel_api.net,文件工具依赖 FAT32 block_read
- 公共辅助代码通过 `CODE/tools/desktop_app.h` 共享
**开发模式演进**:
- **当前阶段**:3 个内置应用(Bash/Editor/Calculator)使用回调模式编译在 desktop.elf 内
- **目标阶段**:工具应用独立开发为单独 .elf,桌面管理器通过 ELF 加载方式载入
## 2. 应用 ABI
### 2.1 独立工具入口
独立工具 .elf 实现以下入口点:
```c
__attribute__((visibility("default")))
void dsk_entry(const dsk_boot_context *ctx);
```
工具接收完整的 `dsk_boot_context`,包含:
```c
typedef struct dsk_boot_context {
u64 magic; /* 0x44534B31424F4F54 ("DSK1BOOT") */
u32 abi_version; /* 1 */
u32 size;
u64 flags;
u64 hhdm_offset;
u64 rsdp_address;
u64 framebuffer_address; /* 帧缓冲物理地址 (+ HHDM) */
u64 framebuffer_width;
u64 framebuffer_height;
u64 framebuffer_pitch;
u32 framebuffer_bpp;
u64 boot_modules_response;
u64 dkm_kernel_api; /* 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;
} dsk_boot_context;
```
### 2.2 公共辅助头文件
`CODE/tools/desktop_app.h` 提供所有工具共享的定义和辅助函数:
```c
/* 类型定义 */
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
/* COM1 串口日志 */
#define COM1 0x3F8
static inline void outb(u16 port, u8 value);
static inline u8 inb(u16 port);
void sputc(char c);
void swrite(const char *s);
void slog(const char *s);
/* PS/2 键盘轮询 */
int ps2kbd_poll(u8 *scancode); /* 返回 1=有数据 */
/* PS/2 鼠标轮询 */
int ps2mouse_poll(int *dx, int *dy, int *btn); /* 返回 1=有数据包 */
/* scan code set 1 → ASCII 映射 */
char scan_to_ascii(u8 sc, int shift);
/* 帧缓冲绘制辅助 */
void fb_init(u64 addr, u64 w, u64 h, u64 pitch);
void fb_pixel(int x, int y, u32 color);
void fb_rect(int x, int y, int w, int h, u32 color);
void fb_string(const char *s, int x, int y, u32 fg, u32 bg, int step);
/* FAT32 文件读取辅助 */
typedef int (*block_read_fn)(u32 index, u64 lba, u32 count, void *buf);
int fat32_read_file(block_read_fn br, const char *path, u8 **data, u32 *size);
/* 窗口概念(标题栏+关闭按钮+客户区) */
#define WIN_TITLEBAR_H 28
#define WIN_BORDER_W 2
void win_draw_frame(int x, int y, int w, int h, const char *title, int focused);
int win_hit_close(int wx, int wy, int ww, int wh, int mx, int my);
```
### 2.3 当前内置应用 ABI(回调模式)
当前 3 个内置应用编译在 desktop.elf 内,使用回调模式:
```c
typedef struct app_ctx {
du_context *fb; /* 全局帧缓冲渲染上下文 */
desktop_win *win; /* 关联窗口 */
int client_x, client_y, client_w, client_h; /* 客户区坐标 */
int should_exit; /* 退出标志 */
desktop_block_read_fn block_read; /* FAT32 块读取函数 */
const void *kernel_api; /* DKM kernel_api 分发表 */
} app_ctx;
typedef void *(*app_create_fn)(app_ctx *ctx);
typedef void (*app_event_fn)(void *state, app_ctx *ctx, desktop_event *ev);
typedef void (*app_draw_fn)(void *state, app_ctx *ctx);
typedef void (*app_destroy_fn)(void *state);
```
### 2.4 应用生命周期
**回调式(当前)**:
```
1. 用户点击图标/快速启动按钮
2. 桌面管理器创建窗口
3. 桌面调用 app->on_create(ctx) → 返回 app_state
4. 事件循环:桌面调用 app->on_event(app_state, ctx, ev)
5. 绘制:桌面调用 app->on_draw(app_state, ctx)
6. 用户关闭窗口 → 桌面调用 app->on_destroy(app_state)
7. 桌面销毁窗口,回收资源
```
**独立 ELF 式(未来)**:
```
1. 桌面管理器通过 FAT32 读取工具 .elf
2. PIE ELF loader 加载 + 重定位
3. 调用 dsk_entry(ctx)
4. 工具自行接管输入/渲染/主循环
5. 工具返回 → 桌面管理器恢复控制
```
## 3. 工具应用详细设计
### 3.1 终端 (Bash) — CODE/tools/bash/
**状态**:内置版本已实现(回调模式);独立版本待开发
**功能**:
- 接收 dsk_boot_context,全屏暗色终端
- PS/2 键盘输入,命令历史(↑↓键)
- 内置命令:help, clear, echo, version/ver, uname, date, about, reboot, halt, pwd, whoami, id, ls, cat
- Sealed Arc 暗色主题(DS_DARK_* 色系)
**UI 设计**:
```
┌─ deshab# ────────────────────────────[✕]─┐
│ deshab# echo "Hello, Deshab!" │
│ Hello, Deshab! │
│ deshab# _ │
│ │
│ │
│ │
├──────────────────────────────────────────┤
│ / 12:34 │
└──────────────────────────────────────────┘
```
**独立版本结构**:
- 标题栏:`deshab#` 标题 + 右侧红色 X 关闭按钮
- 主区域:暗色终端输出区 + 当前输入行 + 闪烁光标
- 状态栏(底部 20px):左侧当前目录 `/`,右侧 RTC 时间
**数据结构**:
```c
typedef struct {
u8 ch[TERM_MAX_CHARS]; /* 字符缓冲 */
u32 fg[TERM_MAX_CHARS]; /* 前景色缓冲 */
int cols, rows; /* 终端尺寸 */
int cur_col, cur_row; /* 当前光标位置 */
char input_buf[256]; /* 当前输入行 */
int input_len, input_cursor; /* 输入长度和光标 */
int prompt_len; /* 提示符长度 */
char history[16][256]; /* 命令历史 */
int history_count; /* 历史条数 */
int history_pos; /* 历史浏览位置 */
} bash_state;
```
**命令实现**:
| 命令 | 功能 | 依赖 |
|------|------|------|
| help | 显示可用命令列表 | 无 |
| clear | 清屏 | 无 |
| echo | 回显参数 | 无 |
| version / ver | 显示版本 "Deshab OS v0.1.0" | 无 |
| uname | 显示系统名 "Deshab" | 无 |
| date | 显示 RTC 日期时间 | CMOS |
| about | 显示系统信息 | 无 |
| reboot | 重启(0x64→0xFE) | 键盘控制器 |
| halt | 停机(HLT) | 无 |
| pwd | 显示当前目录 "/" | 无 |
| whoami | 显示 "root" | 无 |
| id | 显示 "uid=0(root) gid=0(root)" | 无 |
| ls | 列出目录内容 | FAT32 增强遍历 |
| cat | 显示文件内容 | FAT32 读取 |
---
### 3.2 文本编辑器 (Editor) — CODE/tools/editor/
**状态**:内置版本已实现(回调模式);独立版本待开发
**功能**:
- 全屏编辑器,行号 + 编辑区 + 状态栏
- FAT32 文件打开(通过 kernel_api block_read)
- 编辑操作:插入/删除字符、换行、光标移动(方向键/Home/End)
- PageUp/PageDown 翻页
- 文本选择:Shift+方向键
- Ctrl+S 保存(需 FAT32 write API)
- 状态栏:行:列、文件名、修改标记
**UI 设计**:
```
┌─ Editor — README.TXT ───────────────[✕]─┐
│ 1│ # Deshab OS │
│ 2│ 单地址空间 Ring0 内核实验系统 │
│ 3│ │
│ 4│ ## 概述 │
│ 5│ Deshab 是一个...█ │
│ │ │ │
│ │ │ │
├───┴──────────────────────────────────────┤
│ L:5 C:15 README.TXT * │
└──────────────────────────────────────────┘
```
**数据结构**:
```c
typedef struct {
char text[EDITOR_BUF_SIZE]; /* 文本缓冲 (64KB) */
int text_len; /* 文本长度 */
int cursor_pos; /* 光标位置(字节偏移) */
int scroll_y; /* 垂直滚动偏移(行数) */
int cursor_line; /* 光标行号 */
int cursor_col; /* 光标列号 */
int sel_start, sel_end; /* 选择范围 */
int modified; /* 修改标记 */
char filename[128]; /* 当前文件名 */
} editor_state;
```
**渲染细节**:
- 行号:3 位数字宽度(`DS_DARK_TEXT_DIM` 颜色)+ 1px 分隔线(`DS_DARK_DIVIDER`)
- 编辑区背景:`DS_DARK_BG_SECONDARY`
- 光标:2px 宽竖线,`DS_DARK_CURSOR` 颜色
- 状态栏:底部 20px,`DP_ABYSS_800` 背景,显示 `L:行 C:列 文件名 *修改标记`
---
### 3.3 文件管理器 (FileManager) — CODE/tools/fileman/
**状态**:占位(当前 desktop.elf 中 fileman 无回调);独立版本待开发
**功能**:
- 双栏布局:左侧目录树、右侧文件列表
- FAT32 目录遍历(需增强到子目录)
- 文件图标区分:目录/ELF/TXT/CONF
- 双击打开:.txt/.conf → 编辑器,.elf → 执行
- 路径栏 + 返回按钮
**UI 设计**:
```
┌─ 文件管理器 ────────────────────────[✕]─┐
│ [←] /system/deshab64/ │
├──────────┬───────────────────────────────┤
│ / │ 📁 tools/ DIR │
│ /system │ 📄 desktop.elf 53KB ELF │
│ /driver │ 📄 editor.elf 28KB ELF │
│ │ 📄 deshab.elf 131KB ELF │
│ │ 📄 README.TXT 2KB TXT │
│ │ 📄 user.conf 1KB CONF │
├──────────┴───────────────────────────────┤
│ 6 项 │
└──────────────────────────────────────────┘
```
**文件图标颜色**:
| 类型 | 图标 | 主色调 |
|------|------|--------|
| 目录 | 📁 | DP_ARC_500 (紫) |
| ELF | 📄 + 可执行标记 | DP_SEAL_300 (青) |
| TXT | 📄 + 文本标记 | DP_NEUTRAL_300 (灰) |
| CONF | 📄 + 齿轮标记 | DP_WARNING (琥珀) |
**依赖**:FAT32 子目录遍历(当前 DSK 仅支持根目录读取,需增强)
---
### 3.4 浏览器 (Browser) — CODE/tools/browser/
**状态**:Phase 4 实现(依赖 TCP/IP + HTTP + HTML 渲染)
**功能**:
- 地址栏 + 导航按钮(后退/前进/刷新)
- HTTP GET 请求(通过 kernel_api.net)
- 简单 HTML 渲染:标题、段落、链接、列表
- 超链接点击导航
- 历史记录(后退/前进栈)
**UI 设计**:
```
┌─ 浏览器 ────────────────────────────[✕]─┐
│ [←][→][↻] [http://example.com ][Go] │
├──────────────────────────────────────────┤
│ Example Domain │
│ │
│ This domain is for use in illustrative │
│ examples in documents. You may use this │
│ domain in literature... │
│ │
│ More information... │
└──────────────────────────────────────────┘
```
**依赖**:
- TCP/IP 栈(需实现 TCP 连接、发送/接收、拥塞控制)
- HTTP/1.1 客户端(GET 请求、响应解析)
- DNS 解析(netman 已实现)
- HTML 解析器(简化版,仅处理常见标签)
---
### 3.5 HTTP 客户端 (curl) — CODE/tools/curl/
**状态**:Phase 3 实现(依赖 TCP/IP 最小实现)
**功能**:
- 命令行界面运行(终端风格)
- HTTP GET/HEAD 请求
- URL 解析(host:port/path)
- 响应头显示(`-i` 选项)
- 超时处理
**命令行**:
```
curl http://example.com
curl -i http://example.com
curl --head http://example.com
```
**UI 设计**:
```
┌─ curl ──────────────────────────────[✕]─┐
│ > curl http://example.com │
│ HTTP/1.1 200 OK │
│ Content-Type: text/html │
│ │
│ <!doctype html> │
│ <html> │
│ ... │
└──────────────────────────────────────────┘
```
**依赖**:TCP/IP 栈 + DNS 解析
**实现方式**:作为窗口化终端风格应用运行,输出 HTTP 响应内容。
---
### 3.6 ICMP 工具 (ping) — CODE/tools/ping/
**状态**:Phase 3 实现(依赖 ICMP + ARP)
**功能**:
- 发送 ICMP Echo Request
- 接收 ICMP Echo Reply
- RTT 计算(基于 PIT 已校准计时器)
- 统计信息显示(发送/接收/丢包率/平均 RTT)
**命令行**:
```
ping 192.168.1.1
ping -c 4 10.0.2.2
```
**UI 设计**:
```
┌─ ping ──────────────────────────────[✕]─┐
│ PING 192.168.1.1 │
│ 64 bytes: seq=0 time=2ms │
│ 64 bytes: seq=1 time=1ms │
│ 64 bytes: seq=2 time=3ms │
│ │
│ --- 192.168.1.1 ping statistics --- │
│ 3 packets transmitted, 3 received, 0% │
│ RTT min/avg/max = 1/2/3 ms │
└──────────────────────────────────────────┘
```
**依赖**:
- ICMP 协议实现(需通过 kernel_api.net 发送原始 IP 包)
- ARP 解析(netman 已实现)
- 计时器(PIT 已校准)
---
### 3.7 更多应用(规划中)
| 应用 | 描述 | Phase | 依赖 |
|------|------|-------|------|
| System Monitor | CPU/内存/网络状态 | 2 | kernel_api |
| Paint | 简单绘图工具 | 2 | 无 |
| Settings | 系统偏好设置 | 2 | FAT32 write |
| Screenshot | 屏幕截图保存 | 3 | FAT32 write |
| Music Player | PC 喇叭/AC97 音频 | 4 | 音频驱动 |
## 4. 依赖矩阵
```
FAT32 Read | FAT32 Write | TCP/IP | ICMP | DNS | ARP | PS/2输入
bash ✓ | | | | | | ✓
editor ✓ | (保存) | | | | | ✓
fileman ✓ | | | | | | ✓
browser ✓ | | ✓ | | ✓ | ✓ | ✓
curl ✓ | | ✓ | | ✓ | ✓ | ✓
ping ✓ | | | ✓ | | ✓ | ✓
calculator | | | | | | | ✓
```
## 5. 应用图标设计
每个应用使用 32×32 像素图标,程序化生成(C 函数绘制,无需位图文件)。
| 应用 | 图标描述 | 主色调 | 绘制函数 |
|------|----------|--------|----------|
| bash | 终端窗口 >_ | DP_SEAL_300 (亮青) | `draw_icon_terminal()` |
| editor | 笔记本+文本行 | DP_SEAL_500 (青) | `draw_icon_editor()` |
| fileman | 文件夹 | DP_ARC_500 (紫) | `draw_icon_folder()` |
| calculator | 计算器按键 | DP_WARNING (琥珀) | `draw_icon_calc()` |
| browser | 地球/指南针 | DP_SEAL_300 (亮青) | 待实现 |
| curl | 箭头+网络 | DP_SEAL_700 (深青) | 待实现 |
| ping | 信号波 | DP_SUCCESS (绿) | 待实现 |
**图标绘制规范**:
- 圆角矩形背景(6px 圆角,`DU_RADIUS_SM`)
- 1px 描边(使用边框色)
- 前景图形使用应用主色调
- 背景色:DP_ABYSS_700
## 6. 构建集成
### 6.1 独立工具 MAKEFILE
每个工具有独立的 MAKEFILE(与 desktop.elf 相同模式):
```makefile
# tools/bash/MAKEFILE 示例
CC := clang
LD := ld.lld
ROOT := ../../..
OUT := $(ROOT)/SYSTEM/system/deshab64/tools/bash.elf
CFLAGS := -target x86_64-unknown-none -std=c11 -ffreestanding -fno-builtin \
-fno-stack-protector -fpie -mno-red-zone -mno-sse -mno-sse2 \
-mno-mmx -msoft-float -m64 -Wall -Wextra -I.. -I../../UTSM/include -O2
LDFLAGS := -nostdlib -static -pie -z max-page-size=0x1000 -T linker.ld
C_SOURCES := main.c
OBJECTS := $(C_SOURCES:.c=.o)
.PHONY: all clean
all: $(OUT)
$(OUT): $(OBJECTS) linker.ld
@if not exist "$(ROOT)\SYSTEM\system\deshab64\tools" mkdir "$(ROOT)\SYSTEM\system\deshab64\tools"
$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
```
### 6.2 build.ps1 集成
在 `build.ps1` 中添加工具构建步骤:
```powershell
# 构建工具应用
$tools = @("bash", "editor", "fileman", "curl", "ping", "browser")
foreach ($tool in $tools) {
Push-Location "CODE/tools/$tool"
& make -f MAKEFILE
Pop-Location
}
```
### 6.3 FAT32 镜像更新
`mkfat32.c` 中添加工具 .elf 入口:
```
SYSTEM/system/deshab64/tools/bash.elf
SYSTEM/system/deshab64/tools/editor.elf
SYSTEM/system/deshab64/tools/fileman.elf
SYSTEM/system/deshab64/tools/curl.elf
SYSTEM/system/deshab64/tools/ping.elf
SYSTEM/system/deshab64/tools/browser.elf
```
## 7. 测试策略
- **单元测试**:每个应用的事件处理回调可用模拟事件测试
- **QEMU 集成测试**:完整的启动→桌面→打开应用→操作→关闭流程
- **串口日志**:所有应用通过 COM1 输出调试信息(`[bash]`、`[editor]` 等前缀)
- **FAT32 验证**:使用 `driver/test.fat32` 测试镜像验证文件读取功能
- **独立工具验证**:DSK 直接加载工具 .elf,检查 dsk_entry 入口调用和上下文传递