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
This commit is contained in:
1 parent
859197e5e9
commit
632bc877df
3 files changed
+241
-78
No files matched your search
+231
-75
@@ -155,10 +155,15 @@ class DeskServer:
|
||||
focused: int
|
||||
next_z: int
|
||||
btn_down: int
|
||||
close_down: int # 正在被按下的关闭键所属窗口(-1 = 无)
|
||||
# 标题栏按钮的捕获态:btn_win = 窗口下标(-1 = 无),btn_kind = 0/1关闭/2最小化/3最大化
|
||||
btn_win: int
|
||||
btn_kind: int
|
||||
drag_win: int
|
||||
drag_dx: int
|
||||
drag_dy: int
|
||||
# 按住鼠标时的捕获窗口:内容区按下后,移动/松开事件始终投给它(滚动条等
|
||||
# 控件靠按住期间的 HOVER 更新位置;移出窗口也不能丢)。
|
||||
capture_win: int
|
||||
# 复用缓冲
|
||||
msg: desk.DeskMsg
|
||||
evt: desk.DeskMsg
|
||||
@@ -202,10 +207,12 @@ class DeskServer:
|
||||
self.focused = -1
|
||||
self.next_z = 1
|
||||
self.btn_down = 0
|
||||
self.close_down = -1
|
||||
self.btn_win = -1
|
||||
self.btn_kind = 0
|
||||
self.drag_win = -1
|
||||
self.drag_dx = 0
|
||||
self.drag_dy = 0
|
||||
self.capture_win = -1
|
||||
# 预构造一行背景,渲染时整行 memcpy
|
||||
self.bg_row = uint32*(syscall.mmap(0, uint64(w) * uint64(4),
|
||||
uint64(syscall.PROT_READ | syscall.PROT_WRITE),
|
||||
@@ -305,6 +312,120 @@ class DeskServer:
|
||||
def slot(self, win: int) -> desk.WinSlot*:
|
||||
return desk.WinSlot*(self.shm + desk.desk_slot_off(win))
|
||||
|
||||
def _content_h(self, h: int) -> int:
|
||||
ch: int = h - TITLE_H - TITLE_GAP
|
||||
if ch < 1: ch = 1
|
||||
return ch
|
||||
|
||||
# 调整窗口外框几何。像素缓冲只在容量不足时扩容:arena 是 bump 分配,
|
||||
# 容量内复用可避免反复最大化/还原把 arena 耗尽。返回 1 成功 / 0 失败。
|
||||
def _set_window_rect(self, s: desk.WinSlot*, x: int, y: int, w: int, h: int) -> int:
|
||||
ch: int = self._content_h(h)
|
||||
need: int = w * ch
|
||||
if w <= 0 or need <= 0: return 0
|
||||
if need > int(s.fb_cap):
|
||||
off: uint32 = desk.desk_arena_alloc(self.shm, uint32(need * 4))
|
||||
if off == uint32(0): return 0
|
||||
s.fb_off = off
|
||||
s.fb_cap = uint32(need)
|
||||
b: uint32* = uint32*(self.shm + uint64(off))
|
||||
col: uint32 = self.rgb(uint32(30), uint32(30), uint32(50))
|
||||
for k in range(need):
|
||||
b[k] = col
|
||||
s.ux = x
|
||||
s.uy = y
|
||||
s.w = w
|
||||
s.h = h
|
||||
s.fb_w = uint32(w)
|
||||
s.fb_h = uint32(ch)
|
||||
return 1
|
||||
|
||||
def _focus_top_visible(self):
|
||||
best: int = -1
|
||||
bz: int = -1
|
||||
for i in range(desk.DESK_MAX_WIN):
|
||||
s: desk.WinSlot* = self.slot(i)
|
||||
if s.used != 0 and s.active != 0 and s.minimized == 0:
|
||||
if s.z_order > bz:
|
||||
bz = s.z_order
|
||||
best = i
|
||||
self.focused = best
|
||||
|
||||
def _close_window(self, win: int):
|
||||
s: desk.WinSlot* = self.slot(win)
|
||||
if s.used == 0: return
|
||||
# 关闭:通知一次 CLOSE 后把槽位置空回收;window.vp 的 is_active() 见到 used==0
|
||||
# 即返回 0,app 的 while 循环自然退出。像素缓冲不回收(arena 是 bump 分配)。
|
||||
self.push_event(win, uint32(desk.DESK_EVT_CLOSE), 0, 0, 0, 0)
|
||||
self.mark_win(s.uy, s.h)
|
||||
s.used = 0
|
||||
if self.focused == win: self.focused = -1
|
||||
if self.drag_win == win: self.drag_win = -1
|
||||
if self.capture_win == win: self.capture_win = -1
|
||||
if self.btn_win == win:
|
||||
self.btn_win = -1
|
||||
self.btn_kind = 0
|
||||
self._focus_top_visible()
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
|
||||
def _minimize_window(self, win: int):
|
||||
s: desk.WinSlot* = self.slot(win)
|
||||
if s.used == 0 or s.minimized != 0: return
|
||||
self.mark_win(s.uy, s.h)
|
||||
s.minimized = 1
|
||||
if self.focused == win: self.focused = -1
|
||||
if self.drag_win == win: self.drag_win = -1
|
||||
if self.capture_win == win: self.capture_win = -1
|
||||
self._focus_top_visible()
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
|
||||
def _maximize_window(self, win: int):
|
||||
s: desk.WinSlot* = self.slot(win)
|
||||
if s.used == 0 or s.maximized != 0: return
|
||||
ox: int = s.ux
|
||||
oy: int = s.uy
|
||||
ow: int = s.w
|
||||
oh: int = s.h
|
||||
mw: int = self.fb_w
|
||||
mh: int = self.fb_h - TASKBAR_H
|
||||
if mh < TITLE_H + TITLE_GAP + 1: return
|
||||
if self._set_window_rect(s, 0, 0, mw, mh) == 0: return
|
||||
s.restore_x = ox
|
||||
s.restore_y = oy
|
||||
s.restore_w = ow
|
||||
s.restore_h = oh
|
||||
s.maximized = 1
|
||||
self.mark_win(oy, oh)
|
||||
self.mark_win(s.uy, s.h)
|
||||
self.push_event(win, uint32(desk.DESK_EVT_RESIZE), int(s.fb_w), int(s.fb_h), 0, 0)
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
|
||||
def _restore_window(self, win: int) -> int:
|
||||
s: desk.WinSlot* = self.slot(win)
|
||||
if s.used == 0 or s.maximized == 0: return 0
|
||||
oy: int = s.uy
|
||||
oh: int = s.h
|
||||
if self._set_window_rect(s, s.restore_x, s.restore_y, s.restore_w, s.restore_h) == 0:
|
||||
return 0
|
||||
s.maximized = 0
|
||||
self.mark_win(oy, oh)
|
||||
self.mark_win(s.uy, s.h)
|
||||
self.push_event(win, uint32(desk.DESK_EVT_RESIZE), int(s.fb_w), int(s.fb_h), 0, 0)
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
return 1
|
||||
|
||||
def _toggle_maximize(self, win: int):
|
||||
s: desk.WinSlot* = self.slot(win)
|
||||
if s.used == 0: return
|
||||
if s.maximized != 0:
|
||||
self._restore_window(win)
|
||||
else:
|
||||
self._maximize_window(win)
|
||||
|
||||
# 最高 z 序(用于判定活动窗口;无可见窗口返回 -1)
|
||||
def _top_z(self) -> int:
|
||||
m: int = -1
|
||||
@@ -338,26 +459,33 @@ class DeskServer:
|
||||
for i in range(desk.DESK_MAX_WIN):
|
||||
s: desk.WinSlot* = self.slot(i)
|
||||
if s.used == 0:
|
||||
buf_off: uint32 = desk.desk_arena_alloc(self.shm, uint32(w) * uint32(h) * uint32(4))
|
||||
cap_px: int = w * content_h
|
||||
buf_off: uint32 = desk.desk_arena_alloc(self.shm, uint32(cap_px) * uint32(4))
|
||||
if buf_off == uint32(0): return -1
|
||||
s.used = 1
|
||||
s.pid = pid
|
||||
s.active = 1
|
||||
s.minimized = 0
|
||||
s.maximized = 0
|
||||
s.ux = x
|
||||
s.uy = y
|
||||
s.w = w
|
||||
s.h = h
|
||||
s.restore_x = x
|
||||
s.restore_y = y
|
||||
s.restore_w = w
|
||||
s.restore_h = h
|
||||
s.style = style
|
||||
s.cursor = 0
|
||||
s.fb_off = buf_off
|
||||
s.fb_cap = uint32(cap_px)
|
||||
s.fb_w = uint32(w)
|
||||
s.fb_h = uint32(content_h)
|
||||
string.memset(&s.title, 0, desk.DESK_TITLE_MAX)
|
||||
# 像素缓冲先清成窗口底色,避免 app 还没画就露出垃圾
|
||||
buf: uint32* = uint32*(self.shm + uint64(buf_off))
|
||||
col: uint32 = self.rgb(uint32(30), uint32(30), uint32(50))
|
||||
for k in range(w * h):
|
||||
for k in range(cap_px):
|
||||
buf[k] = col
|
||||
s.z_order = self.next_z
|
||||
self.next_z += 1
|
||||
@@ -720,7 +848,9 @@ class DeskServer:
|
||||
self.row_fill(cx + i, yy, 1, x_col)
|
||||
self.row_fill(cx - i, yy, 1, x_col)
|
||||
|
||||
def _draw_min_row(self, bx: int, by: int, bw: int, bh: int, yy: int, style: int):
|
||||
def _draw_min_row(self, bx: int, by: int, bw: int, bh: int, yy: int, style: int, pressed: int):
|
||||
if pressed != 0:
|
||||
self.row_fill(bx, yy, bw, self.rgb(uint32(70), uint32(70), uint32(70)))
|
||||
cx: int = bx + bw / 2
|
||||
cy: int = by + bh / 2
|
||||
lw: int = 5
|
||||
@@ -728,7 +858,9 @@ class DeskServer:
|
||||
if yy == cy + 3:
|
||||
self.row_fill(cx - lw, yy, lw * 2 + 1, self.rgb(uint32(180), uint32(180), uint32(180)))
|
||||
|
||||
def _draw_max_row(self, bx: int, by: int, bw: int, bh: int, yy: int, style: int):
|
||||
def _draw_max_row(self, bx: int, by: int, bw: int, bh: int, yy: int, style: int, pressed: int):
|
||||
if pressed != 0:
|
||||
self.row_fill(bx, yy, bw, self.rgb(uint32(70), uint32(70), uint32(70)))
|
||||
cx: int = bx + bw / 2
|
||||
cy: int = by + bh / 2
|
||||
sz: int = 4
|
||||
@@ -770,7 +902,24 @@ class DeskServer:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _draw_window_btns(self, s: desk.WinSlot*, y0: int, y1: int, th: int, close_pressed: int):
|
||||
# 标题栏按钮命中:1=关闭 2=最小化 3=最大化/还原(与绘制同一套几何)
|
||||
def _title_btn_hit(self, s: desk.WinSlot*, x: int, y: int) -> int:
|
||||
bw: int = self._close_btn_w(s.style)
|
||||
bh: int = self._close_btn_h(s.style)
|
||||
pad: int = self._close_btn_pad(s.style)
|
||||
gap: int = 0
|
||||
if s.style == STYLE_WIN7 or s.style == STYLE_WINXP: gap = 1
|
||||
by: int = s.uy + (TITLE_H - bh) / 2
|
||||
if y < by or y >= by + bh: return 0
|
||||
close_x: int = s.ux + s.w - bw - pad
|
||||
max_x: int = close_x - bw - gap
|
||||
min_x: int = max_x - bw - gap
|
||||
if x >= close_x and x < close_x + bw: return 1
|
||||
if x >= max_x and x < max_x + bw: return 3
|
||||
if x >= min_x and x < min_x + bw: return 2
|
||||
return 0
|
||||
|
||||
def _draw_window_btns(self, s: desk.WinSlot*, y0: int, y1: int, th: int, pressed_kind: int):
|
||||
wx: int = s.ux
|
||||
wy: int = s.uy
|
||||
ww: int = s.w
|
||||
@@ -788,9 +937,9 @@ class DeskServer:
|
||||
yend: int = y1
|
||||
if yend > by + bh: yend = by + bh
|
||||
while yy < yend:
|
||||
self._draw_close_row(close_x, by, bw, bh, yy, style, close_pressed)
|
||||
self._draw_min_row(min_x, by, bw, bh, yy, style)
|
||||
self._draw_max_row(max_x, by, bw, bh, yy, style)
|
||||
self._draw_close_row(close_x, by, bw, bh, yy, style, 1 if pressed_kind == 1 else 0)
|
||||
self._draw_min_row(min_x, by, bw, bh, yy, style, 1 if pressed_kind == 2 else 0)
|
||||
self._draw_max_row(max_x, by, bw, bh, yy, style, 1 if pressed_kind == 3 else 0)
|
||||
yy += 1
|
||||
|
||||
# ---------------- 任务栏 ----------------
|
||||
@@ -817,7 +966,7 @@ class DeskServer:
|
||||
cnt += 1
|
||||
return -1
|
||||
|
||||
# 点击图标:最小化先恢复,再走既有 focus(置顶并整体置脏)
|
||||
# 点击图标:最小化先恢复;已聚焦则最小化(任务栏切换);否则聚焦
|
||||
def _activate_from_taskbar(self, win: int):
|
||||
if win < 0 or win >= desk.DESK_MAX_WIN: return
|
||||
s: desk.WinSlot* = self.slot(win)
|
||||
@@ -825,7 +974,13 @@ class DeskServer:
|
||||
if s.minimized != 0:
|
||||
s.minimized = 0
|
||||
self.mark_win(s.uy, s.h)
|
||||
self.focus(win)
|
||||
self.focus(win)
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
elif self.focused == win:
|
||||
self._minimize_window(win)
|
||||
else:
|
||||
self.focus(win)
|
||||
|
||||
def _draw_taskbar_rows(self, y0: int, y1: int):
|
||||
bar_y: int = self.fb_h - TASKBAR_H
|
||||
@@ -1069,9 +1224,9 @@ class DeskServer:
|
||||
title_alpha, buf, fw, fh, content_y0)
|
||||
yy += 1
|
||||
|
||||
close_pressed: int = 0
|
||||
if self.close_down == win: close_pressed = 1
|
||||
self._draw_window_btns(s, y0, y1, th, close_pressed)
|
||||
pressed_kind: int = 0
|
||||
if self.btn_win == win: pressed_kind = self.btn_kind
|
||||
self._draw_window_btns(s, y0, y1, th, pressed_kind)
|
||||
if s.title[0] != 0:
|
||||
text_y: int = wy + (th - vpui.CHAR_H) / 2
|
||||
if text_y + vpui.CHAR_H > y0 and text_y < y1:
|
||||
@@ -1194,14 +1349,8 @@ class DeskServer:
|
||||
if s.used == 0: return
|
||||
ty: uint32 = m.type
|
||||
if ty == uint32(desk.DESK_REQ_DESTROY):
|
||||
self.mark(s.uy, s.h)
|
||||
s.used = 0
|
||||
if self.focused == win: self.focused = -1
|
||||
# 拖拽中的窗口被销毁:必须清掉 drag_win,否则后续移动会继续操作这个死槽位。
|
||||
if self.drag_win == win: self.drag_win = -1
|
||||
if self.close_down == win: self.close_down = -1
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
self._close_window(win)
|
||||
return
|
||||
elif ty == uint32(desk.DESK_REQ_MOVE):
|
||||
self.mark_win(s.uy, s.h)
|
||||
s.ux = m.a
|
||||
@@ -1209,17 +1358,9 @@ class DeskServer:
|
||||
self.mark_win(s.uy, s.h)
|
||||
elif ty == uint32(desk.DESK_REQ_RESIZE):
|
||||
self.mark_win(s.uy, s.h)
|
||||
new_ch: int = m.b - TITLE_H - TITLE_GAP
|
||||
if new_ch < 1: new_ch = 1
|
||||
# arena 是 bump 分配、不能回收:换尺寸一律重新切片,旧块留给后续复用
|
||||
new_off: uint32 = desk.desk_arena_alloc(self.shm, uint32(m.a) * uint32(m.b) * uint32(4))
|
||||
if new_off != uint32(0):
|
||||
s.fb_off = new_off
|
||||
s.w = m.a
|
||||
s.h = m.b
|
||||
s.fb_w = uint32(m.a)
|
||||
s.fb_h = uint32(new_ch)
|
||||
self.mark_win(s.uy, s.h)
|
||||
if self._set_window_rect(s, s.ux, s.uy, m.a, m.b) != 0:
|
||||
s.maximized = 0
|
||||
self.mark_win(s.uy, s.h)
|
||||
elif ty == uint32(desk.DESK_REQ_TITLE):
|
||||
string.memcpy(&s.title, &m.title, uint64(desk.DESK_TITLE_MAX))
|
||||
self.mark(s.uy, TITLE_H)
|
||||
@@ -1363,14 +1504,23 @@ class DeskServer:
|
||||
self.mark(self.cy - 1, CURSOR_BMP_H + 2)
|
||||
self.pcx = self.cx
|
||||
self.pcy = self.cy
|
||||
# 按住关闭键时移出按钮:撤销按下态并置脏恢复
|
||||
if self.close_down >= 0:
|
||||
cm: desk.WinSlot* = self.slot(self.close_down)
|
||||
if cm.used == 0 or self._close_btn_hit(cm, self.cx, self.cy) == 0:
|
||||
# 按住标题栏按钮时移出热区:撤销按下态并置脏恢复
|
||||
if self.btn_win >= 0:
|
||||
cm: desk.WinSlot* = self.slot(self.btn_win)
|
||||
if cm.used == 0 or self._title_btn_hit(cm, self.cx, self.cy) != self.btn_kind:
|
||||
if cm.used != 0: self.mark(cm.uy, TITLE_H)
|
||||
self.close_down = -1
|
||||
# 悬停:把 HOVER 投给光标下那个窗口(窗口内坐标)
|
||||
if self.btn_down == 0:
|
||||
self.btn_win = -1
|
||||
self.btn_kind = 0
|
||||
if self.btn_down != 0 and self.capture_win >= 0:
|
||||
# 内容区按住期间:移动事件持续投给捕获窗口。滚动条/滑块拖动
|
||||
# 依赖按住时的 HOVER;坐标允许越界,由控件自行判断。
|
||||
cs: desk.WinSlot* = self.slot(self.capture_win)
|
||||
if cs.used != 0:
|
||||
self.push_event(self.capture_win, uint32(desk.DESK_EVT_MOUSE),
|
||||
desk.DESK_MOUSE_HOVER,
|
||||
self.cx - cs.ux, self.cy - cs.uy - TITLE_H - TITLE_GAP, 0)
|
||||
elif self.btn_down == 0:
|
||||
# 悬停:把 HOVER 投给光标下那个窗口(窗口内坐标)
|
||||
hw: int = self.hit_test(self.cx, self.cy)
|
||||
if hw >= 0:
|
||||
hs: desk.WinSlot* = self.slot(hw)
|
||||
@@ -1379,7 +1529,9 @@ class DeskServer:
|
||||
self.cx - hs.ux, self.cy - hs.uy - TITLE_H - TITLE_GAP, 0)
|
||||
if saw_press != 0:
|
||||
self.btn_down = 1
|
||||
self.close_down = -1 # 新手势开始:清掉上一次可能丢失释放沿留下的按下态
|
||||
self.btn_win = -1 # 新手势开始:清掉上一次可能丢失释放沿留下的按下态
|
||||
self.btn_kind = 0
|
||||
self.capture_win = -1
|
||||
# 任务栏图标优先:命中则激活并跳过窗口命中/拖动
|
||||
hit: int = -1
|
||||
tw: int = self._taskbar_icon_hit(self.cx, self.cy)
|
||||
@@ -1389,20 +1541,26 @@ class DeskServer:
|
||||
hit = self.hit_test(self.cx, self.cy)
|
||||
if hit >= 0:
|
||||
s: desk.WinSlot* = self.slot(hit)
|
||||
# 关闭键热区复用 _close_btn_hit(与 _draw_window_btns 同一套几何)
|
||||
in_close: int = self._close_btn_hit(s, self.cx, self.cy)
|
||||
kind: int = self._title_btn_hit(s, self.cx, self.cy)
|
||||
self.focus(hit)
|
||||
if in_close != 0:
|
||||
# 只进入按下态:松手时才真正关窗,保证按下反馈至少能刷出一帧。
|
||||
self.close_down = hit
|
||||
if kind != 0:
|
||||
# 标题栏按钮:只进入按下态,松手且仍在同一按钮上才执行
|
||||
self.btn_win = hit
|
||||
self.btn_kind = kind
|
||||
self.mark(s.uy, TITLE_H)
|
||||
elif self.cy < s.uy + TITLE_H:
|
||||
# 标题栏(非关闭按钮)⇒ 开始拖动
|
||||
self.drag_win = hit
|
||||
self.drag_dx = self.cx - s.ux
|
||||
self.drag_dy = self.cy - s.uy
|
||||
# 标题栏 ⇒ 拖动;最大化窗口先还原再拖
|
||||
restored_ok: int = 1
|
||||
if s.maximized != 0:
|
||||
restored_ok = self._restore_window(hit)
|
||||
s = self.slot(hit)
|
||||
if restored_ok != 0:
|
||||
self.drag_win = hit
|
||||
self.drag_dx = self.cx - s.ux
|
||||
self.drag_dy = self.cy - s.uy
|
||||
else:
|
||||
# 内容区 ⇒ 按窗口内坐标把点击投给 app
|
||||
# 内容区 ⇒ 捕获鼠标:按下后的移动/松开都投给同一窗口
|
||||
self.capture_win = hit
|
||||
self.push_event(hit, uint32(desk.DESK_EVT_MOUSE),
|
||||
desk.DESK_MOUSE_PRESS,
|
||||
self.cx - s.ux, self.cy - s.uy - TITLE_H - TITLE_GAP, 1)
|
||||
@@ -1410,32 +1568,30 @@ class DeskServer:
|
||||
# 否则 btn_down 卡在 1,后续点击永远检测不到按下沿。
|
||||
if cur == 0 and self.btn_down != 0:
|
||||
self.btn_down = 0
|
||||
cw_win: int = self.close_down
|
||||
self.close_down = -1
|
||||
if cw_win >= 0:
|
||||
cs: desk.WinSlot* = self.slot(cw_win)
|
||||
bw: int = self.btn_win
|
||||
bk: int = self.btn_kind
|
||||
self.btn_win = -1
|
||||
self.btn_kind = 0
|
||||
if bw >= 0:
|
||||
bs: desk.WinSlot* = self.slot(bw)
|
||||
if bs.used != 0:
|
||||
self.mark(bs.uy, TITLE_H)
|
||||
if self._title_btn_hit(bs, self.cx, self.cy) == bk:
|
||||
if bk == 1:
|
||||
self._close_window(bw)
|
||||
elif bk == 2:
|
||||
self._minimize_window(bw)
|
||||
elif bk == 3:
|
||||
self._toggle_maximize(bw)
|
||||
elif self.drag_win < 0 and self.capture_win >= 0:
|
||||
# 松手:投给捕获窗口(即使光标已移出窗口)
|
||||
cs: desk.WinSlot* = self.slot(self.capture_win)
|
||||
if cs.used != 0:
|
||||
self.mark(cs.uy, TITLE_H)
|
||||
if self._close_btn_hit(cs, self.cx, self.cy) != 0:
|
||||
# 关闭:通知一次 CLOSE 后把槽位置空回收;window.vp 的 is_active()
|
||||
# 见到 used==0 即返回 0,app 的 while 循环自然退出。
|
||||
# 像素缓冲不回收(arena 是 bump 分配),只放槽位。
|
||||
self.push_event(cw_win, uint32(desk.DESK_EVT_CLOSE), 0, 0, 0, 0)
|
||||
self.mark_win(cs.uy, cs.h)
|
||||
cs.used = 0
|
||||
if self.focused == cw_win: self.focused = -1
|
||||
if self.drag_win == cw_win: self.drag_win = -1
|
||||
self.mark_all_windows()
|
||||
self.mark_titles()
|
||||
elif self.drag_win < 0:
|
||||
# 松手:投 RELEASE 给光标下的窗口
|
||||
rw: int = self.hit_test(self.cx, self.cy)
|
||||
if rw >= 0:
|
||||
rs: desk.WinSlot* = self.slot(rw)
|
||||
self.push_event(rw, uint32(desk.DESK_EVT_MOUSE),
|
||||
self.push_event(self.capture_win, uint32(desk.DESK_EVT_MOUSE),
|
||||
desk.DESK_MOUSE_RELEASE,
|
||||
self.cx - rs.ux, self.cy - rs.uy - TITLE_H - TITLE_GAP, 0)
|
||||
self.cx - cs.ux, self.cy - cs.uy - TITLE_H - TITLE_GAP, 0)
|
||||
self.drag_win = -1
|
||||
self.capture_win = -1
|
||||
if self.btn_down != 0 and self.drag_win >= 0:
|
||||
s2: desk.WinSlot* = self.slot(self.drag_win)
|
||||
if s2.used != 0:
|
||||
|
||||
@@ -575,7 +575,7 @@ def devfs_register_fb0(fb: rawptr, width: int, height: int, pitch: int, format:
|
||||
# 这里用 devfs 设备 + mmap 达到同样效果)。
|
||||
# ============================================================================
|
||||
# 共享区大小:vpsdk/desk.vp 里有一份同名同值的镜像(用户在 mmap 时必须先知道长度)。
|
||||
define DESK_SHM_SIZE = 8388608
|
||||
define DESK_SHM_SIZE = 33554432
|
||||
|
||||
virtual class shm_device(devfs_file):
|
||||
shm_phys: uint64
|
||||
|
||||
+9
-2
@@ -26,7 +26,8 @@ from stdint import *
|
||||
|
||||
# 必须与内核 VKernel/Kernel/drivers/devfs/devfs.vp 的 DESK_SHM_SIZE 一致
|
||||
# (mmap 时用户必须先给出长度,所以这里不能靠"问内核")。
|
||||
define DESK_SHM_SIZE = 8388608
|
||||
# 32MB:1920×1080 全屏窗口的内容缓冲约 7.3MB,最大化需要足够 arena。
|
||||
define DESK_SHM_SIZE = 33554432
|
||||
define DESK_MAGIC = 0x4B534544 # 'DESK'
|
||||
define DESK_VERSION = 1
|
||||
|
||||
@@ -86,17 +87,23 @@ class WinSlot:
|
||||
pid: int
|
||||
active: int
|
||||
minimized: int
|
||||
maximized: int
|
||||
z_order: int
|
||||
ux: int
|
||||
uy: int
|
||||
w: int
|
||||
h: int
|
||||
# 最大化前的还原几何
|
||||
restore_x: int
|
||||
restore_y: int
|
||||
restore_w: int
|
||||
restore_h: int
|
||||
style: int
|
||||
cursor: int
|
||||
fb_off: uint32
|
||||
fb_w: uint32
|
||||
fb_h: uint32
|
||||
_pad2: uint32
|
||||
fb_cap: uint32 # 像素缓冲容量(以像素计;扩容后复用,避免 arena 泄漏)
|
||||
title: [DESK_TITLE_MAX]char
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user