Files
ViperOS/vpsdk/window.vp
T
TermiNexus c977caec91 fix(vkernel/vpsdk): 窗口缓冲改走“用户缓冲 + WIN_FLUSH 拷贝”,修 app 写内核页 #PF(err=0x7)
- 现场:四个 app 一画就用户态 #PF,cr2 全在内核堆区(~0xb7c1000/0x9f81000/0xb851000/0xb881000),err=0x7(present + 用户写),RAX 正是各自颜色常量(0x1E1E32/0xC0C0C/0xF0F19)

- 根因:GET_WINBUF 把 desktop 的**内核**窗口后备缓冲地址直接交给 app(该页 U=0),app 当用户指针写 → 必然 #PF,四个 app 全中(tid=5 那条 cr2=0xffffffff52209000 是同一指针继续走坏)

- 内核:WIN_FLUSH 增加源指针 `WIN_FLUSH(win_id, src)`:先 desktop.get_fb 取窗口缓冲、再 desktop.get_fb_bytes 取字节数(配对取,避免 resize 重建导致尺寸/指针不一致),memcpy 后 desktop.flush;syscall_handler 的 WIN_FLUSH 分支透传 arg2;desktop 新增 get_fb_bytes

- app(vpsdk/window.vp):get_winbuf 改为按窗口分配**用户态**缓冲(stdlib.malloc → MMAP,落在 0x20000000 用户堆)并缓存;flush(win_id) 改为 WIN_FLUSH(win_id, 用户缓冲)
2026-10-14 19:30:29 +08:00

108 lines
3.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from . import syscall as syscall
import vpsdk.stdlib as stdlib
from stdint import *
define STYLE_CLASSIC = 0
define STYLE_WIN10 = 1
define STYLE_WIN11 = 2
define STYLE_WIN7 = 3
define STYLE_WINXP = 4
define EVENT_TYPE_NONE = 0
define EVENT_TYPE_CLICK = 1
define EVENT_TYPE_HOVER = 2
define EVENT_TYPE_RELEASE = 3
define EVENT_TYPE_HOVER_LEAVE = 4
define EVENT_TYPE_KEY = 5
define EVENT_TYPE_KEY_RELEASE = 6
define EVENT_TYPE_PING = 7
define EVENT_TYPE_RESIZE = 8
define KEY_STATE_PRESS = 1
define KEY_STATE_RELEASE = 2
define KEY_STATE_REPEAT = 3
define CURSOR_DEFAULT = 0
define CURSOR_IBEAM = 1
define CURSOR_RESIZE_EW = 2
define CURSOR_RESIZE_NS = 3
define CURSOR_RESIZE_NWSE = 4
define VK_LEFT = -1
define VK_RIGHT = -2
define VK_UP = -3
define VK_DOWN = -4
define VK_HOME = -5
define VK_END = -6
define VK_DELETE = -7
define VK_PRIOR = -8
define VK_NEXT = -9
@c.Attribute(t.attr.packed)
@t.Object
class InputEvent:
type: uint32
win_id: int
x: int
y: int
button: uint8
_pad0: uint8
_pad1: uint8
_pad2: uint8
def create_window(x: int, y: int, w: int, h: int, title: const str, style: int) -> int:
return int(syscall._syscall6(uint64(syscall.CREATE_WINDOW), uint64(x), uint64(y), uint64(w), uint64(h), uint64(title), uint64(style)))
def draw_text(win_id: int, x: int, y: int, text: const str, color: uint32) -> int:
return int(syscall._syscall5(uint64(syscall.DRAW_TEXT), uint64(win_id), uint64(x), uint64(y), uint64(text), uint64(color)))
# 每窗口一份**用户态**后备缓冲(stdlib.malloc → MMAP → 0x20000000 用户堆)。
# 旧实现用 GET_WINBUF 把内核窗口缓冲地址直接交给 app,那片页 U=0 → app 一画就 #PF(err=0x7);
# 现在 app 画在自己的用户缓冲里,flush(win_id) 交给内核拷进窗口缓冲(WIN_FLUSH(win_id, src))。
define WINBUF_MAX_BYTES = 1024 * 1024 * 4
_winbufs: t.CArray[uint64, 64]
def get_winbuf(win_id: int) -> UINT32PTR:
if win_id < 0 or win_id >= 64: return None
if _winbufs[win_id] == 0:
p: t.CPtr = stdlib.malloc(WINBUF_MAX_BYTES)
if p is None: return None
_winbufs[win_id] = uint64(p)
return t.CPtr(_winbufs[win_id])
def get_win_size(win_id: int) -> int:
return int(syscall._syscall2(uint64(syscall.GET_WIN_SIZE), uint64(win_id), 0))
def flush(win_id: int):
buf: UINT32PTR = get_winbuf(win_id) # 确保缓冲已分配
syscall._syscall3(uint64(syscall.WIN_FLUSH), uint64(win_id), uint64(buf))
def mainloop(win_id: int):
syscall._syscall1(uint64(syscall.WAIT_WINDOW), uint64(win_id))
def poll_event(evt: InputEvent*) -> int:
return int(syscall._syscall1(uint64(syscall.POLL_EVENT), uint64(evt)))
def is_active(win_id: int) -> int:
return int(syscall._syscall2(uint64(syscall.WAIT_WINDOW), uint64(win_id), 1))
def set_cursor_type(win_id: int, cursor_t: int):
syscall._syscall2(uint64(syscall.SET_CURSOR), uint64(win_id), uint64(cursor_t))
def set_title(win_id: int, title: const str) -> int:
return int(syscall._syscall2(uint64(syscall.SET_TITLE), uint64(win_id), uint64(title)))
def set_geometry(win_id: int, x: int, y: int, w: int, h: int) -> int:
return int(syscall._syscall5(uint64(syscall.SET_GEOMETRY), uint64(win_id), uint64(x), uint64(y), uint64(w), uint64(h)))
def set_resizable(win_id: int, rw: int, rh: int) -> int:
return int(syscall._syscall3(uint64(syscall.SET_RESIZABLE), uint64(win_id), uint64(rw), uint64(rh)))
#class Window:
# HWND: int
# def __init__(self):
# self.HWND = create_window(100, 100, 100, 100)