refactor(new_editor): tighten app dependency boundaries
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Bootstrap/EditorResources.h"
|
||||
#include "Platform/Win32/EditorWindowConstants.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
#include "Platform/Win32/EditorWindowPlatformInternal.h"
|
||||
#include "Platform/Win32/EditorWindowRuntimeInternal.h"
|
||||
#include "State/EditorContext.h"
|
||||
@@ -73,122 +74,121 @@ EditorWindow::EditorWindow(
|
||||
std::wstring title,
|
||||
bool primary,
|
||||
UIEditorWorkspaceController workspaceController)
|
||||
: m_window{
|
||||
nullptr,
|
||||
std::move(windowId),
|
||||
std::move(title),
|
||||
{},
|
||||
primary,
|
||||
false }
|
||||
, m_composition{ std::move(workspaceController), {} } {
|
||||
: m_state(std::make_unique<EditorWindowState>()) {
|
||||
m_state->window.windowId = std::move(windowId);
|
||||
m_state->window.title = std::move(title);
|
||||
m_state->window.primary = primary;
|
||||
m_state->composition.workspaceController = std::move(workspaceController);
|
||||
UpdateCachedTitleText();
|
||||
}
|
||||
|
||||
EditorWindow::~EditorWindow() = default;
|
||||
|
||||
std::string_view EditorWindow::GetWindowId() const {
|
||||
return m_window.windowId;
|
||||
return m_state->window.windowId;
|
||||
}
|
||||
|
||||
HWND EditorWindow::GetHwnd() const {
|
||||
return m_window.hwnd;
|
||||
return m_state->window.hwnd;
|
||||
}
|
||||
|
||||
bool EditorWindow::HasHwnd() const {
|
||||
return m_window.hwnd != nullptr;
|
||||
return m_state->window.hwnd != nullptr;
|
||||
}
|
||||
|
||||
bool EditorWindow::IsPrimary() const {
|
||||
return m_window.primary;
|
||||
return m_state->window.primary;
|
||||
}
|
||||
|
||||
bool EditorWindow::IsClosing() const {
|
||||
return m_window.closing;
|
||||
return m_state->window.closing;
|
||||
}
|
||||
|
||||
bool EditorWindow::IsRenderReady() const {
|
||||
return m_render.ready;
|
||||
return m_state->render.ready;
|
||||
}
|
||||
|
||||
bool EditorWindow::IsTrackingMouseLeave() const {
|
||||
return m_input.trackingMouseLeave;
|
||||
return m_state->input.trackingMouseLeave;
|
||||
}
|
||||
|
||||
bool EditorWindow::HasHoveredBorderlessResizeEdge() const {
|
||||
return m_chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
return m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
Host::BorderlessWindowResizeEdge::None;
|
||||
}
|
||||
|
||||
const std::wstring& EditorWindow::GetTitle() const {
|
||||
return m_window.title;
|
||||
return m_state->window.title;
|
||||
}
|
||||
|
||||
const UIEditorWorkspaceController& EditorWindow::GetWorkspaceController() const {
|
||||
return m_composition.workspaceController;
|
||||
return m_state->composition.workspaceController;
|
||||
}
|
||||
|
||||
UIEditorWorkspaceController& EditorWindow::GetWorkspaceController() {
|
||||
return m_composition.workspaceController;
|
||||
return m_state->composition.workspaceController;
|
||||
}
|
||||
|
||||
const EditorShellRuntime& EditorWindow::GetShellRuntime() const {
|
||||
return m_composition.shellRuntime;
|
||||
return m_state->composition.shellRuntime;
|
||||
}
|
||||
|
||||
EditorShellRuntime& EditorWindow::GetShellRuntime() {
|
||||
return m_composition.shellRuntime;
|
||||
return m_state->composition.shellRuntime;
|
||||
}
|
||||
|
||||
const UIEditorShellInteractionFrame& EditorWindow::GetShellFrame() const {
|
||||
return m_composition.shellRuntime.GetShellFrame();
|
||||
return m_state->composition.shellRuntime.GetShellFrame();
|
||||
}
|
||||
|
||||
const UIEditorShellInteractionState& EditorWindow::GetShellInteractionState() const {
|
||||
return m_composition.shellRuntime.GetShellInteractionState();
|
||||
return m_state->composition.shellRuntime.GetShellInteractionState();
|
||||
}
|
||||
|
||||
void EditorWindow::SetExternalDockHostDropPreview(
|
||||
const Widgets::UIEditorDockHostDropPreviewState& preview) {
|
||||
m_composition.shellRuntime.SetExternalDockHostDropPreview(preview);
|
||||
m_state->composition.shellRuntime.SetExternalDockHostDropPreview(preview);
|
||||
}
|
||||
|
||||
void EditorWindow::ClearExternalDockHostDropPreview() {
|
||||
m_composition.shellRuntime.ClearExternalDockHostDropPreview();
|
||||
m_state->composition.shellRuntime.ClearExternalDockHostDropPreview();
|
||||
}
|
||||
|
||||
void EditorWindow::AttachHwnd(HWND hwnd) {
|
||||
m_window.hwnd = hwnd;
|
||||
m_window.closing = false;
|
||||
m_state->window.hwnd = hwnd;
|
||||
m_state->window.closing = false;
|
||||
}
|
||||
|
||||
void EditorWindow::MarkDestroyed() {
|
||||
m_window.hwnd = nullptr;
|
||||
m_window.closing = false;
|
||||
m_input.trackingMouseLeave = false;
|
||||
m_state->window.hwnd = nullptr;
|
||||
m_state->window.closing = false;
|
||||
m_state->input.trackingMouseLeave = false;
|
||||
}
|
||||
|
||||
void EditorWindow::MarkClosing() {
|
||||
m_window.closing = true;
|
||||
m_state->window.closing = true;
|
||||
}
|
||||
|
||||
void EditorWindow::ClearClosing() {
|
||||
m_window.closing = false;
|
||||
m_state->window.closing = false;
|
||||
}
|
||||
|
||||
void EditorWindow::SetTrackingMouseLeave(bool trackingMouseLeave) {
|
||||
m_input.trackingMouseLeave = trackingMouseLeave;
|
||||
m_state->input.trackingMouseLeave = trackingMouseLeave;
|
||||
}
|
||||
|
||||
void EditorWindow::SetTitle(std::wstring title) {
|
||||
m_window.title = std::move(title);
|
||||
m_state->window.title = std::move(title);
|
||||
UpdateCachedTitleText();
|
||||
}
|
||||
|
||||
void EditorWindow::ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController) {
|
||||
m_composition.workspaceController = std::move(workspaceController);
|
||||
m_state->composition.workspaceController = std::move(workspaceController);
|
||||
}
|
||||
|
||||
void EditorWindow::InvalidateHostWindow() const {
|
||||
if (m_window.hwnd != nullptr && IsWindow(m_window.hwnd)) {
|
||||
InvalidateRect(m_window.hwnd, nullptr, FALSE);
|
||||
if (m_state->window.hwnd != nullptr && IsWindow(m_state->window.hwnd)) {
|
||||
InvalidateRect(m_state->window.hwnd, nullptr, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,71 +197,80 @@ bool EditorWindow::Initialize(
|
||||
EditorContext& editorContext,
|
||||
const std::filesystem::path& captureRoot,
|
||||
bool autoCaptureOnStartup) {
|
||||
if (m_window.hwnd == nullptr) {
|
||||
if (m_state->window.hwnd == nullptr) {
|
||||
LogRuntimeTrace("app", "window initialize skipped: hwnd is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
Host::RefreshBorderlessWindowDwmDecorations(m_window.hwnd);
|
||||
m_chrome.runtime.Reset();
|
||||
m_chrome.runtime.SetWindowDpi(QueryWindowDpi(m_window.hwnd));
|
||||
m_render.renderer.SetDpiScale(GetDpiScale());
|
||||
Host::RefreshBorderlessWindowDwmDecorations(m_state->window.hwnd);
|
||||
m_state->chrome.runtime.Reset();
|
||||
m_state->chrome.runtime.SetWindowDpi(QueryWindowDpi(m_state->window.hwnd));
|
||||
m_state->render.renderer.SetDpiScale(GetDpiScale());
|
||||
|
||||
std::ostringstream dpiTrace = {};
|
||||
dpiTrace << "initial dpi=" << m_chrome.runtime.GetWindowDpi()
|
||||
dpiTrace << "initial dpi=" << m_state->chrome.runtime.GetWindowDpi()
|
||||
<< " scale=" << GetDpiScale();
|
||||
LogRuntimeTrace("window", dpiTrace.str());
|
||||
|
||||
if (!m_render.renderer.Initialize(m_window.hwnd)) {
|
||||
if (!m_state->render.renderer.Initialize(m_state->window.hwnd)) {
|
||||
LogRuntimeTrace("app", "renderer initialization failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
GetClientRect(m_window.hwnd, &clientRect);
|
||||
GetClientRect(m_state->window.hwnd, &clientRect);
|
||||
const int clientWidth = (std::max)(clientRect.right - clientRect.left, 1L);
|
||||
const int clientHeight = (std::max)(clientRect.bottom - clientRect.top, 1L);
|
||||
if (!m_render.windowRenderer.Initialize(m_window.hwnd, clientWidth, clientHeight)) {
|
||||
if (!m_state->render.windowRenderer.Initialize(
|
||||
m_state->window.hwnd,
|
||||
clientWidth,
|
||||
clientHeight)) {
|
||||
LogRuntimeTrace("app", "d3d12 window renderer initialization failed");
|
||||
m_render.renderer.Shutdown();
|
||||
m_state->render.renderer.Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
const Host::D3D12WindowRenderLoopAttachResult attachResult =
|
||||
m_render.windowRenderLoop.Attach(m_render.renderer, m_render.windowRenderer);
|
||||
m_state->render.windowRenderLoop.Attach(
|
||||
m_state->render.renderer,
|
||||
m_state->render.windowRenderer);
|
||||
if (!attachResult.interopWarning.empty()) {
|
||||
LogRuntimeTrace("app", attachResult.interopWarning);
|
||||
}
|
||||
|
||||
editorContext.AttachTextMeasurer(m_render.renderer);
|
||||
m_composition.shellRuntime.Initialize(repoRoot, m_render.renderer);
|
||||
m_composition.shellRuntime.AttachViewportWindowRenderer(m_render.windowRenderer);
|
||||
m_composition.shellRuntime.SetViewportSurfacePresentationEnabled(
|
||||
editorContext.AttachTextMeasurer(m_state->render.renderer);
|
||||
m_state->composition.shellRuntime.Initialize(
|
||||
repoRoot,
|
||||
m_state->render.renderer,
|
||||
m_state->render.renderer);
|
||||
m_state->composition.shellRuntime.AttachViewportWindowRenderer(
|
||||
m_state->render.windowRenderer);
|
||||
m_state->composition.shellRuntime.SetViewportSurfacePresentationEnabled(
|
||||
attachResult.hasViewportSurfacePresentation);
|
||||
|
||||
std::string titleBarLogoError = {};
|
||||
if (!LoadEmbeddedPngTexture(
|
||||
m_render.renderer,
|
||||
m_state->render.renderer,
|
||||
IDR_PNG_LOGO_ICON,
|
||||
m_render.titleBarLogoIcon,
|
||||
m_state->render.titleBarLogoIcon,
|
||||
titleBarLogoError)) {
|
||||
LogRuntimeTrace("icons", "titlebar logo_icon.png: " + titleBarLogoError);
|
||||
}
|
||||
if (!m_composition.shellRuntime.GetBuiltInIconError().empty()) {
|
||||
LogRuntimeTrace("icons", m_composition.shellRuntime.GetBuiltInIconError());
|
||||
if (!m_state->composition.shellRuntime.GetBuiltInIconError().empty()) {
|
||||
LogRuntimeTrace("icons", m_state->composition.shellRuntime.GetBuiltInIconError());
|
||||
}
|
||||
|
||||
LogRuntimeTrace(
|
||||
"app",
|
||||
"shell runtime initialized: " +
|
||||
editorContext.DescribeWorkspaceState(
|
||||
m_composition.workspaceController,
|
||||
m_composition.shellRuntime.GetShellInteractionState()));
|
||||
m_render.ready = true;
|
||||
m_state->composition.workspaceController,
|
||||
m_state->composition.shellRuntime.GetShellInteractionState()));
|
||||
m_state->render.ready = true;
|
||||
|
||||
m_render.autoScreenshot.Initialize(captureRoot);
|
||||
m_state->render.autoScreenshot.Initialize(captureRoot);
|
||||
if (autoCaptureOnStartup && IsAutoCaptureOnStartupEnabled()) {
|
||||
m_render.autoScreenshot.RequestCapture("startup");
|
||||
m_state->render.autoScreenshot.RequestCapture("startup");
|
||||
editorContext.SetStatus("Capture", "Startup capture requested.");
|
||||
}
|
||||
|
||||
@@ -271,41 +280,42 @@ bool EditorWindow::Initialize(
|
||||
void EditorWindow::Shutdown() {
|
||||
ForceReleasePointerCapture();
|
||||
|
||||
m_render.ready = false;
|
||||
m_render.autoScreenshot.Shutdown();
|
||||
m_composition.shellRuntime.Shutdown();
|
||||
m_render.renderer.ReleaseTexture(m_render.titleBarLogoIcon);
|
||||
m_render.windowRenderLoop.Detach();
|
||||
m_render.windowRenderer.Shutdown();
|
||||
m_render.renderer.Shutdown();
|
||||
m_input.pendingEvents.clear();
|
||||
m_chrome.chromeState = {};
|
||||
m_chrome.runtime.Reset();
|
||||
m_state->render.ready = false;
|
||||
m_state->render.autoScreenshot.Shutdown();
|
||||
m_state->composition.shellRuntime.Shutdown();
|
||||
m_state->render.renderer.ReleaseTexture(m_state->render.titleBarLogoIcon);
|
||||
m_state->render.windowRenderLoop.Detach();
|
||||
m_state->render.windowRenderer.Shutdown();
|
||||
m_state->render.renderer.Shutdown();
|
||||
m_state->input.pendingEvents.clear();
|
||||
m_state->chrome.chromeState = {};
|
||||
m_state->chrome.runtime.Reset();
|
||||
}
|
||||
|
||||
void EditorWindow::ResetInteractionState() {
|
||||
ForceReleasePointerCapture();
|
||||
|
||||
m_input.pendingEvents.clear();
|
||||
m_input.trackingMouseLeave = false;
|
||||
m_input.modifierTracker.Reset();
|
||||
m_composition.shellRuntime.ResetInteractionState();
|
||||
m_chrome.chromeState = {};
|
||||
m_chrome.runtime.EndBorderlessResize();
|
||||
m_chrome.runtime.EndBorderlessWindowDragRestore();
|
||||
m_chrome.runtime.EndInteractiveResize();
|
||||
m_chrome.runtime.SetHoveredBorderlessResizeEdge(Host::BorderlessWindowResizeEdge::None);
|
||||
m_chrome.runtime.ClearPredictedClientPixelSize();
|
||||
m_state->input.pendingEvents.clear();
|
||||
m_state->input.trackingMouseLeave = false;
|
||||
m_state->input.modifierTracker.Reset();
|
||||
m_state->composition.shellRuntime.ResetInteractionState();
|
||||
m_state->chrome.chromeState = {};
|
||||
m_state->chrome.runtime.EndBorderlessResize();
|
||||
m_state->chrome.runtime.EndBorderlessWindowDragRestore();
|
||||
m_state->chrome.runtime.EndInteractiveResize();
|
||||
m_state->chrome.runtime.SetHoveredBorderlessResizeEdge(
|
||||
Host::BorderlessWindowResizeEdge::None);
|
||||
m_state->chrome.runtime.ClearPredictedClientPixelSize();
|
||||
}
|
||||
|
||||
bool EditorWindow::ApplyWindowResize(UINT width, UINT height) {
|
||||
if (!m_render.ready || width == 0u || height == 0u) {
|
||||
if (!m_state->render.ready || width == 0u || height == 0u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Host::D3D12WindowRenderLoopResizeResult resizeResult =
|
||||
m_render.windowRenderLoop.ApplyResize(width, height);
|
||||
m_composition.shellRuntime.SetViewportSurfacePresentationEnabled(
|
||||
m_state->render.windowRenderLoop.ApplyResize(width, height);
|
||||
m_state->composition.shellRuntime.SetViewportSurfacePresentationEnabled(
|
||||
resizeResult.hasViewportSurfacePresentation);
|
||||
|
||||
if (!resizeResult.windowRendererWarning.empty()) {
|
||||
@@ -322,12 +332,12 @@ bool EditorWindow::ApplyWindowResize(UINT width, UINT height) {
|
||||
bool EditorWindow::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const {
|
||||
outWidth = 0u;
|
||||
outHeight = 0u;
|
||||
if (m_window.hwnd == nullptr || !IsWindow(m_window.hwnd)) {
|
||||
if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
if (!GetClientRect(m_window.hwnd, &clientRect)) {
|
||||
if (!GetClientRect(m_state->window.hwnd, &clientRect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -343,7 +353,7 @@ bool EditorWindow::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight)
|
||||
}
|
||||
|
||||
bool EditorWindow::ResolveRenderClientPixelSize(UINT& outWidth, UINT& outHeight) const {
|
||||
if (m_chrome.runtime.TryGetPredictedClientPixelSize(outWidth, outHeight)) {
|
||||
if (m_state->chrome.runtime.TryGetPredictedClientPixelSize(outWidth, outHeight)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -351,7 +361,7 @@ bool EditorWindow::ResolveRenderClientPixelSize(UINT& outWidth, UINT& outHeight)
|
||||
}
|
||||
|
||||
float EditorWindow::GetDpiScale() const {
|
||||
return m_chrome.runtime.GetDpiScale(kBaseDpiScale);
|
||||
return m_state->chrome.runtime.GetDpiScale(kBaseDpiScale);
|
||||
}
|
||||
|
||||
float EditorWindow::PixelsToDips(float pixels) const {
|
||||
@@ -367,11 +377,11 @@ UIPoint EditorWindow::ConvertClientPixelsToDips(LONG x, LONG y) const {
|
||||
|
||||
UIPoint EditorWindow::ConvertScreenPixelsToClientDips(const POINT& screenPoint) const {
|
||||
POINT clientPoint = screenPoint;
|
||||
if (m_window.hwnd != nullptr) {
|
||||
ScreenToClient(m_window.hwnd, &clientPoint);
|
||||
if (m_state->window.hwnd != nullptr) {
|
||||
ScreenToClient(m_state->window.hwnd, &clientPoint);
|
||||
}
|
||||
|
||||
const float dpiScale = m_chrome.runtime.GetDpiScale(kBaseDpiScale);
|
||||
const float dpiScale = m_state->chrome.runtime.GetDpiScale(kBaseDpiScale);
|
||||
return UIPoint(
|
||||
dpiScale > 0.0f
|
||||
? static_cast<float>(clientPoint.x) / dpiScale
|
||||
@@ -385,15 +395,17 @@ void EditorWindow::OnResize(UINT width, UINT height) {
|
||||
bool matchesPredictedClientSize = false;
|
||||
UINT predictedWidth = 0u;
|
||||
UINT predictedHeight = 0u;
|
||||
if (m_chrome.runtime.TryGetPredictedClientPixelSize(predictedWidth, predictedHeight)) {
|
||||
if (m_state->chrome.runtime.TryGetPredictedClientPixelSize(
|
||||
predictedWidth,
|
||||
predictedHeight)) {
|
||||
matchesPredictedClientSize =
|
||||
predictedWidth == width &&
|
||||
predictedHeight == height;
|
||||
}
|
||||
|
||||
m_chrome.runtime.ClearPredictedClientPixelSize();
|
||||
if (IsBorderlessWindowEnabled() && m_window.hwnd != nullptr) {
|
||||
Host::RefreshBorderlessWindowDwmDecorations(m_window.hwnd);
|
||||
m_state->chrome.runtime.ClearPredictedClientPixelSize();
|
||||
if (IsBorderlessWindowEnabled() && m_state->window.hwnd != nullptr) {
|
||||
Host::RefreshBorderlessWindowDwmDecorations(m_state->window.hwnd);
|
||||
}
|
||||
|
||||
if (!matchesPredictedClientSize) {
|
||||
@@ -402,12 +414,12 @@ void EditorWindow::OnResize(UINT width, UINT height) {
|
||||
}
|
||||
|
||||
void EditorWindow::OnEnterSizeMove() {
|
||||
m_chrome.runtime.BeginInteractiveResize();
|
||||
m_state->chrome.runtime.BeginInteractiveResize();
|
||||
}
|
||||
|
||||
void EditorWindow::OnExitSizeMove() {
|
||||
m_chrome.runtime.EndInteractiveResize();
|
||||
m_chrome.runtime.ClearPredictedClientPixelSize();
|
||||
m_state->chrome.runtime.EndInteractiveResize();
|
||||
m_state->chrome.runtime.ClearPredictedClientPixelSize();
|
||||
UINT width = 0u;
|
||||
UINT height = 0u;
|
||||
if (QueryCurrentClientPixelSize(width, height)) {
|
||||
@@ -416,13 +428,13 @@ void EditorWindow::OnExitSizeMove() {
|
||||
}
|
||||
|
||||
void EditorWindow::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
|
||||
m_chrome.runtime.SetWindowDpi(dpi == 0u ? kDefaultDpi : dpi);
|
||||
m_render.renderer.SetDpiScale(GetDpiScale());
|
||||
if (m_window.hwnd != nullptr) {
|
||||
m_state->chrome.runtime.SetWindowDpi(dpi == 0u ? kDefaultDpi : dpi);
|
||||
m_state->render.renderer.SetDpiScale(GetDpiScale());
|
||||
if (m_state->window.hwnd != nullptr) {
|
||||
const LONG windowWidth = suggestedRect.right - suggestedRect.left;
|
||||
const LONG windowHeight = suggestedRect.bottom - suggestedRect.top;
|
||||
SetWindowPos(
|
||||
m_window.hwnd,
|
||||
m_state->window.hwnd,
|
||||
nullptr,
|
||||
suggestedRect.left,
|
||||
suggestedRect.top,
|
||||
@@ -434,11 +446,11 @@ void EditorWindow::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
|
||||
if (QueryCurrentClientPixelSize(clientWidth, clientHeight)) {
|
||||
ApplyWindowResize(clientWidth, clientHeight);
|
||||
}
|
||||
Host::RefreshBorderlessWindowDwmDecorations(m_window.hwnd);
|
||||
Host::RefreshBorderlessWindowDwmDecorations(m_state->window.hwnd);
|
||||
}
|
||||
|
||||
std::ostringstream trace = {};
|
||||
trace << "dpi changed to " << m_chrome.runtime.GetWindowDpi()
|
||||
trace << "dpi changed to " << m_state->chrome.runtime.GetWindowDpi()
|
||||
<< " scale=" << GetDpiScale();
|
||||
LogRuntimeTrace("window", trace.str());
|
||||
}
|
||||
@@ -449,7 +461,7 @@ bool EditorWindow::IsVerboseRuntimeTraceEnabled() {
|
||||
}
|
||||
|
||||
void EditorWindow::UpdateCachedTitleText() {
|
||||
m_window.titleText = WideToUtf8(m_window.title);
|
||||
m_state->window.titleText = WideToUtf8(m_state->window.title);
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
Reference in New Issue
Block a user