发布前托管重绘与布局封版收口
收口 Dialog/overlay 后鼠标状态同步、Tooltip 临时 coverage 与持久 coverage 拆分、跨 root 脏区补提交、TextBox/Button 绘制副作用修复,并补充 KEY6 回归用例和 BUG/Fix/Feature 开发记录。
This commit is contained in:
+57
-17
@@ -4,6 +4,12 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class SxTabOverlayRedrawMode
|
||||
{
|
||||
None,
|
||||
RefreshSnapshot
|
||||
};
|
||||
|
||||
bool SxTabRectsIntersect(const RECT& a, const RECT& b)
|
||||
{
|
||||
return a.left < b.right && a.right > b.left &&
|
||||
@@ -473,7 +479,7 @@ int TabControl::indexOf(const std::string& tabText) const
|
||||
return idx;
|
||||
}
|
||||
|
||||
return idx;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void TabControl::setDirty(bool dirty)
|
||||
@@ -498,9 +504,11 @@ void TabControl::requestRepaint(Control* parent)
|
||||
|
||||
if (this == parent)
|
||||
{
|
||||
RECT coverage{};
|
||||
bool hasCoverage = false;
|
||||
auto commitTabUnit = [&](Control* unit, bool forceOverlayRedraw)
|
||||
RECT paintCoverage{};
|
||||
bool hasPaintCoverage = false;
|
||||
RECT persistentCoverage{};
|
||||
bool hasPersistentCoverage = false;
|
||||
auto commitTabUnit = [&](Control* unit, SxTabOverlayRedrawMode overlayMode)
|
||||
{
|
||||
if (!unit || !unit->IsVisible())
|
||||
return;
|
||||
@@ -508,9 +516,9 @@ void TabControl::requestRepaint(Control* parent)
|
||||
const bool directDirty = unit->isDirty();
|
||||
const bool subtreeDirty = unit->hasManagedDirtySubtree();
|
||||
|
||||
if (forceOverlayRedraw)
|
||||
if (overlayMode == SxTabOverlayRedrawMode::RefreshSnapshot)
|
||||
{
|
||||
// 下层单元已经写过像素,上层页签/页面作为 overlay 补画时,
|
||||
// 下层单元的持久内容已经写过像素,上层页签/页面作为 overlay 补画时,
|
||||
// 必须先丢掉旧快照,重新抓取当前背景后再画,否则会把旧背景再贴回来。
|
||||
unit->invalidateBackgroundSnapshot();
|
||||
unit->setDirty(true);
|
||||
@@ -529,15 +537,26 @@ void TabControl::requestRepaint(Control* parent)
|
||||
return;
|
||||
}
|
||||
|
||||
const RECT rc = unit->getManagedRepaintCoverageRect();
|
||||
if (!hasCoverage)
|
||||
const RECT paintRect = unit->getManagedRepaintCoverageRect();
|
||||
if (!hasPaintCoverage)
|
||||
{
|
||||
coverage = rc;
|
||||
hasCoverage = true;
|
||||
paintCoverage = paintRect;
|
||||
hasPaintCoverage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
coverage = SxTabUnionRect(coverage, rc);
|
||||
paintCoverage = SxTabUnionRect(paintCoverage, paintRect);
|
||||
}
|
||||
|
||||
const RECT persistentRect = unit->getManagedRepaintPersistentCoverageRect();
|
||||
if (!hasPersistentCoverage)
|
||||
{
|
||||
persistentCoverage = persistentRect;
|
||||
hasPersistentCoverage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
persistentCoverage = SxTabUnionRect(persistentCoverage, persistentRect);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -553,11 +572,14 @@ void TabControl::requestRepaint(Control* parent)
|
||||
|
||||
if (page->hasManagedDirtySubtree())
|
||||
{
|
||||
commitTabUnit(page, false);
|
||||
commitTabUnit(page, SxTabOverlayRedrawMode::None);
|
||||
}
|
||||
else if (hasCoverage && SxTabRectsIntersect(page->getManagedRepaintCoverageRect(), coverage))
|
||||
else if (hasPaintCoverage && SxTabRectsIntersect(page->getManagedRepaintCoverageRect(), paintCoverage))
|
||||
{
|
||||
commitTabUnit(page, true);
|
||||
const bool persistentHit = hasPersistentCoverage &&
|
||||
SxTabRectsIntersect(page->getManagedRepaintPersistentCoverageRect(), persistentCoverage);
|
||||
if (persistentHit)
|
||||
commitTabUnit(page, SxTabOverlayRedrawMode::RefreshSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,11 +591,14 @@ void TabControl::requestRepaint(Control* parent)
|
||||
|
||||
if (button->hasManagedDirtySubtree())
|
||||
{
|
||||
commitTabUnit(button, false);
|
||||
commitTabUnit(button, SxTabOverlayRedrawMode::None);
|
||||
}
|
||||
else if (hasCoverage && SxTabRectsIntersect(button->getManagedRepaintCoverageRect(), coverage))
|
||||
else if (hasPaintCoverage && SxTabRectsIntersect(button->getManagedRepaintCoverageRect(), paintCoverage))
|
||||
{
|
||||
commitTabUnit(button, true);
|
||||
const bool persistentHit = hasPersistentCoverage &&
|
||||
SxTabRectsIntersect(button->getManagedRepaintPersistentCoverageRect(), persistentCoverage);
|
||||
if (persistentHit)
|
||||
commitTabUnit(button, SxTabOverlayRedrawMode::RefreshSnapshot);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -612,6 +637,21 @@ RECT TabControl::getManagedRepaintCoverageRect() const
|
||||
return coverage;
|
||||
}
|
||||
|
||||
RECT TabControl::getManagedRepaintPersistentCoverageRect() const
|
||||
{
|
||||
// 持久 coverage 排除页签按钮 Tooltip 等临时浮层,
|
||||
// 用于判断上层页签/页面补画时是否允许刷新背景快照。
|
||||
RECT coverage = getBoundsRect();
|
||||
for (const auto& control : controls)
|
||||
{
|
||||
if (control.first->IsVisible())
|
||||
coverage = SxTabUnionRect(coverage, control.first->getManagedRepaintPersistentCoverageRect());
|
||||
if (control.second->IsVisible())
|
||||
coverage = SxTabUnionRect(coverage, control.second->getManagedRepaintPersistentCoverageRect());
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
|
||||
bool TabControl::canCommitManagedPartialRepaint() const
|
||||
{
|
||||
// TabControl 只有在自己本体不脏且背景快照有效时,才允许只更新脏页签/脏页面。
|
||||
|
||||
Reference in New Issue
Block a user