new_editor: stabilize resize lifecycle groundwork

This commit is contained in:
2026-04-23 00:36:28 +08:00
parent c10367a42e
commit 03e0b362f7
19 changed files with 439 additions and 161 deletions

View File

@@ -11,7 +11,9 @@
#include <XCEngine/UI/Layout/UITabStripLayout.h>
#include <algorithm>
#include <chrono>
#include <cmath>
#include <sstream>
#include <string_view>
#include <windowsx.h>
@@ -32,6 +34,11 @@ constexpr float kTitleBarLogoInsetLeft = 8.0f;
constexpr float kTitleBarLogoTextGap = 8.0f;
constexpr float kTitleBarFrameStatsInsetRight = 12.0f;
bool IsVerboseResizeTraceEnabled() {
static const bool s_enabled = ResolveVerboseRuntimeTraceEnabled();
return s_enabled;
}
float ResolveDetachedTabWidth(
std::string_view text,
const UIEditorTextMeasurer* textMeasurer) {
@@ -340,17 +347,42 @@ bool EditorWindowChromeController::HandleResizePointerMove(
return true;
}
const auto resizeStepBegin = std::chrono::steady_clock::now();
SetPredictedClientPixelSize(
static_cast<UINT>(width),
static_cast<UINT>(height));
const auto applyResizeBegin = std::chrono::steady_clock::now();
if (window.ApplyWindowResize(static_cast<UINT>(width), static_cast<UINT>(height))) {
(void)EditorWindowFrameDriver::DriveImmediateFrame(
window,
editorContext,
globalTabDragActive);
const auto immediateFrameBegin = std::chrono::steady_clock::now();
window.QueueCompletedImmediateFrame(
EditorWindowFrameDriver::DriveImmediateFrame(
window,
editorContext,
globalTabDragActive));
const auto immediateFrameEnd = std::chrono::steady_clock::now();
MarkPredictedClientPixelSizePresented();
if (IsVerboseResizeTraceEnabled()) {
const auto totalEnd = std::chrono::steady_clock::now();
const auto applyResizeMs =
std::chrono::duration_cast<std::chrono::milliseconds>(
immediateFrameBegin - applyResizeBegin).count();
const auto immediateFrameMs =
std::chrono::duration_cast<std::chrono::milliseconds>(
immediateFrameEnd - immediateFrameBegin).count();
const auto totalMs =
std::chrono::duration_cast<std::chrono::milliseconds>(
totalEnd - resizeStepBegin).count();
std::ostringstream trace = {};
trace << "borderless live resize step predicted="
<< width << 'x' << height
<< " applyResizeMs=" << applyResizeMs
<< " immediateFrameMs=" << immediateFrameMs
<< " totalBeforeSetWindowPosMs=" << totalMs;
LogRuntimeTrace("resize", trace.str());
}
}
const auto setWindowPosBegin = std::chrono::steady_clock::now();
SetWindowPos(
window.m_state->window.hwnd,
nullptr,
@@ -358,7 +390,23 @@ bool EditorWindowChromeController::HandleResizePointerMove(
targetRect.top,
width,
height,
SWP_NOZORDER | SWP_NOACTIVATE);
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOREDRAW);
ValidateRect(window.m_state->window.hwnd, nullptr);
if (IsVerboseResizeTraceEnabled()) {
const auto totalEnd = std::chrono::steady_clock::now();
const auto setWindowPosMs =
std::chrono::duration_cast<std::chrono::milliseconds>(
totalEnd - setWindowPosBegin).count();
const auto totalMs =
std::chrono::duration_cast<std::chrono::milliseconds>(
totalEnd - resizeStepBegin).count();
std::ostringstream trace = {};
trace << "borderless live resize present+apply complete predicted="
<< width << 'x' << height
<< " setWindowPosMs=" << setWindowPosMs
<< " totalStepMs=" << totalMs;
LogRuntimeTrace("resize", trace.str());
}
return true;
}
@@ -828,10 +876,11 @@ bool EditorWindowChromeController::ApplyPredictedWindowRectTransition(
SetPredictedClientPixelSize(static_cast<UINT>(width), static_cast<UINT>(height));
if (window.ApplyWindowResize(static_cast<UINT>(width), static_cast<UINT>(height))) {
(void)EditorWindowFrameDriver::DriveImmediateFrame(
window,
editorContext,
globalTabDragActive);
window.QueueCompletedImmediateFrame(
EditorWindowFrameDriver::DriveImmediateFrame(
window,
editorContext,
globalTabDragActive));
MarkPredictedClientPixelSizePresented();
}
SetWindowPos(