3.5 KiB
3.5 KiB
Fix-BUG-20260409-0001
适用场景:记录某个 BUG 的修复方案、影响评估、验证结果与落地信息。
关联信息
- Fix ID: Fix-BUG-20260409-0001
- 关联 BUG ID: BUG-20260409-0001
- 修复目标: 收紧对话框快照、遮挡、事件分发和统一提交重绘链
- 状态:已完成 / 待持续回归
- 负责人:Codex 协作修改
- 分支 / 版本:
master
根因分析
- 根因:
- 旧实现中“作废快照”和“回贴旧背景”混在一起,resize 时容易把旧画面贴回屏幕。
- 非模态对话框与底层控件之间缺少明确的事件阻断和 hover 清理机制。
- 重绘长期依赖控件即时局部绘制,导致底层先画、对话框后补,容易闪烁或层级错乱。
- 标题曾作为独立
Label存在,导致额外一层背景快照,时序敏感。
- 触发条件:
- 非模态遮挡下的 hover / click
- 模态或非模态 resize
- 对话框打开 / 关闭
- 为什么之前没发现:
- 问题主要集中在“高频交互 + 对话框遮挡 + resize”组合路径
修复方案
- 修复思路:
- 拆分快照语义
- 收紧对话框事件消费
- 让
Dialog在窗口变化时只重新居中 - 将标题绘制并入
Dialog - 把重绘推进到窗口统一收口
- 关键改动:
discardBackground()与invalidateBackgroundSnapshot()分离Dialog标题改为直接绘制,不再使用独立LabelDialog::handleEvent()对自身区域内鼠标事件统一吞掉- 对话框关闭及遮挡场景补发合成
WM_MOUSEMOVE,清理底层 hover Window引入托管重绘,先重绘受影响 root,再补画相交对话框
- 涉及文件 / 类 / 函数:
Window.h / Window.cppDialog.h / Dialog.cppControl.h / Control.cppCanvas.cppTabControl.cppButton.cppTextBox.cpp
- 影响的 API / 行为:
Dialog在窗口变化时的语义固定为“只重新居中,不拉伸”- 非模态对话框覆盖区域内不再允许鼠标事件穿透到底层
- 关键约束 / 不变量:
- 对话框始终绘制在普通控件之上
- 托管分发期间控件不直接提交绘制
- resize 和对话框开关仍走整场景重绘兜底
影响评估
- 影响范围:
- 所有包含
Dialog、按钮 hover、遮挡重绘的场景
- 所有包含
- 兼容性影响:有(行为更严格,底层控件不再穿透响应)
- 行为变化:有(对话框 resize 只居中;遮挡区域 hover 不再透传)
- 性能影响:有正向变化(减少无意义整场景补画);同时在某些兜底场景仍保留整场景重绘
- 回归风险:
- 托管重绘 root 选择不当可能导致嵌套容器局部重绘异常
- 需持续回归
Canvas / TabControl / Table / Dialog组合场景
验证结果
- 验证步骤:
- 在
KEY == 2 / 4中打开非模态对话框,快速在遮挡区域附近 hover 和点击。 - 在
KEY == 3 / 4中打开模态对话框并拖动窗口大小。 - 关闭对话框后观察底层按钮 hover 恢复。
- 验证结果:
- 穿透、残影、关闭后 hover 不恢复等主问题已压住。
- 回归检查:
- 保留对“快速划过多个按钮时偶发一帧双高亮”的已知限制记录。
- 验证证据:
- 静态推演 + 多轮编译验证 + 用户回归反馈
落地信息
- Commit:
4a6e1537f8431ab07a4ec- 当前工作区未提交阶段
- PR:[可选]
- 发布版本:[可选]
- 备注:该修复跨多个阶段逐步收敛,不是一次性完成