docs: 收口阶段3键盘路由与焦点回归结论

This commit is contained in:
Codex
2026-10-10 00:06:41 +08:00
parent 29df994f09
commit dd88a80b8c
8 changed files with 649 additions and 34 deletions
@@ -0,0 +1,54 @@
# BUG-20261009-0001
> 适用场景:记录问题本身,不展开完整修复方案。修复内容写入对应的 Fix 文档。
## 基本信息
- ID: BUG-20261009-0001
- 标题: Table 内部分页按钮焦点视觉延迟刷新
- 状态:已修复,自动回归通过,KEY1 人工复验待执行
- 严重性:S2
- 优先级:P1
- 模块: Focus / Table / Managed Repaint
- 版本 / 分支: `master`,阶段 3 实现提交 `29df994`
- 环境: Windows + EasyX + Routed 键盘生产路径
- 发现人: 用户 KEY1 人工回归
- 关联 Fix ID: Fix-BUG-20261009-0001
## 问题描述
- 现象: Tab 把逻辑焦点移入 Table 的分页 Button 后,焦点框不会立即出现;焦点离开后,旧焦点框也不会立即消失。只有 hover、翻页或其它原因再次触发表格重绘时,屏幕才与逻辑焦点状态一致。
- 影响范围: Table 内部上一页/下一页 Button 的全部逻辑焦点视觉;逻辑焦点身份和 Tab 顺序本身正确。
- 期望结果: 分页 Button 获焦和失焦都必须在当前输入批次的托管重绘收口中刷新整张 Table,不依赖下一次无关事件。
## 复现信息
- 前置条件: Table 已首次绘制并 materialize 分页 Button,当前页存在可用分页方向。
- 复现步骤:
1. 启动 KEY1。
2. 使用 Tab 把焦点移动到 Table 分页 Button。
3. 不移动鼠标、不触发其它控件,观察分页区。
4. 再按 Tab 离开分页 Button,继续观察分页区。
- 复现概率:人工回归稳定观察到
- 人工证据: 用户于 2026-10-09 的 KEY1 回归描述。
## 根因分析
- Table 分页 Button 是真实 `Button`,但它属于 Table 内部绘制单元,不能作为独立顶层重绘 root 提交。
- `Button::applyFocusState()` 只把内部 Button 自身标脏并请求重绘;Table 没有因此进入 dirty,外层 Canvas 的脏子树判断看不到需要重画的 Table。
- 逻辑焦点状态已更新,但屏幕继续保留上一帧,直到后续事件把 Table 自身标脏。
## 跟踪信息
- 首次发现时间: 2026-10-09
- 最后更新时间: 2026-10-09
- 修复版本: `29df994`
- 验证版本: Debug x64 定向 focus UI 3/3、完整 UI 1/1、四配置 67/67 与 KEY1–KEY6 编译通过
- 关联记录: `Module-20261009-0007`
## 关闭边界
- 自动像素测试已证明分页 Button 焦点框在 Tab 进入时即时出现、离开时即时清除。
- BUG 最终人工关闭仍需用户复验 KEY1;自动通过不替代该人工门槛。
@@ -0,0 +1,55 @@
# BUG-20261009-0002
> 适用场景:记录问题本身,不展开完整修复方案。修复内容写入对应的 Fix 文档。
## 基本信息
- ID: BUG-20261009-0002
- 标题: 同父 Canvas 并发脏子树导致上层区域被下层重绘覆盖
- 状态:已修复,自动回归通过,KEY5 人工复验待执行
- 严重性:S2
- 优先级:P1
- 模块: Canvas / Managed Repaint / Overlay / Focus
- 版本 / 分支: `master`,阶段 3 实现提交 `29df994`
- 环境: Windows + EasyX + KEY5 D-1/D-2 同父 overlay
- 发现人: 用户 KEY5 人工回归
- 关联 Fix ID: Fix-BUG-20261009-0002
## 问题描述
- 现象: 焦点从 KEY5 的 D-1 下层按钮转移到 D-2 上层按钮时,下层失焦重绘会覆盖 D-2 的一部分;如果没有后续事件再次触发完整重绘,错误像素会持续存在。
- 影响范围: 同一 Canvas 内发生区域相交的上下层兄弟,并且下层持久内容与上层脏子树在同一批次提交。
- 期望结果: 只要下层本轮持久写屏区域与上层兄弟相交,上层兄弟必须基于当前屏幕重新抓背景并完整恢复,不能只提交自己的局部脏后代。
## 复现信息
- 前置条件: 两个相交 Canvas 按绘制顺序形成下层和上层;二者各有可聚焦 Button。
- 复现步骤:
1. 启动 KEY5。
2. 在 C 米区离开后使焦点进入 D-1 下层按钮。
3. 再把焦点移到 D-2 上层按钮。
4. 不触发额外重绘,观察 D-2 与 D-1 的相交区域。
- 复现概率:用户人工路径可复现
- 人工证据: 用户截图显示 D-1 重绘像素覆盖 D-2 上层区域。
## 根因分析
- `Canvas::requestRepaint()` 依绘制顺序提交脏子树并累计实际 coverage。
- 旧分支优先判断“当前上层兄弟自己是否有脏子树”。当 D-2 的 Button 同时获焦时,代码只提交 D-2 的局部脏子树。
- 此时 D-1 已经把持久像素写进 D-2 区域;仅画 D-2 的 Button 无法恢复 D-2 Canvas 背景和其它未脏内容,因此留下错误覆盖。
## 跟踪信息
- 首次发现时间: 2026-10-09
- 最后更新时间: 2026-10-09
- 修复版本: `29df994`
- 验证版本: 扩展 focus UI 3/3、完整 UI 1/1、四配置 67/67 与 KEY1–KEY6 编译通过
- 关联记录: `BUG-20260415-0005`、`BUG-20260511-0012`、`Module-20261009-0007`
## 关闭边界
- 自动像素测试已覆盖“下层失焦 + 上层获焦同批发生”并断言相交点仍为上层背景色。
- Tooltip 临时 coverage 仍不触发持久快照刷新;完整 tooltip UI 已通过。
- BUG 最终人工关闭仍需用户复验 KEY5 D 区。