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