feat(window): 滚轮事件下传与 Terminal 滚动

- desk 协议新增 DESK_MOUSE_WHEEL;window 新增 EVENT_TYPE_WHEEL
- Explorer 汇总一批鼠标包的 wheel 增量,投给光标下的窗口
  (窗口内坐标;任务栏区域不投递)
- InputEvent.button 承载滚轮有符号增量(uint8 编码,消费方按 int8 解码)
- vpui.Text 处理 WHEEL:每次滚动 3 行,按“输出行 + 输入行”总行数钳制,
  并同步滚动条;输入行仍保持在可视区内
This commit is contained in:
TermiNexus committed 2026-10-27 14:50:04 +08:00
1 parent 5405a34a24
commit 99c8cea8ee
4 files changed
+34

No files matched your search

+17
View File
@@ -1827,6 +1827,11 @@ class DeskServer:
viperlib.snprintf(&_mb, 128, "[explorer] mouse pkt n=%d btn=%d\n", mn, int(mp[0]))
devfs.serial_puts(&_mb)
moved: int = 0
wheel: int = 0
if mn >= 10:
wv: int = int(mp[9])
if wv >= 128: wv = wv - 256
wheel = wheel + wv
if mn >= 9:
moved = self._move_cursor(int(*(int32*(uint64(&mp) + uint64(1)))),
int(*(int32*(uint64(&mp) + uint64(5)))))
@@ -1848,7 +1853,19 @@ class DeskServer:
bi: int = int(mp[0]) & 1
if bi != 0 and cur == 0: saw_press = 1
cur = bi
if mn >= 10:
wv2: int = int(mp[9])
if wv2 >= 128: wv2 = wv2 - 256
wheel = wheel + wv2
mn = fs.read(self.mfd, &mp, uint32(16))
if wheel != 0:
# 滚轮:投给光标下那个窗口(窗口内坐标),由控件决定滚动行为。
hw: int = self.hit_test(self.cx, self.cy)
if hw >= 0:
hs: desk.WinSlot* = self.slot(hw)
self.push_event(hw, uint32(desk.DESK_EVT_MOUSE),
desk.DESK_MOUSE_WHEEL,
self.cx - hs.ux, self.cy - hs.uy - TITLE_H - TITLE_GAP, wheel)
if moved != 0:
self._mark_cursor_at(self.pcy)
self._mark_cursor_at(self.cy)
+1
View File
@@ -65,6 +65,7 @@ define DESK_EVT_RESIZE = 105 # a=w b=h
define DESK_MOUSE_PRESS = 1
define DESK_MOUSE_RELEASE = 2
define DESK_MOUSE_HOVER = 3
define DESK_MOUSE_WHEEL = 4 # d = 滚轮增量(有符号)
@__attribute__(packed)
+13
View File
@@ -1294,6 +1294,19 @@ virtual class Text(Widget):
tk2: Tk* = self.tk
tk2.focused_widget = None
return 1
elif etype == window.EVENT_TYPE_WHEEL:
if self.contains(ex, ey):
w: int = int(evt.button)
if w >= 128: w = w - 256
vis: int = self._visible_lines()
self.scroll_offset = self.scroll_offset - w * 3
max_off: int = self.line_count + 1 - vis
if max_off < 0: max_off = 0
if self.scroll_offset < 0: self.scroll_offset = 0
if self.scroll_offset > max_off: self.scroll_offset = max_off
self._update_scrollbar()
return 1
return 0
elif etype == window.EVENT_TYPE_KEY:
if self.focused:
ebtn2: uint8 = evt.button
+3
View File
@@ -20,6 +20,7 @@ define EVENT_TYPE_KEY = 5
define EVENT_TYPE_KEY_RELEASE = 6
define EVENT_TYPE_PING = 7
define EVENT_TYPE_RESIZE = 8
define EVENT_TYPE_WHEEL = 9
define KEY_STATE_PRESS = 1
define KEY_STATE_RELEASE = 2
@@ -229,6 +230,8 @@ def poll_event(evt: InputEvent*) -> int:
evt.type = uint32(EVENT_TYPE_CLICK)
elif kind == desk.DESK_MOUSE_RELEASE:
evt.type = uint32(EVENT_TYPE_RELEASE)
elif kind == desk.DESK_MOUSE_WHEEL:
evt.type = uint32(EVENT_TYPE_WHEEL)
else:
evt.type = uint32(EVENT_TYPE_HOVER)
evt.x = _evt.b # 窗口内坐标