diff --git a/docs/research/conpty-resize-repaint-timing.md b/docs/research/conpty-resize-repaint-timing.md new file mode 100644 index 00000000..901e4e6f --- /dev/null +++ b/docs/research/conpty-resize-repaint-timing.md @@ -0,0 +1,55 @@ +# resize 期间 ConPTY 重绘与终端网格的时序(#194 设计记录) + +本页把 [#194](../..#194) 的观测与候选方案固定下来,便于决定方向后直接实现。它不改变任何行为。 + +## 观测事实 + +在 hosted windows-2025 上用 dispatch-only 复现作业采样,失败轮(`text_actions` 的 `actions geometry lost terminal selection`)留下三份互相对得上的证据: + +1. **选区丢弃诊断**:`row-text-changed row=78, saved_bytes=29, current_bytes=29, saved_columns=111, current_columns=111` —— 字节数与列数都不变,说明是整行内容被换成了相邻行,不是裁剪。 +2. **进度记录**:几何变化前 `grid=[111,7] top=75`,缩放到 75% 时 `grid=[149,10] top=75`,回到 100% 时 `grid=[111,7] top=78`,且 `selected` 由 true 变 false。 +3. **输出轨迹**:一轮几何序列里出现约 10 次"回 home 重打尾部 6 行(075–080)"的重绘批次,并带 `ESC[7;1H` 与若干 `ESC[K CR LF`。 + +把三者合起来:重绘批次按**旧几何**(10 行、首行 075)生成,被**新几何**(7 行、首行 078)消费,于是行 0–5 被写成 075–080,整体错位 **10 − 7 = 3 行**。 + +## 为什么这是产品问题而不是测试问题 + +- 终端把 ConPTY 的重绘当作普通 VT 输出应用,是标准行为;问题在于**重绘对应的几何与当前网格不一致**; +- 真实用户在 DPI/缩放变化时同样可能遇到:内容错行、选区/Find 失效; +- 该形状在 `local` 与 `system` 两种动作场景都出现过,不依赖剪贴板路径。 + +## 候选方向 + +### 方向 1:切换网格前先消费完已到达的输出(保守) + +- 在 `size_changed` 应用新网格前,先把输出队列中已到达的块按旧尺寸喂给解析器; +- 优点:不改协议、不改期限,纯粹调整本进程的消费顺序; +- 风险:如果重绘批次在 resize 请求**之后**才到达(当前证据倾向于如此),仅"先排空已到达"不够,需要把"等待重绘批次"也纳入窗口,复杂度上升; +- 需要先做一个小实验确认重绘的到达时机(输出轨迹 + 尺寸轨迹即可判定)。 + +### 方向 2:按尺寸世代标记输出(结构性) + +- 为 ConPTY 输出附带"消费时应使用的网格尺寸",重绘批次按其生成时的尺寸消费; +- 优点:语义清晰,可同时覆盖 DPI、缩放、窗口尺寸变化; +- 风险:需要改动 `Session`/读取路径的状态模型,属于架构级变更,必须单独立项评审。 + +### 方向 3:识别并吸收重绘批次(启发式) + +- 识别以 `ESC[?25l ESC[H` 开头、且内容与当前可见尾部匹配的重绘序列,在尺寸切换瞬间丢弃或重放; +- 优点:改动局部; +- 风险:启发式识别可能误伤正常程序输出(例如自己实现重绘的 TUI 应用),不建议作为首选。 + +## 建议顺序 + +先做方向 1 的**可行性实验**(不改产品): + +1. 扩展输出轨迹,标记"每个重绘批次的起始偏移与到达时刻"; +2. 与 `geometry-*` 阶段的时间戳对照,确认重绘是"resize 前生成、resize 后到达"还是相反; +3. 若确为后者,则方向 1 需要扩展为"延迟应用新网格直到该批次消费完",并评估对交互延迟的影响; +4. 以上结论再交用户确认后实施。 + +## 证据入口 + +- 复现作业:`.github/workflows/conpty-compat.yml` 的 `windows-2025-actions-repeat`(覆盖 `text_actions|selection_context|shell`); +- 诊断变量:`TERMFORGE_CAPTURE_OUTPUT`、`TERMFORGE_OUTPUT_TRACE`、`TERMFORGE_SELECTION_DIAG`; +- 相关讨论:[#194](../..#194)、[#156](../..#156)(已关闭,机制记录)、[#38](../..#38)(托管稳定性汇总)。