refactor(new_editor): centralize win32 frame execution

This commit is contained in:
2026-04-22 14:37:25 +08:00
parent 4a42b757c7
commit b44f5ca9fc
10 changed files with 114 additions and 44 deletions

View File

@@ -269,6 +269,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP)
set(XCUI_EDITOR_APP_PLATFORM_SOURCES
app/Platform/Win32/EditorWindow.cpp
app/Platform/Win32/EditorWindowChromeController.cpp
app/Platform/Win32/EditorWindowFrameDriver.cpp
app/Platform/Win32/EditorWindowFrameOrchestrator.cpp
app/Platform/Win32/EditorWindowInputController.cpp
app/Platform/Win32/EditorWindowRuntimeController.cpp

View File

@@ -222,12 +222,16 @@ bool EditorWindow::Initialize(
<< " scale=" << GetDpiScale();
LogRuntimeTrace("window", dpiTrace.str());
return m_runtime->Initialize(
const bool initialized = m_runtime->Initialize(
m_state->window.hwnd,
repoRoot,
editorContext,
captureRoot,
autoCaptureOnStartup);
if (initialized) {
RequestFrame(EditorWindowFrameRequestReason::Initial);
}
return initialized;
}
void EditorWindow::Shutdown() {
@@ -385,6 +389,7 @@ void EditorWindow::OnResize(UINT width, UINT height) {
if (!matchesPredictedClientSize) {
ApplyWindowResize(width, height);
}
RequestFrame(EditorWindowFrameRequestReason::Resize);
}
void EditorWindow::OnEnterSizeMove() {
@@ -399,6 +404,7 @@ void EditorWindow::OnExitSizeMove() {
if (QueryCurrentClientPixelSize(width, height)) {
ApplyWindowResize(width, height);
}
RequestFrame(EditorWindowFrameRequestReason::ExitSizeMove);
}
void EditorWindow::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
@@ -427,6 +433,7 @@ void EditorWindow::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
trace << "dpi changed to " << m_chromeController->GetWindowDpi()
<< " scale=" << GetDpiScale();
LogRuntimeTrace("window", trace.str());
RequestFrame(EditorWindowFrameRequestReason::DpiChanged);
}
bool EditorWindow::IsVerboseRuntimeTraceEnabled() {
@@ -651,19 +658,15 @@ EditorWindowFrameTransferRequests EditorWindow::RenderFrame(
return transferRequests;
}
EditorWindowFrameTransferRequests EditorWindow::OnPaintMessage(
EditorContext& editorContext,
bool globalTabDragActive) {
void EditorWindow::OnPaintMessage() {
if (!m_runtime->IsReady() || m_state->window.hwnd == nullptr) {
return {};
return;
}
PAINTSTRUCT paintStruct = {};
BeginPaint(m_state->window.hwnd, &paintStruct);
const EditorWindowFrameTransferRequests transferRequests =
RenderFrame(editorContext, globalTabDragActive);
EndPaint(m_state->window.hwnd, &paintStruct);
return transferRequests;
RequestFrame(EditorWindowFrameRequestReason::PaintMessage);
}
UIRect EditorWindow::ResolveWorkspaceBounds(float clientWidthDips, float clientHeightDips) const {
@@ -926,6 +929,17 @@ void EditorWindow::ResetInputModifiers() {
void EditorWindow::RequestManualScreenshot() {
m_runtime->RequestManualScreenshot("manual_f12");
RequestFrame(EditorWindowFrameRequestReason::ManualScreenshot);
}
void EditorWindow::RequestFrame(EditorWindowFrameRequestReason reason) {
m_pendingFrameRequestReasons |= ToFrameRequestMask(reason);
}
std::uint32_t EditorWindow::ConsumePendingFrameRequestReasons() {
const std::uint32_t pendingFrameRequestReasons = m_pendingFrameRequestReasons;
m_pendingFrameRequestReasons = 0u;
return pendingFrameRequestReasons;
}
bool EditorWindow::IsPointerInsideClientArea() const {

View File

@@ -5,6 +5,7 @@
#endif
#include "Platform/Win32/EditorWindowPointerCapture.h"
#include "Platform/Win32/EditorWindowFrameRequest.h"
#include "Platform/Win32/EditorWindowTransferRequests.h"
#include <windows.h>
@@ -61,6 +62,7 @@ namespace XCEngine::UI::Editor::App {
class EditorContext;
class EditorShellRuntime;
class EditorWindowChromeController;
class EditorWindowFrameDriver;
class EditorWindowFrameOrchestrator;
class EditorWindowHostRuntime;
class EditorWindowInputController;
@@ -95,6 +97,7 @@ public:
private:
friend class EditorWindowChromeController;
friend class EditorWindowFrameDriver;
friend class EditorWindowHostRuntime;
friend class EditorWindowMessageDispatcher;
friend class EditorWindowWorkspaceCoordinator;
@@ -135,13 +138,13 @@ private:
bool autoCaptureOnStartup);
void Shutdown();
void ResetInteractionState();
void RequestFrame(EditorWindowFrameRequestReason reason);
std::uint32_t ConsumePendingFrameRequestReasons();
EditorWindowFrameTransferRequests RenderFrame(
EditorContext& editorContext,
bool globalTabDragActive);
EditorWindowFrameTransferRequests OnPaintMessage(
EditorContext& editorContext,
bool globalTabDragActive);
void OnPaintMessage();
void OnResize(UINT width, UINT height);
void OnEnterSizeMove();
void OnExitSizeMove();
@@ -253,6 +256,7 @@ private:
std::unique_ptr<EditorWindowFrameOrchestrator> m_frameOrchestrator = {};
std::unique_ptr<EditorWindowInputController> m_inputController = {};
std::unique_ptr<EditorWindowRuntimeController> m_runtime = {};
std::uint32_t m_pendingFrameRequestReasons = 0u;
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -400,6 +400,8 @@ bool EditorWindowChromeController::HandleResizePointerMove(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive) {
(void)editorContext;
(void)globalTabDragActive;
if (!IsBorderlessResizeActive() ||
window.m_state->window.hwnd == nullptr) {
return false;
@@ -428,7 +430,7 @@ bool EditorWindowChromeController::HandleResizePointerMove(
static_cast<UINT>(width),
static_cast<UINT>(height));
window.ApplyWindowResize(static_cast<UINT>(width), static_cast<UINT>(height));
(void)window.RenderFrame(editorContext, globalTabDragActive);
window.RequestFrame(EditorWindowFrameRequestReason::BorderlessTransition);
SetWindowPos(
window.m_state->window.hwnd,
@@ -897,6 +899,8 @@ bool EditorWindowChromeController::ApplyPredictedWindowRectTransition(
EditorContext& editorContext,
bool globalTabDragActive,
const RECT& targetRect) {
(void)editorContext;
(void)globalTabDragActive;
if (window.m_state->window.hwnd == nullptr) {
return false;
}
@@ -909,7 +913,6 @@ bool EditorWindowChromeController::ApplyPredictedWindowRectTransition(
SetPredictedClientPixelSize(static_cast<UINT>(width), static_cast<UINT>(height));
window.ApplyWindowResize(static_cast<UINT>(width), static_cast<UINT>(height));
(void)window.RenderFrame(editorContext, globalTabDragActive);
SetWindowPos(
window.m_state->window.hwnd,
nullptr,
@@ -918,6 +921,7 @@ bool EditorWindowChromeController::ApplyPredictedWindowRectTransition(
width,
height,
SWP_NOZORDER | SWP_NOACTIVATE);
window.RequestFrame(EditorWindowFrameRequestReason::BorderlessTransition);
window.InvalidateHostWindow();
return true;
}

View File

@@ -0,0 +1,29 @@
#include "Platform/Win32/EditorWindowFrameDriver.h"
#include "Platform/Win32/EditorWindow.h"
namespace XCEngine::UI::Editor::App {
EditorWindowFrameTransferRequests EditorWindowFrameDriver::DriveFrame(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive) {
if (!window.IsRenderReady() ||
window.GetHwnd() == nullptr ||
window.IsClosing()) {
return {};
}
(void)window.ConsumePendingFrameRequestReasons();
EditorWindowFrameTransferRequests transferRequests =
window.RenderFrame(editorContext, globalTabDragActive);
if (const HWND hwnd = window.GetHwnd();
hwnd != nullptr && IsWindow(hwnd)) {
ValidateRect(hwnd, nullptr);
}
return transferRequests;
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,18 @@
#pragma once
#include "Platform/Win32/EditorWindowTransferRequests.h"
namespace XCEngine::UI::Editor::App {
class EditorContext;
class EditorWindow;
class EditorWindowFrameDriver final {
public:
static EditorWindowFrameTransferRequests DriveFrame(
EditorWindow& window,
EditorContext& editorContext,
bool globalTabDragActive);
};
} // namespace XCEngine::UI::Editor::App

View File

@@ -0,0 +1,22 @@
#pragma once
#include <cstdint>
namespace XCEngine::UI::Editor::App {
enum class EditorWindowFrameRequestReason : std::uint32_t {
None = 0u,
Initial = 1u << 0u,
PaintMessage = 1u << 1u,
Resize = 1u << 2u,
DpiChanged = 1u << 3u,
ExitSizeMove = 1u << 4u,
BorderlessTransition = 1u << 5u,
ManualScreenshot = 1u << 6u
};
constexpr std::uint32_t ToFrameRequestMask(EditorWindowFrameRequestReason reason) {
return static_cast<std::uint32_t>(reason);
}
} // namespace XCEngine::UI::Editor::App

View File

@@ -3,6 +3,7 @@
#include "Bootstrap/EditorResources.h"
#include "Composition/EditorContext.h"
#include "Platform/Win32/EditorWindow.h"
#include "Platform/Win32/EditorWindowFrameDriver.h"
#include "Platform/Win32/WindowManager/EditorWindowWorkspaceCoordinator.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
@@ -234,7 +235,10 @@ void EditorWindowHostRuntime::RenderAllWindows(
}
EditorWindowFrameTransferRequests transferRequests =
window->RenderFrame(m_editorContext, globalTabDragActive);
EditorWindowFrameDriver::DriveFrame(
*window,
m_editorContext,
globalTabDragActive);
workspaceCoordinator.CommitWindowProjection(*window);
if (!transferRequests.HasPendingRequests()) {
continue;

View File

@@ -59,24 +59,6 @@ struct EditorWindowMessageDispatcher::DispatchContext {
EditorWindow& window;
};
void EditorWindowMessageDispatcher::RenderAndValidateWindow(const DispatchContext& context) {
if (!context.window.IsRenderReady()) {
return;
}
EditorWindowFrameTransferRequests transferRequests = context.window.RenderFrame(
context.hostRuntime.GetEditorContext(),
context.workspaceCoordinator.IsGlobalTabDragActive());
if (transferRequests.HasPendingRequests()) {
context.workspaceCoordinator.HandleWindowFrameTransferRequests(
context.window,
std::move(transferRequests));
}
if (context.hwnd != nullptr && IsWindow(context.hwnd)) {
ValidateRect(context.hwnd, nullptr);
}
}
bool EditorWindowMessageDispatcher::EnsureTrackingMouseLeave(const DispatchContext& context) {
if (context.window.IsTrackingMouseLeave()) {
return true;
@@ -399,7 +381,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowLifecycleMessage(
context.window.OnDpiChanged(
static_cast<UINT>(LOWORD(wParam)),
*reinterpret_cast<const RECT*>(lParam));
RenderAndValidateWindow(context);
context.window.InvalidateHostWindow();
outResult = 0;
return true;
case WM_ENTERSIZEMOVE:
@@ -408,7 +390,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowLifecycleMessage(
return true;
case WM_EXITSIZEMOVE:
context.window.OnExitSizeMove();
RenderAndValidateWindow(context);
context.window.InvalidateHostWindow();
outResult = 0;
return true;
case WM_SIZE:
@@ -416,7 +398,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowLifecycleMessage(
context.window.OnResize(
static_cast<UINT>(LOWORD(lParam)),
static_cast<UINT>(HIWORD(lParam)));
RenderAndValidateWindow(context);
context.window.InvalidateHostWindow();
}
outResult = 0;
return true;
@@ -436,14 +418,7 @@ bool EditorWindowMessageDispatcher::TryDispatchWindowLifecycleMessage(
outResult = 0;
return true;
case WM_PAINT:
if (EditorWindowFrameTransferRequests transferRequests = context.window.OnPaintMessage(
context.hostRuntime.GetEditorContext(),
context.workspaceCoordinator.IsGlobalTabDragActive());
transferRequests.HasPendingRequests()) {
context.workspaceCoordinator.HandleWindowFrameTransferRequests(
context.window,
std::move(transferRequests));
}
context.window.OnPaintMessage();
outResult = 0;
return true;
case WM_ERASEBKGND:

View File

@@ -30,7 +30,6 @@ public:
private:
struct DispatchContext;
static void RenderAndValidateWindow(const DispatchContext& context);
static bool EnsureTrackingMouseLeave(const DispatchContext& context);
static bool TryHandleChromeHoverConsumption(
const DispatchContext& context,