|
|
f0a7ce23b1
|
feat(gui): 模式 A agent 独立光标 + 后台注入;修坐标换算;固化计划与交接文档
## 模式 A:agent 独立光标(不抢用户鼠标)
现有 computeruse 走 SetCursorPos + mouse_event,agent 一干活就抢走用户
真实鼠标,用户无法同时使用电脑。现改为:GUI 自绘 agent 专属光标,实际
输入经 PostMessage 直接投递到目标窗口句柄,用户鼠标全程不动。
新增:
cmd/gui/agent-cursor.js 透明置顶层窗口 + mascot 指针 + 移动/点击脉冲
动画;记录上次命中的 hwnd 供键盘动作使用
cmd/gui/agent-inject.js Windows 后台注入:WindowFromPoint 定位、
客户区坐标换算、PostMessage 投递鼠标/键盘/
滚轮/文本;拖拽分步移动
配置 gui-prefs.deviceBridge.agentCursor.mode = "overlay"(默认) | "real"。
明确的设计边界(不是实现缺陷,是平台限制):
· 只对「接受窗口消息的程序」可靠。原生 Win32 程序可靠;Chromium/
Electron 自绘界面、游戏、DirectX 会忽略合成消息。
· 不做真实鼠标降级。用户既选了不抢鼠标,就不该偷偷改成操作真鼠标,
失败即 status=error 并说明原因。
· 键盘类动作依赖先前的鼠标操作(后台注入不动真光标,
GetCursorPos 拿到的是用户自己的光标位置)。
端到端 8/8 正确响应;「真实点击是否落到目标窗口」因当前环境无可注入的
可见窗口而未验证,已在 GUI-PLAN.md 列为待办。
## 修坐标换算(我自己上一轮引入的 bug)
上一轮我加了 rawX / scaleFactor 的换算,理由是「SetCursorPos 期望 DIP」。
**那个前提是错的** —— Electron 主进程是 per-monitor DPI-aware,Win32 坐标
不做虚拟化。实测:
Electron screen API (DIP) : 1260 x 840 scaleFactor=2
GetSystemMetrics : 2520 x 1680
SetCursorPos(200,200) -> GetCursorPos 读回 (200,200) 恒等,不缩放
加 /scale 会把原本正确的点击改坏:200% 屏上点 (600,400) 被送到
(400,267),越靠右下偏得越远。已改回 physical ? rawX : rawX*scale,
drag 终点同步修正(原先两处换算不一致)。
易误判之处:在普通 node 进程里测同一函数读到的是 1260x840(虚拟化值),
会以为 Win32 用 DIP —— 必须在 Electron 内测。
## 判据
computeruse.test.mjs 43 条(npm test 共 127 条全绿),新增 5 条钉住
模式 A 的核心承诺:
· agent-inject / agent-cursor 均无 SetCursorPos 调用(查前先剥注释,
因为注释里会引用该名字解释「为什么不用它」)
· koffi 指针参数用 Buffer(普通对象不写回,会拿错 hwnd)
· overlay 默认开启且可切回 real
· 自绘光标层 setIgnoreMouseEvents 穿透
核心不变量已做变异验证:注入 SetCursorPos 后判据立即转红。
另修正坐标判据方向(原判据断言 /scale 是对的,与实测相反)。
## 文档
GUI-PLAN.md 改造计划与进度的单一事实来源:已完成/待办、坐标
实测结论与踩坑、koffi 3.x 使用约定、端到端测试方法、
环境注意事项(含本机无 Go 工具链、waiter 改动未编译验证)
SERVER-HANDOFF.md 服务端需同步的部分:放开 action 白名单(schema enum
+ switch default 双重限制,不改则 11 个新动作下发不到)、
透传 tox/toy/steps/dx/ms、统一 scroll 方向语义、
写入坐标约定防重蹈
|
2026-10-02 14:12:32 +08:00 |
|
|
|
d6dd84e1c8
|
fix(gui): 启动期误判服务端未启动;keybd_event 类型名致组合键全废
## 修 GUI 反复误判「服务端未启动」
isServerRunning() 硬编码 http://localhost:8080/。实测该部署下服务端在
192.168.2.60:8080(homed 跑在 WSL 里):
localhost:8080 -> 000 连不上
192.168.2.60:8080 -> 302 正常
于是每次启动都:探测失败 → 误判服务没起 → 去 startHomed() 拉起 GUI 旁
并不存在的 homed.exe(findHomed 返回 null 就 skip)→ 再 waitForServer()
干等 8s 超时 → 打印 "homed failed to start within timeout"。
gui.log 里这条 ERR 累计出现 53 次,是日志里唯一的错误项。
改法:
· serverProbeTargets() 按「connections.json 里已配置的连接(当前连接
优先)→ localhost」顺序探测,命中任一即视为在线
· 服务可达时直接 skip homed 自动拉起
· 无本地 homed 可执行文件时不再空等超时,直接说明情况
· probeOne 加超时保护,避免启动被挂住
实测:修复后启动日志为 "server reachable, skip homed autostart",
该 ERR 不再出现。
## 修 keybd_event 类型名(组合键整体失效)
koffi 不认 Win32 的 `byte`:
"void keybd_event(byte bVk, ...)"
-> Error: Unknown or invalid type name 'byte'
"void keybd_event(uint8 bVk, ...)" -> 正常
原代码用的正是 `byte`,且整段包在空 catch 里,于是 keybd_event 恒为 null,
所有组合键(keypress/hotkey)都返回 "keybd_event unavailable"。
这个 bug 很难被发现:单键 click/move/scroll 走 mouse_event,不受影响。
端到端实测确认:修复前 hotkey ctrl+shift+t 报
computeruse hotkey: keybd_event unavailable
另外签名解析失败现在会打日志,不再静默。
## 判据
computeruse.test.mjs 扩到 38 条(进 npm test,全量 121 条全绿),新增:
· keybd_event 签名类型(且已做变异验证:改回 byte 判据立即转红)
· 服务探测不只探 localhost / localhost 仅兜底 / 仅当有 homed 才拉起
· 服务可达时 skip autostart / 探测有超时保护
|
2026-10-02 13:03:17 +08:00 |
|