Commit Graph
90 Commits
Author SHA1 Message Date
TermiNexus 51287eb1a0 perf(explorer): per-frame window double buffering and present-aware FLUSH 2026-10-29 00:57:00 +08:00
TermiNexus 6f856992da feat: Linux ABI P0-P6, BMIDE DMA, ImageSee, 4KiB page pool and Explorer hardening 2026-10-29 00:42:21 +08:00
TermiNexus ebd43ef9da fix(explorer): make window shadows follow rounded corners
_shadow_alpha() measured the distance to the window's bounding rectangle,
so WIN11/WIN7/WINXP shadows still had square corners: the rounded corner
notch stayed unshadowed and the outer iso-alpha lines met at a right
angle.

Measure against the rectangle inset by the window radius instead. The
corner arcs now shape both the notch and the outer falloff, while the
straight edges keep the previous values. Square styles pass r = 0 and
are unchanged.
2026-10-27 22:52:01 +08:00
TermiNexus 807c4207c0 chore: raise QEMU memory and extend the FontDemo sample
Give the guest 512 MiB so the full Noto Sans SC face and the fonttools
buffers fit, and render a mixed Chinese/Latin string in FontDemo.
2026-10-27 22:44:19 +08:00
TermiNexus 9bfdaecc6b feat(vpui): support direct and Explorer-managed TTF text
vpui.set_text_mode selects:
- TEXT_MODE_DIRECT: vpui imports fonttools, loads /FONTS/FONT.TTF and
  builds the 8x16 atlas in-process.
- TEXT_MODE_MANAGED (default): text is queued per frame and drawn by
  Explorer through the new DESK_REQ_TEXT request; Explorer uses the same
  fonttools atlas.

Remove the fixed VPUI.ATL asset and its loader.
2026-10-27 22:08:16 +08:00
TermiNexus faab22c40e feat(font): use the full Noto Sans SC font and enlarge the disk
- FontDemo points at /FONTS/FONT.TTF
- build.py installs NotoSansSC-6.ttf as disk/fonts/font.ttf
- grow disk.img from 64 MiB to 256 MiB
2026-10-27 20:45:27 +08:00
TermiNexus 585d3a8215 feat(font): add Brotli/WOFF2 and TrueType text rendering
- vpsdk/brotli: Brotli decoder with the static dictionary
- vpsdk/fonttools: TTF/WOFF2 loading, cmap, glyf/composite glyphs and
  anti-aliased rasterization
- Apps/FontDemo: render 你好,世界 from a fixed font path
- autostart FontDemo and copy the Brotli dictionary into disk/libs
- build with the fixed ViperC compiler that zero-extends unsigned types
2026-10-27 20:26:05 +08:00
TermiNexus 93a4f5bdcb chore(explorer): remove [explorer] debug output
Drop startup/input/frame tracing from the desktop shell and window
server, including the one-shot diagnostic counters.
2026-10-27 17:54:06 +08:00
TermiNexus 976b8307f9 chore(scene3d): remove [s3d] debug output
Drop the serial tracing from startup, the render thread and the
pre-render loop.
2026-10-27 17:52:32 +08:00
TermiNexus 925e0ffaea feat(power): add reboot and shutdown syscalls and terminal commands
- REBOOT (0x1008): 8042 reset with PCI 0xCF9 fallback
- SHUTDOWN (0x1009): ACPI S5 writes to the common QEMU/Bochs/VBox
  PM1a control ports, then halt
- vpsdk.process.reboot()/shutdown()
- Terminal commands: reboot, shutdown (help updated)
2026-10-27 16:56:26 +08:00
TermiNexus c379cadc38 feat(terminal): 日志与输入行之间留空行
- Text._exec_input 在本命令确实产生输出时追加一个空行,
  提示符与最后一条日志之间保持一个空行;无输出的命令不补
- 用实际 line_count 判断,clear 后不会被误补空行
- Terminal 启动时的介绍日志后也插入一个空行
2026-10-27 14:52:09 +08:00
TermiNexus 99c8cea8ee feat(window): 滚轮事件下传与 Terminal 滚动
- desk 协议新增 DESK_MOUSE_WHEEL;window 新增 EVENT_TYPE_WHEEL
- Explorer 汇总一批鼠标包的 wheel 增量,投给光标下的窗口
  (窗口内坐标;任务栏区域不投递)
