perf(server): D2D 候选窗每次显示只绘制一遍

PlaceAndShow 同步 Present 之后,前面各个 setter 的 InvalidateRect 留下的
WM_PAINT 又把整张卡片(含阴影模糊)画一遍;宿主改尺寸时 WM_SIZE 也会在
显式 Present 之前同步画一遍。同步 Present 后 ValidateRect 丢弃过时的
WM_PAINT;PlaceAndShow 自己触发的 WM_SIZE 只调整交换链尺寸,由随后的
Present 出帧。
This commit is contained in:
fanlusky committed 2026-09-27 15:03:17 +08:00
1 parent 7bbb9042fc
commit dff42f92df
2 files changed
+14 -1

No files matched your search

+12 -1
View File
@@ -1011,9 +1011,17 @@ void CandidatePresenter::PlaceAndShow(POINT caret, float widthDip, float heightD
SUCCEEDED(DwmGetWindowAttribute(hwnd_, DWMWA_CLOAKED, &cloaked, sizeof(cloaked))) && cloaked == 0;
const int firstX = onScreen && x > current.left ? current.left : x;
const int firstY = onScreen && y > current.top ? current.top : y;
// WM_SIZE from this resize would present the frame once more right before
// the explicit Present below; let it only resize the swap chain.
placingHost_ = true;
SetWindowPos(hwnd_, HWND_TOPMOST, firstX, firstY, hostWidthPx, hostHeightPx, SWP_NOACTIVATE | SWP_SHOWWINDOW);
placingHost_ = false;
impl_->resources.EnsureForComposition(hwnd_);
Present();
// Every setter above invalidated the window, which queued a WM_PAINT that
// would render the whole card (shadow blur included) a second time. The
// frame just presented is already current.
ValidateRect(hwnd_, nullptr);
if (firstX != x || firstY != y)
{
SetWindowPos(hwnd_, nullptr, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
@@ -1303,7 +1311,10 @@ bool CandidatePresenter::HandleMessage(UINT message, WPARAM wParam, LPARAM lPara
if (::is_global_wnd_cand_shown)
{
impl_->resources.Resize(static_cast<UINT>(LOWORD(lParam)), static_cast<UINT>(HIWORD(lParam)));
Present();
if (!placingHost_)
{
Present();
}
}
return true;
case WM_MOUSEMOVE:
+2
View File
@@ -54,6 +54,8 @@ class CandidatePresenter
bool bound_ = false;
bool hoverArmed_ = false;
bool ignoreSelectionCallback_ = false;
// Set while PlaceAndShow resizes the host; it presents right afterwards.
bool placingHost_ = false;
POINT hoverBaseline_{};
float decorationTopDip_ = 0.0f;
float decorationWidthDip_ = 0.0f;