Files
StellarX-kaifa/开发记录/Fix/Fix-BUG-20260409-0001-对话框重绘快照与遮挡交互异常.md
T

3.5 KiB
Raw Blame History

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 标题改为直接绘制,不再使用独立 Label
    • Dialog::handleEvent() 对自身区域内鼠标事件统一吞掉
    • 对话框关闭及遮挡场景补发合成 WM_MOUSEMOVE,清理底层 hover
    • Window 引入托管重绘,先重绘受影响 root,再补画相交对话框
  • 涉及文件 / 类 / 函数:
    • Window.h / Window.cpp
    • Dialog.h / Dialog.cpp
    • Control.h / Control.cpp
    • Canvas.cpp
    • TabControl.cpp
    • Button.cpp
    • TextBox.cpp
  • 影响的 API / 行为:
    • Dialog 在窗口变化时的语义固定为“只重新居中,不拉伸”
    • 非模态对话框覆盖区域内不再允许鼠标事件穿透到底层
  • 关键约束 / 不变量:
    • 对话框始终绘制在普通控件之上
    • 托管分发期间控件不直接提交绘制
    • resize 和对话框开关仍走整场景重绘兜底

影响评估

  • 影响范围:
    • 所有包含 Dialog、按钮 hover、遮挡重绘的场景
  • 兼容性影响:有(行为更严格,底层控件不再穿透响应)
  • 行为变化:有(对话框 resize 只居中;遮挡区域 hover 不再透传)
  • 性能影响:有正向变化(减少无意义整场景补画);同时在某些兜底场景仍保留整场景重绘
  • 回归风险:
    • 托管重绘 root 选择不当可能导致嵌套容器局部重绘异常
    • 需持续回归 Canvas / TabControl / Table / Dialog 组合场景

验证结果

  • 验证步骤:
  1. KEY == 2 / 4 中打开非模态对话框,快速在遮挡区域附近 hover 和点击。
  2. KEY == 3 / 4 中打开模态对话框并拖动窗口大小。
  3. 关闭对话框后观察底层按钮 hover 恢复。
  • 验证结果:
    • 穿透、残影、关闭后 hover 不恢复等主问题已压住。
  • 回归检查:
    • 保留对“快速划过多个按钮时偶发一帧双高亮”的已知限制记录。
  • 验证证据:
    • 静态推演 + 多轮编译验证 + 用户回归反馈

落地信息

  • Commit:
    • 4a6e153
    • 7f8431a
    • b07a4ec
    • 当前工作区未提交阶段
  • PR[可选]
  • 发布版本:[可选]
  • 备注:该修复跨多个阶段逐步收敛,不是一次性完成