- InputEvent.button 承载滚轮有符号增量(uint8 编码,消费方按 int8 解码)
- vpui.Text 处理 WHEEL:每次滚动 3 行,按“输出行 + 输入行”总行数钳制,
  并同步滚动条;输入行仍保持在可视区内
2026-10-27 14:50:04 +08:00
TermiNexus 5e2598a992 feat(terminal): 输入行跟随输出并显示当前路径
- Text 不再把输入行固定在控件底部:输入行紧跟在最后一条输出之后,
  输出增加时随之下移;超出可视区时 scroll_offset 保持输入行可见
- Text 增加 prompt 字段 / set_prompt;点击定位、光标、_exec_input、
  滚动条计算都按实际 prompt 长度和总行数(输出行 + 输入行)计算
- Terminal 的提示符改为“归一化路径 + /> ”:
  根目录是 "/> ",/apps 是 "/apps/> "
- cd 成功后更新提示符;裸 cd 仍打印当前路径
2026-10-27 14:41:35 +08:00
TermiNexus ab18afd26e feat(window): WIN7 关闭按钮红底改为圆形
WIN7 样式的关闭按钮仍保留 28×20 的命中区,但红色背景改为
区域内居中的 20×20 圆,圆心与 X 图标中心重合;
hover / 按下时的颜色变化规则不变。
2026-10-27 14:40:48 +08:00
TermiNexus b94de46ce5 feat(window): 任务栏层级提升到窗口之上
- render_range 顺序改为:背景 → 窗口 → 任务栏 → 光标,
  窗口拖到任务栏区域时会被任务栏盖住
- hit_test 在任务栏高度内直接返回 -1,避免窗口视觉上被任务栏
  盖住后还能点到下面的窗口;任务栏图标仍由 _taskbar_icon_hit 处理
2026-10-27 14:35:38 +08:00
TermiNexus f9e91a9d6e fix(gargantua): 调整窗口大小时不再改画布源尺寸
现象:计算过程中拖动/缩放 Gargantua 窗口,tid=2 以
[0E] rip=0x413f2f cr2=0x46c000 退出。

原因:RESIZE 处理器把 FBCanvas 的源尺寸用
set_fb(fb, new_w, new_h) 改成窗口内容尺寸,但 _fb_mem 仍是固定的
160×90。窗口变大后 FBCanvas.draw 会按新的 _cw 逐行读取
self._fb[py*_cw+px],越过 _fb_mem 末尾(0x46c000)触发用户态缺页。

修复:RESIZE 时不再改画布源尺寸,只调用 root.redraw() 按新窗口
尺寸重绘;超过源尺寸的部分由 FBCanvas 现有的 min(_cw,self.w)
裁剪逻辑处理。
2026-10-27 14:23:35 +08:00
TermiNexus 845633773b fix(window): 标题栏按钮保持方角,仅按窗口圆角裁剪
上一版把 WIN11 关闭按钮红底做了内收 + 按钮圆角,不符合预期:
窗口是全圆角,但按钮本身应当是方角,唯一需要丢弃的是与窗口
右上圆角重合的那部分像素。

- WIN11 关闭按钮红底恢复整块矩形,仅用 _window_round_keep 丢弃窗口圆角外像素
- WIN7/WINXP 按钮底色同样改为方角(r=0),仍做窗口轮廓裁剪
- 按钮命中区域保持不变(仍是完整方角矩形)
2026-10-27 13:25:41 +08:00
TermiNexus 8dc806e7e2 fix(window): WIN11 关闭按钮 hover 红底按圆角裁剪
WIN11 窗口是圆角样式,关闭按钮又紧贴右上角;此前 hover/按下直接
row_fill 整块矩形,红色会盖住窗口圆角外的区域。

- 新增 _window_round_keep:按窗口自身的圆角轮廓判断像素是否可画
- 新增 _close_fill_row:同时按“按钮圆角 + 窗口圆角”双重裁剪
- WIN11 关闭按钮红底向内收 2px、圆角 3px;WIN7/WINXP 也走窗口轮廓裁剪
- 移除不再使用的 _round_fill_row
2026-10-27 13:21:34 +08:00
TermiNexus b9efc30d71 feat(window): 标题栏 hover、最大化图标、边缘缩放与控件光标
1) 标题栏按钮 hover:min/max 背景按 alpha 压暗,close 变红、图标变白;
   按下态更深。新增 hover_btn_win/kind,仅在变化时重画标题栏。
