vdi-cloud/docs/independent-cursor-design-20261103.md

65 lines
6.0 KiB
Markdown
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.

# 独立光标二次开发设计与接入条件
> 2026-11-05更新:Ubuntu/麒麟已部署单座席X11受限方案,通过认证SSH同步形状,在新连接前启动无光标捕获并在整次会话结束后恢复服务,见[实施记录](linux-native-cursor-20261105.md)。以下是11月3日Windows正式控制协议设计与当时现场状态;该Windows协议仍未实现,不能混同Linux新方案。
状态:已通过受控的 Windows 光标导出 + 盒子 X11 本地指针原型验证;尚未实现 Sunshine/Moonlight 的自动独立光标通道,不应标记为生产功能已部署。测试已结束,当前恢复单个 Windows 远程白色光标。实测结果见 [独立光标可行性验证](independent-cursor-feasibility-20261103.md)。
## 已核实的实际路径
- 盒子固定 Moonlight Qt 6.2.0,现有 absolute mouse 输入仍经 moonlight-common-c 的可靠输入通道发送。
- 当前 RKMPP/EGL 路径使用 PacerRender 独立线程;实际诊断会话没有主线程 render 调用,输入优先调度不会改变这个渲染路径。
- Sunshine `input.cpp` 的 Ctrl+Alt+Shift+N 直接翻转全局 `display_cursor`。`video.cpp` 将其地址传入 display capture。它没有按会话的目标状态、确认或租约,不能作为可靠的独立光标协议。
- Windows Desktop Duplication 可能返回独立光标形状,也可能返回已含光标的画面;不能假定所有显示设备都能从视频中无损移除光标。
- Windows 当前没有现成的 Sunshine C++ 构建环境。因此本轮可以构建盒子客户端、验证输入和刷新率,但不能把未构建的服务端补丁当成已完成联调。
参考:[Sunshine input.cpp](https://github.com/LizardByte/Sunshine/blob/master/src/input.cpp)、[video.cpp](https://github.com/LizardByte/Sunshine/blob/master/src/video.cpp)、[Windows RAM capture](https://github.com/LizardByte/Sunshine/blob/master/src/platform/windows/display_ram.cpp)、[Microsoft Desktop Duplication 光标说明](https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/desktop-dup-api)。master 仅用于核实设计,实际修改须先固定现场 Sunshine 版本对应提交。
## 实施方式
在 Sunshine 与 moonlight-common-c/Moonlight 间扩展现有加密控制通道;不另外开放未经认证的 UDP 光标端口。默认仍使用远程视频光标,仅在双方协商并确认支持后启用。新增消息必须有协议版本、会话标识、显示配置代数及严格的大小校验。
| 消息 | 必要内容与作用 |
| --- | --- |
| 能力协商 | 支持形状类型、最大尺寸、显隐/视频帧交接能力;旧客户端保持原行为 |
| 光标形状 | 形状版本、尺寸、热点、像素/掩码格式;形状变化时发送并缓存 |
| 光标状态 | 状态序号、形状版本、显隐、坐标、显示区域及缩放配置代数 |
| 交接请求/确认 | 明确目标模式,携带首个采用该模式的视频帧 ID;不能使用无确认的 toggle |
| 位置校正 | 服务端主动移动与最近输入序号关联;用户持续移动时不能用旧位置反复拉回 |
| 心跳/结束 | 会话租约、显式结束;连接丢失时服务端自动恢复视频光标 |
光标移动由盒子的本地指针立即显示,形状和显隐仍取自服务端。窗口、按钮响应和内容更新继续走视频,所以独立光标不等于窗口拖动零延迟。
## 单光标交接
1. 服务端确认当前捕获后端可独立控制光标,客户端收到并成功创建当前形状;否则保持远程模式。
2. 服务端在明确的视频帧边界停止混合光标,并发出该帧 ID。客户端显示到这个边界后才开启本地光标,避免旧视频仍有光标时出现双指针。
3. 结束独立模式时反向交接,在开始包含远程光标的视频帧上隐藏本地光标。
4. 辅助状态超时、形状不支持、捕获设备更换、显示缩放改变、解码器重建、第二路会话接入时,执行确认后的回退。控制连接完全断开且无法继续交接时结束串流,返回选择页。
5. 不能通过替换 Windows 全局鼠标主题为透明图片实现;不能把普通箭头覆盖在视频光标上。
心跳和租约先按 250ms/1000ms 做实验参数,最终值由 Wi-Fi 抖动及故障恢复测试决定。现有全局 display_cursor 还须改为与会话/捕获生命周期一致的状态,防止多个客户端互相覆盖。
## Windows 特殊情况
- 处理彩色 alpha、单色 AND/XOR 和 masked-color;不支持的形状明确回退。不能把 XOR 像素简单当透明像素。
- 热点随流画面缩放映射,窗口信箱区域不发送越界输入;切换分辨率后废弃旧代数的光标消息。
- 服务端隐藏指针、文字选择、拖动缩放、忙碌动画必须正确;锁屏/UAC 桌面切换不能继续显示过期光标。
- SDL 硬件指针操作留在主线程;网络线程仅提交有界状态,禁止直接调用 SDL_SetCursor/释放正在使用的 cursor。
- 本地移动与远程主动 warp 分开处理,避免拖动时抖动、回弹;点击仍使用已修复的按钮坐标/输入顺序。
## 必须通过的验收
| 场景 | 要求 |
| --- | --- |
| 移动/拖动/右键/快速双击 | 单光标、点击准确、无丢失的按键释放 |
| 箭头/文字/调整大小/忙碌/隐藏/自定义 | 形状、热点及显隐正确;不支持时可靠回退 |
| 100%/125%/150% 缩放、分辨率切换 | 无偏移;旧代数消息失效 |
| 辅助消息停止、控制断开、服务器重启 | 无持久双光标或无光标状态 |
| 窗口失焦、鼠标离开、重新捕获 | 不锁死本地系统指针;恢复后坐标正确 |
| 旧服务端/客户端、多会话 | 不误启用;保持原有远程模式 |
| 高速摄像对照 | 分别报告指针移动、点击响应、拖窗内容更新的 P50/P95 |
## 下一阶段开始条件
固定现场 Sunshine 版本及源码提交,在独立构建目录准备可复现 Windows 构建,备份原安装并在测试实例验证后,再修改双方协议和捕获交接。不得为部署光标实验重装当前 Windows、刷 GPU ROM 或中断其他虚拟机。