2) 最大化图标改为单线方框(上边框不再两行加厚);最大化后显示
   两个错位重叠方框作为“还原”。
3) 窗口边缘 5px 热区支持拖拽缩放:左/右 ↔、上/下 ↕、四角斜向;
   缩放中实时更新几何与内容缓冲(按 1.5 倍扩容,避免 arena 抖动),
   并向 app 发 RESIZE。
4) 新增 DESK_REQ_CURSOR / window.set_cursor_type 真正下发光标类型;
   explorer 按窗口 cursor + 边缘热区选择箭头 / I 形 / 手指 / 缩放光标。
5) vpui.Tk 在 HOVER 时按最上层控件设置光标:Entry/Text → I 形,
   Button → 手指;Entry 自己的光标请求移除,避免与集中逻辑冲突。
2026-10-27 13:14:42 +08:00
TermiNexus 6ecd891f64 fix(desk): 清空共享区槽表并按版本拒绝旧 app
现场:所有窗口消失、任务栏多出若干图标,点击后 explorer 以
[0E] rip=0x4061e8 cr2=0x1207e8fff 缺页退出。

原因:desk_format 只清 DeskHeader,没有清 0x100 起的 WinSlot 表。
DESK_SHM_SIZE 从 8MB 提到 32MB 后,mm.malloc 拿到的内存不再恰好全零
(混入 bootloader/固件遗留数据),随机 used/active 被当成窗口,
合成时按垃圾 fb_off 越界读像素。

- desk_format 先 memset 整个控制区(0x000000 ~ 0x200000)
- 分配槽位时整槽清零,避免复用残留
- DESK_VERSION 1 → 2,desk_ready 校验版本:
  旧 app 按旧 WinSlot 偏移读写会写坏共享区,现在直接拒绝挂载
- render_window_rows 校验 fb_off 范围,坏槽位只跳过,不再拖崩合成器
2026-10-27 12:52:23 +08:00
TermiNexus 8e94458fc2 fix(window): 最大化窗口不绘制阴影
最大化后窗口底边正好贴住任务栏,阴影(下沿 14px)会盖在任务栏上。
最大化状态跳过阴影绘制。
2026-10-27 12:44:54 +08:00
TermiNexus 03a5738702 perf(window): 最小化窗口的 FLUSH 不再置脏
应用最小化后仍会继续绘制并发送 FLUSH;此前每条 FLUSH 都标脏窗口区域,
合成器于是每帧重画背景。最小化时直接忽略置脏即可。
2026-10-27 12:43:53 +08:00
TermiNexus 632bc877df feat(window): 鼠标捕获与窗口最小化/最大化
鼠标:
- 内容区按下后记录 capture_win,按住期间的移动仍投 HOVER、松开投 RELEASE
  (即使光标移出窗口)。此前 btn_down != 0 时完全不发 HOVER,滚动条
  拖动拿不到位置更新。
- 标题栏按钮按下态改为通用 btn_win/btn_kind,支持关闭/最小化/最大化。

窗口:
- WinSlot 新增 maximized、restore_*、fb_cap 字段
- 最小化:隐藏窗口并把焦点交给最高可见窗口;任务栏点击恢复,
  再点一次已聚焦窗口则最小化
- 最大化:保存还原几何,铺满工作区(不含任务栏)并发送 RESIZE 事件;
  再次点击还原;拖动最大化窗口会先还原
- 像素缓冲按 fb_cap 复用,仅在容量不足时从 arena 扩容,避免反复
  最大化/还原耗尽 bump arena
- 1920x1080 最大化需要约 7.3MB 内容缓冲:DESK_SHM_SIZE 8MB → 32MB
2026-10-27 12:43:19 +08:00
TermiNexus 329a60b123 feat(terminal): 裸 cd 显示当前路径并归一化 cwd
- 只输入 cd 时不再重置到根目录,改为打印当前路径(pwd 语义)
- 新增 _normalize_path:折叠重复分隔符、去掉 .、处理 ..,
  根目录下 cd .. 仍为 /
- _cwd 保存归一化后的路径,pwd/ls 不再出现 /app/../.. 这类串,
  也避免路径越 cd 越长
2026-10-26 23:09:19 +08:00
TermiNexus fa1a92b568 chore(terminal): 链接不再 --strip-all,保留符号
便于崩溃现场按地址反查函数,与内核保留符号的做法一致。
2026-10-26 22:41:39 +08:00
TermiNexus bc089a0c69 feat(diag): 用户态窗口渲染链路临时打点
沿 Scene3D → FBCanvas → vpui.redraw → window.flush → explorer 合成器逐段打点,
用于定位窗口内容不上屏停在哪一环:

- Explorer:fb 哨兵像素回读、建窗槽位回读、首个 FLUSH、首帧 back/fb/任务栏像素、
  每 240 帧统计槽位/最上层窗口矩形/中心像素/共享缓冲首像素
- vpui:首次 redraw(缓冲地址尺寸)、st1~st4 分段(malloc/铺底/控件/拷回)、
  首次 flush、FBCanvas 首绘的源缓冲与像素
- Scene3D:主线程预渲染 3 帧(非清屏像素计数、三角形命中/调用数)、渲染线程
  入口与每 60 轮采样;渲染线程参数类型改为 rawptr

以上均为临时诊断,定位完成后应移除。
2026-10-26 22:41:32 +08:00
TermiNexus 8c31645c0f fix(gfx): floorf/ceilf 参数显式收窄为 float
min/max 是 double 内建,结果直接传给 floorf/ceilf 时编译器禁止隐式
double->float,实际会把 f64 的低 32 位当 f32 传参,使三角形包围盒取值全错。
内核 vesafb 与 Scene3D 两处光栅化同步修正。
2026-10-26 22:41:09 +08:00
TermiNexus 1ccacf8204 refactor(userspace): 清理 t/c 依赖与过时注释
Terminal、SerialLogger 不再 import t, c;dynlib 删除已失效的指针级数说明。
2026-10-26 22:40:07 +08:00
TermiNexus a3c1d221e6 fix(kbd,sched,scene3d): 键盘报告去重;用户线程 return 跳板修正;关窗时序
① Enter 洪流:usb_kbd._on_int_complete 的按下沿依赖 kbd_prev_keycodes,而状态提交在函数末尾第三趟循环;kbd_report 是常驻 DMA 缓冲,按键保持/NAK/重复完成都会让回调反复看到同一份报告 ⇒ 每次中断都注入一次 Enter,Terminal 刷出 [cmd] enter,explorer 被拖死。新增 kbd_prev_sig(modifier+6 keycode 的标量签名)整份报告去重;同一趟循环里先提交 prev 再判定;全 0 报告只更新状态;抽出 _rearm() 保证所有出口都重排中断 IN 且 DMA 读取先于重排。② explorer 限流:kb_pend[64] + _deliver_kb,单轮最多投递 64 字节,ring_push 返回 -1 时停在当前字节(不再当成功丢弃),pending 清空才补读;鼠标取包同样 64 包/轮上限。③ 关窗卡死根因:process.vp 的 _tramp_code 是 mov eax,34; int 0x80; jmp \$,而 Syscall.THREAD_EXIT=60 ⇒ 用户线程 return 后走 syscall 34(无匹配分支)返回 Ring3 在 jmp \$ 空转,空转不再产生 syscall,而内核只在 syscall 返回路径消费 needs_reschedule ⇒ 协作式调度彻底停摆,整机冻结。sched.create_user_thread 在跳板映射后把立即数低字节改为 60(幂等)。④ 次生:主线程先退会立即回收自己的用户栈,而 Scene3D 渲染线程还引用其栈上对象。Scene3D 渲染线程退出改为显式 process.thread_exit() 并置 _render_done;主线程 mainloop 返回后先 yield 等渲染线程退出(上限 10000 次)再 exit。⑤ window.flush 在槽位 used==0 时直接返回;vpui.Tk.redraw 入口判 win_id 与 is_active,窗口已回收时不碰 arena 不 flush。
2026-10-17 16:49:37 +08:00
TermiNexus 7e7204a09a fix(mm,explorer): slab 页严格归属与分配位图;关闭按钮按下态与松手关闭
① [mm] BAD blk 的解码:site=2=free_block、reason=1=magic 失配;blk 实际是 slab_page+16(页在 0x1b56020),sz 是该页 free_head,而非块大小。被踩的是页头前 8~16 字节,最可能是无锁 buddy 在 usb.init(sched.enable 之后)与用户进程 MMAP 并发 malloc 时重复授予同一 8KB 块。② mm 加固:_slab_find_page 不再只看 magic,新增 _slab_page_owns(block_ptr 回指、指针在对象区内、按 obj_size 对齐、序号 < total_objs);slab_page 新增 alloc_bits,只有已分配对象可 free,重复释放/野指针被拒,避免 free_count 提前到 total_objs 把仍在用的页拆回 buddy;free_obj 拒绝已全空继续收对象;_create_page 失败路径清零 magic。③ hid_ascii 仅只读且已有边界检查,非本次堆损坏来源;usb_kbd 把 code >= 64 改为显式早返回。④ 关闭按钮:按下只置 close_down 并置脏(按钮画按下态:CLASSIC 40,40,70→20,20,45;WIN7/XP 红底 200,50,50→140,25,25;WIN10/11 补深灰底),松手且仍命中才发 CLOSE + used=0,移出则撤销按下态恢复;几何复用 _close_btn_* 同一套函数。
2026-10-17 16:23:44 +08:00
TermiNexus bd1cd2f228 fix(explorer): 逐包跟踪按下/释放沿,修复单击需长按
批量取包后只保留最后一包的按键状态:快速点击的按下+释放落在同一批里,最终 btn=0,按下沿永远检测不到(表现为必须长按)。改为批次内维护 cur 并记录 saw_press(任一分包出现 0→1)。同时把释放与拖动从 elif 改为独立 if:同批内按下并松开时,按下分支之后必须立刻走释放,否则 btn_down 卡在 1,后续点击继续失效。
2026-10-17 15:52:32 +08:00
TermiNexus 4003b0d286 diag(explorer): 首次键盘字节打点,区分内核无数据与事件未送达
键盘仍无输入:在 poll_input 的键盘分支加一次性打印(kn 字节数 + 首字节)。判读:没有该行 ⇒ 内核 keyboard 设备这一侧没数据;有该行但 Terminal 仍不显示 ⇒ explorer 投递或 vpui 路由问题。
2026-10-17 13:26:50 +08:00
TermiNexus b405973e91 perf(gargantua): 渲染按 64 像素分块并每块让出 CPU
原实现一次连续算 4 行(640 像素,单像素最坏 100 步),长时间不让出,单核下输入/合成全卡。改为 64 像素一块,每块后 process.yield_cpu();每 4 行仍 root.redraw() 保持渐进刷新节奏;事件轮询从每 4 行一次提升到每 64 像素一次。单次占用降到约 1/10,逐像素结果不变(仅调度顺序变化)。
2026-10-17 13:20:22 +08:00
TermiNexus 850c4b8adc fix(keyboard,explorer): 键盘解码单队列化消除读循环自旋;关窗清理悬垂状态
① 卡死/键盘无效:has_data() 把'原始待解码'与'已解码可读'混成一个计数,而 read_scancode() 只看已解码队列;一旦出现 has_data()>0 但本次取不到字节(断码/修饰键/E0 前缀),devfs 的读循环里 count 不前进而 has_data() 恒真 ⇒ asm.sti() 后无 yield 自旋,协作式调度下整机停死。改为解码下沉到 IRQ、只保留一个输出队列(has_data()==out_count,read_scancode() 返回 0 ⟺ 队列空),ANSI 序列整条原子入队;devfs 读循环以 read_scancode() 返回 0 为唯一终止条件。② 关窗:DESTROY 与关闭键路径清 drag_win,focus/_activate_from_taskbar 校验槽位存活;poll_requests 单轮最多处理一圈(head 已推进,剩余留到下轮,不丢消息也不自旋)。③ vpui:孤立 ESC 后紧跟的普通键不再被吞。
2026-10-17 13:20:22 +08:00
TermiNexus e0308ba074 feat(input): 键盘接入 app —— 焦点回退 + 无聚焦控件时路由到文本控件
① explorer:新增 _key_target(),focused 无效(-1/已关/已最小化)时回退到 z 序最高的可见窗口,不再把键盘输入整体丢弃;载荷经核对无需改(explorer 传 evt.x,vpui.Text 读的正是 evt.x)。② vpui:Tk 新增 _first_text_widget(),mainloop 的 KEY 分支在 focused_widget 为空时回退到第一个可见的 Text/Entry,并同步置焦点;顺带修 Text.handle_event 只认 '\\r' 导致回车无效(内核给的是 '\\n')。Terminal 无需改动。
2026-10-17 12:00:19 +08:00
TermiNexus 51ce473092 feat(explorer): 任务栏窗口图标可点击激活/恢复
原来任务栏图标只画不响应:鼠标按下分支只做窗口 hit_test,点在任务栏上返回 -1 就什么都不做。新增 _taskbar_icon_x/_taskbar_icon_y/_taskbar_icon_hit/_activate_from_taskbar:几何与绘制共用同一套函数(避免热区与绘制分叉),筛选与 ordinal 顺序和 _draw_taskbar_rows 完全一致(used && active,含 minimized)。按下时先判 taskbar 图标命中 —— 命中则激活:minimized 先恢复并置脏,再走既有 focus()(更新 z 序、聚焦、整体置脏);未命中才继续原有窗口命中/拖动逻辑,本次点击不会被重复处理。
2026-10-17 11:55:22 +08:00
TermiNexus 0593f1798b fix(explorer): 窗口创建/销毁时整体置脏,避免内容残留
抽出 mark_all_windows()(所有可见窗口整体置脏,含阴影带),CREATE 与 DESTROY 分支各调用一次并保留 mark_titles()。原来这两处只标记标题栏 + 任务栏:新建窗口的内容区不脏(可能空白),关窗后下方露出的旧内容也不会重画,都要等鼠标经过才恢复。focus() 的内联循环同步收敛到该函数。
2026-10-17 11:53:14 +08:00
TermiNexus fbbb10099d fix(explorer): 焦点/层级切换时把可见窗口整体置脏
现象:窗口层级切换后内容不刷新,要等鼠标经过才覆盖。原因:focus() 只调 mark_titles()(标题栏 + 任务栏),没有标记内容区;被抬起的窗口内容区因此不会重画,原来压在上面的窗口仍留在屏幕。改为层级变化时对所有可见窗口调 mark_win(含阴影带),随后按新 z 序整体重画。
2026-10-17 11:52:17 +08:00
TermiNexus a19c5d1a53 perf(explorer): 修半透明/圆角混合底,并优化阴影与混合热点
① 混合底:上一版背景裁剪会跳过窗口覆盖的列,导致 back 在那些列保留上一帧内容;而 WIN7 标题栏 alpha 混合、WIN11/XP 圆角逐像素裁剪都需要读到正确背景。现在按样式在必要行补铺背景:WIN7 铺标题栏行 + 底部圆角段,WIN11/XP 铺上下圆角段,CLASSIC/WIN10 不铺(直角不透明)。补铺发生在所有窗口绘制之前,下层窗口随后正常覆盖。② 性能:阴影 alpha 改按行查表 + 无除法 SWAR 变暗;_blend/_blend_row 改 SWAR 并行混合(无除法、无格式分支);内容行不再先整行 fill 再 blit,直接 blit + 左右 1px 边框;圆角行逐像素只保留左右各 r 列,中段整段拷贝(宽 800 窗每圆角行从约 800 次降到 16 次);关闭键圆角先扫连续区间再整段 fill;render_range 缓存每个可见窗口的几何/样式,_top_z 只算一次并传入。
2026-10-17 11:36:34 +08:00
TermiNexus 844fbff31c fix(kernel,explorer): 内核不再画屏消除残留;CREATE 打印 style 诊断
蓝色残留根因:main.vp 里 VGA_drv.Print 在 __init__ 尾部执行,而它晚于 app spawn —— explorer 已经把桌面画上去了,内核随后又往 framebuffer 打一行测试文本/清屏,于是永远盖在桌面上(整屏刷一次也救不了,因为之后又被画)。S3e 之后屏幕由 explorer 独占合成,直接删除内核侧 VGA 驱动创建与 Print。另:handle_request 的 CREATE 分支加一条诊断打印(style/w/h),用于确认 style 是否真的透传到 explorer —— 5 条日志,定位后撤。
2026-10-17 11:03:05 +08:00
TermiNexus ae39fab5d8 perf(explorer): 背景只铺窗口外区间;进主循环前整屏刷一次
① 修卡:render_range 原来对每一行都先铺整行背景(全宽)再画窗口,对窗口覆盖的那几百列纯属浪费 —— Scene3D 每帧刷全窗时等于每帧多拷一整屏背景。改为逐行只铺没被任何可见窗口覆盖的 x 区间(窗口收集与 z 排序提到背景之前)。② 修 VGA 残留:内核启动期的 VGA/gfx 测试内容(蓝色测试块)不属于任何脏行,只靠增量渲染会永远留在屏幕上;serve() 进主循环前先 mark_all + 整屏渲染一次。
2026-10-16 23:07:09 +08:00
TermiNexus 78b0ca8db7 feat(explorer): 窗口样式差异可见化(标题栏/边框圆角/按钮按样式区分)
参考 desktop.vp 的 _draw_app_window 与三枚按钮函数,把 5 种样式的差异做到一眼可辨:标题栏 CLASSIC 蓝紫纯色 / WIN10 近黑 / WIN11 深灰 / WIN7 浅蓝 Aero 渐变(alpha 玻璃) / WINXP 蓝渐变;边框 CLASSIC-win10 直角、WIN7/11/XP 圆角 r=8;按钮 CLASSIC 16x16 深蓝底灰 X、WIN10/11 46x30 无底色灰字形、WIN7 28x20、WINXP 21x21 且红底白 X。新增 _is_in_corner/_is_on_border/_corner_alpha 与按行绘制的 _draw_flat_row/_draw_round_row/_blend_row/_title_row_color;关闭键热区改为与绘制共用同一套几何函数,避免点击错位。标题栏高度仍统一用 TITLE_H=32:app 侧内容区高度依赖 vpui 的 TITLE_H,改高度会让内容错位,故差异只由配色/圆角/按钮体现。
2026-10-16 23:04:21 +08:00
TermiNexus aab4643dfa feat(desk): style 透传到 CREATE 请求;任务栏随焦点/窗口集合刷新
① style 透传:DeskMsg 增加 style 字段(放在 d 与 title 之间),window._send 增加 style 可选参数(默认 0,其它调用点不受影响),create_window 把 style 一并压进 CREATE 请求,explorer 的 handle_request 用它建窗(原来硬编码 0)—— 这样 vpui 的 set_style 才能真正生效,样式区分与圆角才有意义。DeskMsg 是共享协议结构,app 与 explorer 必须一起重编。② 任务栏刷新:mark_titles 追加标记任务栏条带(焦点切换会调它,任务栏图标配色随之更新),CREATE 与 DESTROY 分支也各调一次(图标数量变化)。
2026-10-16 22:42:58 +08:00
TermiNexus c4ff870941 perf(explorer): 恢复逐脏段渲染与提交,避免退化成全屏重绘
上一版把脏行合并成一段连续范围渲染 + 一次提交,导致窗口(上)与任务栏(下)同时脏时每帧全屏渲染 + 全屏 4MB 提交,帧率崩。改回逐个脏段处理:每段先渲染进 back,随后逐行提交该段,段内一致性仍然成立,而写屏总量回到与脏区面积成正比。
2026-10-16 22:37:46 +08:00
TermiNexus 5f863bed71 perf(explorer): 合成改画后备缓冲,渲染末尾只提交脏行到 framebuffer
消除撕裂:原来所有绘制直接写真实 framebuffer,与显示器扫描并发 ⇒ 撕裂/闪烁;而用户态无法做垂直同步(QEMU/OVMF 的 GOP 线性帧缓冲没有 VGA 回扫信号,FB_WAIT_VBLANK 实测返回 0 空转)。改法对齐历史内核桌面的做法:DeskServer 增加进程本地后备缓冲 back(与 bg_row 同机制 mmap 匿名页),row_fill/row_blit/draw_char/阴影混合/任务栏 logo 等所有写入点从 self.fb 改到 self.back(back 行距 = fb_w,framebuffer 行距 = pitch_px),render() 先把脏行范围渲染到 back,末尾再把仍脏的行逐行 memcpy 提交到 framebuffer。分配失败时打印并退回直写。同时删掉已完成使命的 vblank iters 诊断打印。
2026-10-16 22:31:35 +08:00
TermiNexus 3945decc2d fix(explorer): 窗口覆盖到底部条带时把任务栏一并置脏
现象:任务栏要鼠标经过(光标行恰好落在它上面)才刷新一行。因为任务栏只在启动的 mark_all 画过一次,之后没有时钟每秒标脏,唯一能让任务栏行变脏的是窗口变化或光标自身所在行。窗口在 render_range 里是画在任务栏**之上**的,所以窗口覆盖到底部条带时必须连带标记任务栏条带,否则残留旧窗口内容、也无法恢复。
2026-10-16 22:17:25 +08:00
TermiNexus e1d31c3dc9 diag(explorer,fb0): vblank 返回等待迭代数并打点;脏行合并为一段渲染
排查'仍闪烁':① FB_WAIT_VBLANK 改为返回等待消耗的迭代数(到上限 = 超时 = 当前没有 VGA 回扫信号),explorer 首次调用打印一次 —— 用来判定垂直回扫同步是否真的生效;② render() 原来按连续脏行分段、每段各渲染一次,同一帧的多次写屏会跨越多个扫描周期,现在把脏行合并成一段连续范围一次性渲染,缩小撕裂窗口。
2026-10-16 21:55:36 +08:00
TermiNexus ecabd59518 feat(explorer): 还原窗口样式、阴影、任务栏与三枚窗口按钮,精简注释
对齐被删除的内核桌面 desktop.vp 的视觉:窗口改为四边框 + 标题栏(活动/非活动配色)+ 标题内容分隔线 + 内容按 1px 内缩合成,并按 WinSlot.style 选择样式配色;新增最小化/最大化/关闭三枚按钮;新增矩形窗口阴影(SHADOW_* + self._blend 按 framebuffer 格式做 alpha 混合);任务栏改为深色底 + 分 opper线 + 蓝色 logo 圆盘 + ViperOS 文本 + 每个活动窗口的带边框图标(焦点/普通/最小化三色)与标题首字符,高度 28→50 对齐旧桌面。置脏范围改用 mark_win(含阴影带)/ mark_titles(活动窗口切换时刷新所有标题栏)。同时精简全文注释(不保留历史沿革叙述)。任务栏时钟未实现:用户态无时间源;圆角未实现:style 尚未透传到 CREATE 请求;最小化/最大化仅外观未接线。
2026-10-16 21:47:44 +08:00
TermiNexus e41701e201 feat(fb0): 新增 FB_WAIT_VBLANK ioctl,合成前等垂直回扫
explorer 直接写 framebuffer 会与显示器扫描并发,造成撕裂/闪烁;而它在 Ring3 没有 IO 端口权限,不能像历史内核桌面那样自己 inb 0x3DA。所以在 /dev/fb0 上加 FB_WAIT_VBLANK(0x4601)由内核代等垂直回扫(带超时,无 VGA 时序时不死等),vpsdk 暴露 fb_wait_vblank(),desk_server.render() 写屏前调用一次。
2026-10-16 21:37:58 +08:00
TermiNexus 1c0720a746 perf(explorer,vpui): 矩形填充改 rep stosd,鼠标输入一次取完队列
性能三处:① vpui._fill_rect 原为逐像素双重循环(带边界判断),app 每帧都要把整窗填一遍背景色(Scene3D 是 640×360 = 23 万次写),改为逐行 string.memset32(rep stosd),先统一裁剪再整行填充;② explorer.row_fill 同样逐像素,任务栏(1360 像素/行)与标题栏每帧要填上万像素,同样改 rep stosd;③ 鼠标延迟:poll_input 原来每轮只从设备取一个包,而 serve 一轮要跑 poll_requests + poll_input + render(毫秒级),PS/2 是 100Hz ⇒ 输入在队列里排队累积、光标明显滞后。改为一次把已到的包全部取完(位移累加、按键以最后一个包为准),并把位移累加+钳制抽成 _move_cursor()。
2026-10-16 21:31:04 +08:00