refactor(new_editor): tighten app dependency boundaries
This commit is contained in:
@@ -4,21 +4,61 @@
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "Platform/Win32/EditorWindowState.h"
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
#include "Platform/Win32/EditorWindowPointerCapture.h"
|
||||
#include "Platform/Win32/EditorWindowTransferRequests.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine::UI {
|
||||
|
||||
class UIDrawList;
|
||||
|
||||
struct UIPoint;
|
||||
struct UIRect;
|
||||
struct UIInputEvent;
|
||||
struct UIInputModifiers;
|
||||
|
||||
enum class UIPointerButton : std::uint8_t;
|
||||
enum class UIInputEventType : std::uint8_t;
|
||||
|
||||
} // namespace XCEngine::UI
|
||||
|
||||
namespace XCEngine::UI::Editor {
|
||||
|
||||
class UIEditorWorkspaceController;
|
||||
|
||||
struct UIEditorDockHostInteractionState;
|
||||
struct UIEditorShellInteractionFrame;
|
||||
struct UIEditorShellInteractionState;
|
||||
struct UIEditorShellInteractionResult;
|
||||
|
||||
namespace Widgets {
|
||||
struct UIEditorDockHostDropPreviewState;
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor
|
||||
|
||||
namespace XCEngine::UI::Editor::Host {
|
||||
|
||||
enum class BorderlessWindowChromeHitTarget : std::uint8_t;
|
||||
enum class BorderlessWindowResizeEdge : std::uint8_t;
|
||||
|
||||
struct BorderlessWindowChromeLayout;
|
||||
|
||||
} // namespace XCEngine::UI::Editor::Host
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
class EditorContext;
|
||||
class EditorShellRuntime;
|
||||
struct EditorWindowState;
|
||||
|
||||
namespace Internal {
|
||||
class EditorWindowHostRuntime;
|
||||
@@ -40,6 +80,7 @@ public:
|
||||
std::wstring title,
|
||||
bool primary,
|
||||
UIEditorWorkspaceController workspaceController);
|
||||
~EditorWindow();
|
||||
|
||||
EditorWindow(const EditorWindow&) = delete;
|
||||
EditorWindow& operator=(const EditorWindow&) = delete;
|
||||
@@ -215,11 +256,7 @@ private:
|
||||
void UpdateCachedTitleText();
|
||||
static bool IsVerboseRuntimeTraceEnabled();
|
||||
|
||||
EditorWindowWindowState m_window = {};
|
||||
EditorWindowRenderState m_render = {};
|
||||
EditorWindowInputState m_input = {};
|
||||
EditorWindowCompositionState m_composition = {};
|
||||
EditorWindowChromeRuntimeState m_chrome = {};
|
||||
std::unique_ptr<EditorWindowState> m_state = {};
|
||||
};
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
bool EditorWindow::IsBorderlessWindowEnabled() const {
|
||||
@@ -6,7 +7,7 @@ bool EditorWindow::IsBorderlessWindowEnabled() const {
|
||||
}
|
||||
|
||||
bool EditorWindow::IsBorderlessWindowMaximized() const {
|
||||
return m_chrome.runtime.IsBorderlessWindowMaximized();
|
||||
return m_state->chrome.runtime.IsBorderlessWindowMaximized();
|
||||
}
|
||||
|
||||
bool EditorWindow::HandleBorderlessWindowSystemCommand(
|
||||
@@ -22,7 +23,7 @@ bool EditorWindow::HandleBorderlessWindowSystemCommand(
|
||||
ToggleBorderlessWindowMaximizeRestore(editorContext, globalTabDragActive);
|
||||
return true;
|
||||
case SC_RESTORE:
|
||||
if (!IsIconic(m_window.hwnd)) {
|
||||
if (!IsIconic(m_state->window.hwnd)) {
|
||||
ToggleBorderlessWindowMaximizeRestore(editorContext, globalTabDragActive);
|
||||
return true;
|
||||
}
|
||||
@@ -33,29 +34,31 @@ bool EditorWindow::HandleBorderlessWindowSystemCommand(
|
||||
}
|
||||
|
||||
bool EditorWindow::HandleBorderlessWindowGetMinMaxInfo(LPARAM lParam) const {
|
||||
return Host::HandleBorderlessWindowGetMinMaxInfo(m_window.hwnd, lParam);
|
||||
return Host::HandleBorderlessWindowGetMinMaxInfo(m_state->window.hwnd, lParam);
|
||||
}
|
||||
|
||||
LRESULT EditorWindow::HandleBorderlessWindowNcCalcSize(WPARAM wParam, LPARAM lParam) const {
|
||||
return Host::HandleBorderlessWindowNcCalcSize(
|
||||
m_window.hwnd,
|
||||
m_state->window.hwnd,
|
||||
wParam,
|
||||
lParam,
|
||||
m_chrome.runtime.GetWindowDpi());
|
||||
m_state->chrome.runtime.GetWindowDpi());
|
||||
}
|
||||
|
||||
bool EditorWindow::QueryCurrentWindowRect(RECT& outRect) const {
|
||||
outRect = {};
|
||||
return m_window.hwnd != nullptr && GetWindowRect(m_window.hwnd, &outRect) != FALSE;
|
||||
return m_state->window.hwnd != nullptr &&
|
||||
GetWindowRect(m_state->window.hwnd, &outRect) != FALSE;
|
||||
}
|
||||
|
||||
bool EditorWindow::QueryBorderlessWindowWorkAreaRect(RECT& outRect) const {
|
||||
outRect = {};
|
||||
if (m_window.hwnd == nullptr) {
|
||||
if (m_state->window.hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const HMONITOR monitor = MonitorFromWindow(m_window.hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
const HMONITOR monitor =
|
||||
MonitorFromWindow(m_state->window.hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
if (monitor == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -74,7 +77,7 @@ bool EditorWindow::ApplyPredictedWindowRectTransition(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive,
|
||||
const RECT& targetRect) {
|
||||
if (m_window.hwnd == nullptr) {
|
||||
if (m_state->window.hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -84,13 +87,13 @@ bool EditorWindow::ApplyPredictedWindowRectTransition(
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetPredictedClientPixelSize(
|
||||
m_state->chrome.runtime.SetPredictedClientPixelSize(
|
||||
static_cast<UINT>(width),
|
||||
static_cast<UINT>(height));
|
||||
ApplyWindowResize(static_cast<UINT>(width), static_cast<UINT>(height));
|
||||
(void)RenderFrame(editorContext, globalTabDragActive);
|
||||
SetWindowPos(
|
||||
m_window.hwnd,
|
||||
m_state->window.hwnd,
|
||||
nullptr,
|
||||
targetRect.left,
|
||||
targetRect.top,
|
||||
@@ -104,7 +107,7 @@ bool EditorWindow::ApplyPredictedWindowRectTransition(
|
||||
void EditorWindow::ToggleBorderlessWindowMaximizeRestore(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (m_window.hwnd == nullptr) {
|
||||
if (m_state->window.hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -116,8 +119,8 @@ void EditorWindow::ToggleBorderlessWindowMaximizeRestore(
|
||||
return;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetBorderlessWindowRestoreRect(currentRect);
|
||||
m_chrome.runtime.SetBorderlessWindowMaximized(true);
|
||||
m_state->chrome.runtime.SetBorderlessWindowRestoreRect(currentRect);
|
||||
m_state->chrome.runtime.SetBorderlessWindowMaximized(true);
|
||||
ApplyPredictedWindowRectTransition(
|
||||
editorContext,
|
||||
globalTabDragActive,
|
||||
@@ -126,11 +129,11 @@ void EditorWindow::ToggleBorderlessWindowMaximizeRestore(
|
||||
}
|
||||
|
||||
RECT restoreRect = {};
|
||||
if (!m_chrome.runtime.TryGetBorderlessWindowRestoreRect(restoreRect)) {
|
||||
if (!m_state->chrome.runtime.TryGetBorderlessWindowRestoreRect(restoreRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetBorderlessWindowMaximized(false);
|
||||
m_state->chrome.runtime.SetBorderlessWindowMaximized(false);
|
||||
ApplyPredictedWindowRectTransition(
|
||||
editorContext,
|
||||
globalTabDragActive,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
|
||||
#include <XCEngine/UI/Types.h>
|
||||
|
||||
@@ -13,11 +14,11 @@ using ::XCEngine::UI::UIRect;
|
||||
bool EditorWindow::UpdateBorderlessWindowResizeHover(LPARAM lParam) {
|
||||
const Host::BorderlessWindowResizeEdge hoveredEdge =
|
||||
HitTestBorderlessWindowResizeEdge(lParam);
|
||||
if (m_chrome.runtime.GetHoveredBorderlessResizeEdge() == hoveredEdge) {
|
||||
if (m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() == hoveredEdge) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetHoveredBorderlessResizeEdge(hoveredEdge);
|
||||
m_state->chrome.runtime.SetHoveredBorderlessResizeEdge(hoveredEdge);
|
||||
ApplyBorderlessWindowResizeCursorHoverPriority();
|
||||
return true;
|
||||
}
|
||||
@@ -25,7 +26,8 @@ bool EditorWindow::UpdateBorderlessWindowResizeHover(LPARAM lParam) {
|
||||
bool EditorWindow::HandleBorderlessWindowResizeButtonDown(LPARAM lParam) {
|
||||
const Host::BorderlessWindowResizeEdge edge =
|
||||
HitTestBorderlessWindowResizeEdge(lParam);
|
||||
if (edge == Host::BorderlessWindowResizeEdge::None || m_window.hwnd == nullptr) {
|
||||
if (edge == Host::BorderlessWindowResizeEdge::None ||
|
||||
m_state->window.hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -35,22 +37,22 @@ bool EditorWindow::HandleBorderlessWindowResizeButtonDown(LPARAM lParam) {
|
||||
}
|
||||
|
||||
RECT windowRect = {};
|
||||
if (!GetWindowRect(m_window.hwnd, &windowRect)) {
|
||||
if (!GetWindowRect(m_state->window.hwnd, &windowRect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chrome.runtime.BeginBorderlessResize(edge, screenPoint, windowRect);
|
||||
m_state->chrome.runtime.BeginBorderlessResize(edge, screenPoint, windowRect);
|
||||
AcquirePointerCapture(EditorWindowPointerCaptureOwner::BorderlessResize);
|
||||
InvalidateHostWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorWindow::HandleBorderlessWindowResizeButtonUp() {
|
||||
if (!m_chrome.runtime.IsBorderlessResizeActive()) {
|
||||
if (!m_state->chrome.runtime.IsBorderlessResizeActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chrome.runtime.EndBorderlessResize();
|
||||
m_state->chrome.runtime.EndBorderlessResize();
|
||||
ReleasePointerCapture(EditorWindowPointerCaptureOwner::BorderlessResize);
|
||||
InvalidateHostWindow();
|
||||
return true;
|
||||
@@ -59,7 +61,8 @@ bool EditorWindow::HandleBorderlessWindowResizeButtonUp() {
|
||||
bool EditorWindow::HandleBorderlessWindowResizePointerMove(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (!m_chrome.runtime.IsBorderlessResizeActive() || m_window.hwnd == nullptr) {
|
||||
if (!m_state->chrome.runtime.IsBorderlessResizeActive() ||
|
||||
m_state->window.hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -69,10 +72,10 @@ bool EditorWindow::HandleBorderlessWindowResizePointerMove(
|
||||
}
|
||||
|
||||
RECT targetRect = Host::ComputeBorderlessWindowResizeRect(
|
||||
m_chrome.runtime.GetBorderlessResizeInitialWindowRect(),
|
||||
m_chrome.runtime.GetBorderlessResizeInitialScreenPoint(),
|
||||
m_state->chrome.runtime.GetBorderlessResizeInitialWindowRect(),
|
||||
m_state->chrome.runtime.GetBorderlessResizeInitialScreenPoint(),
|
||||
currentScreenPoint,
|
||||
m_chrome.runtime.GetBorderlessResizeEdge(),
|
||||
m_state->chrome.runtime.GetBorderlessResizeEdge(),
|
||||
640,
|
||||
360);
|
||||
const int width = targetRect.right - targetRect.left;
|
||||
@@ -81,14 +84,14 @@ bool EditorWindow::HandleBorderlessWindowResizePointerMove(
|
||||
return true;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetPredictedClientPixelSize(
|
||||
m_state->chrome.runtime.SetPredictedClientPixelSize(
|
||||
static_cast<UINT>(width),
|
||||
static_cast<UINT>(height));
|
||||
ApplyWindowResize(static_cast<UINT>(width), static_cast<UINT>(height));
|
||||
(void)RenderFrame(editorContext, globalTabDragActive);
|
||||
|
||||
SetWindowPos(
|
||||
m_window.hwnd,
|
||||
m_state->window.hwnd,
|
||||
nullptr,
|
||||
targetRect.left,
|
||||
targetRect.top,
|
||||
@@ -99,40 +102,44 @@ bool EditorWindow::HandleBorderlessWindowResizePointerMove(
|
||||
}
|
||||
|
||||
void EditorWindow::ClearBorderlessWindowResizeState() {
|
||||
if (m_chrome.runtime.IsBorderlessResizeActive()) {
|
||||
if (m_state->chrome.runtime.IsBorderlessResizeActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_chrome.runtime.GetHoveredBorderlessResizeEdge() ==
|
||||
if (m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() ==
|
||||
Host::BorderlessWindowResizeEdge::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetHoveredBorderlessResizeEdge(Host::BorderlessWindowResizeEdge::None);
|
||||
m_state->chrome.runtime.SetHoveredBorderlessResizeEdge(
|
||||
Host::BorderlessWindowResizeEdge::None);
|
||||
InvalidateHostWindow();
|
||||
}
|
||||
|
||||
void EditorWindow::ForceClearBorderlessWindowResizeState() {
|
||||
if (m_chrome.runtime.GetHoveredBorderlessResizeEdge() ==
|
||||
if (m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() ==
|
||||
Host::BorderlessWindowResizeEdge::None &&
|
||||
!m_chrome.runtime.IsBorderlessResizeActive()) {
|
||||
!m_state->chrome.runtime.IsBorderlessResizeActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_chrome.runtime.SetHoveredBorderlessResizeEdge(Host::BorderlessWindowResizeEdge::None);
|
||||
m_chrome.runtime.EndBorderlessResize();
|
||||
m_state->chrome.runtime.SetHoveredBorderlessResizeEdge(
|
||||
Host::BorderlessWindowResizeEdge::None);
|
||||
m_state->chrome.runtime.EndBorderlessResize();
|
||||
ReleasePointerCapture(EditorWindowPointerCaptureOwner::BorderlessResize);
|
||||
InvalidateHostWindow();
|
||||
}
|
||||
|
||||
Host::BorderlessWindowResizeEdge EditorWindow::HitTestBorderlessWindowResizeEdge(
|
||||
LPARAM lParam) const {
|
||||
if (!IsBorderlessWindowEnabled() || m_window.hwnd == nullptr || IsBorderlessWindowMaximized()) {
|
||||
if (!IsBorderlessWindowEnabled() ||
|
||||
m_state->window.hwnd == nullptr ||
|
||||
IsBorderlessWindowMaximized()) {
|
||||
return Host::BorderlessWindowResizeEdge::None;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
if (!GetClientRect(m_window.hwnd, &clientRect)) {
|
||||
if (!GetClientRect(m_state->window.hwnd, &clientRect)) {
|
||||
return Host::BorderlessWindowResizeEdge::None;
|
||||
}
|
||||
|
||||
@@ -146,10 +153,10 @@ Host::BorderlessWindowResizeEdge EditorWindow::HitTestBorderlessWindowResizeEdge
|
||||
}
|
||||
|
||||
void EditorWindow::ApplyBorderlessWindowResizeCursorHoverPriority() {
|
||||
if (m_chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
if (m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
Host::BorderlessWindowResizeEdge::None ||
|
||||
m_chrome.runtime.IsBorderlessResizeActive()) {
|
||||
m_chrome.chromeState.hoveredTarget =
|
||||
m_state->chrome.runtime.IsBorderlessResizeActive()) {
|
||||
m_state->chrome.chromeState.hoveredTarget =
|
||||
Host::BorderlessWindowChromeHitTarget::None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowConstants.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
#include "Platform/Win32/EditorWindowRuntimeInternal.h"
|
||||
#include "Platform/Win32/EditorWindowStyle.h"
|
||||
#include "State/EditorContext.h"
|
||||
@@ -127,7 +128,7 @@ std::uint8_t ResolveExpectedShellCaptureButtons(
|
||||
EditorWindowFrameTransferRequests EditorWindow::RenderFrame(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (!m_render.ready || m_window.hwnd == nullptr) {
|
||||
if (!m_state->render.ready || m_state->window.hwnd == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -158,13 +159,13 @@ EditorWindowFrameTransferRequests EditorWindow::RenderFrame(
|
||||
AppendBorderlessWindowChrome(drawList, width);
|
||||
|
||||
const Host::D3D12WindowRenderLoopPresentResult presentResult =
|
||||
m_render.windowRenderLoop.Present(drawData);
|
||||
m_state->render.windowRenderLoop.Present(drawData);
|
||||
if (!presentResult.warning.empty()) {
|
||||
LogRuntimeTrace("present", presentResult.warning);
|
||||
}
|
||||
|
||||
m_render.autoScreenshot.CaptureIfRequested(
|
||||
m_render.renderer,
|
||||
m_state->render.autoScreenshot.CaptureIfRequested(
|
||||
m_state->render.renderer,
|
||||
drawData,
|
||||
pixelWidth,
|
||||
pixelHeight,
|
||||
@@ -175,15 +176,15 @@ EditorWindowFrameTransferRequests EditorWindow::RenderFrame(
|
||||
EditorWindowFrameTransferRequests EditorWindow::OnPaintMessage(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (!m_render.ready || m_window.hwnd == nullptr) {
|
||||
if (!m_state->render.ready || m_state->window.hwnd == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
PAINTSTRUCT paintStruct = {};
|
||||
BeginPaint(m_window.hwnd, &paintStruct);
|
||||
BeginPaint(m_state->window.hwnd, &paintStruct);
|
||||
const EditorWindowFrameTransferRequests transferRequests =
|
||||
RenderFrame(editorContext, globalTabDragActive);
|
||||
EndPaint(m_window.hwnd, &paintStruct);
|
||||
EndPaint(m_state->window.hwnd, &paintStruct);
|
||||
return transferRequests;
|
||||
}
|
||||
|
||||
@@ -210,40 +211,40 @@ EditorWindowFrameTransferRequests EditorWindow::RenderRuntimeFrame(
|
||||
const UIRect& workspaceBounds,
|
||||
UIDrawList& drawList) {
|
||||
SyncShellCapturedPointerButtonsFromSystemState();
|
||||
std::vector<UIInputEvent> frameEvents = std::move(m_input.pendingEvents);
|
||||
m_input.pendingEvents.clear();
|
||||
std::vector<UIInputEvent> frameEvents = std::move(m_state->input.pendingEvents);
|
||||
m_state->input.pendingEvents.clear();
|
||||
if (!frameEvents.empty() && IsVerboseRuntimeTraceEnabled()) {
|
||||
LogRuntimeTrace(
|
||||
"input",
|
||||
DescribeInputEvents(frameEvents) + " | " +
|
||||
editorContext.DescribeWorkspaceState(
|
||||
m_composition.workspaceController,
|
||||
m_composition.shellRuntime.GetShellInteractionState()));
|
||||
m_state->composition.workspaceController,
|
||||
m_state->composition.shellRuntime.GetShellInteractionState()));
|
||||
}
|
||||
|
||||
const Host::D3D12WindowRenderLoopFrameContext frameContext =
|
||||
m_render.windowRenderLoop.BeginFrame();
|
||||
m_state->render.windowRenderLoop.BeginFrame();
|
||||
if (!frameContext.warning.empty()) {
|
||||
LogRuntimeTrace("viewport", frameContext.warning);
|
||||
}
|
||||
|
||||
editorContext.AttachTextMeasurer(m_render.renderer);
|
||||
editorContext.AttachTextMeasurer(m_state->render.renderer);
|
||||
const bool useDetachedTitleBarTabStrip = ShouldUseDetachedTitleBarTabStrip();
|
||||
m_composition.shellRuntime.Update(
|
||||
m_state->composition.shellRuntime.Update(
|
||||
editorContext,
|
||||
m_composition.workspaceController,
|
||||
m_state->composition.workspaceController,
|
||||
workspaceBounds,
|
||||
frameEvents,
|
||||
BuildCaptureStatusText(),
|
||||
m_window.primary
|
||||
m_state->window.primary
|
||||
? EditorShellVariant::Primary
|
||||
: EditorShellVariant::DetachedWindow,
|
||||
useDetachedTitleBarTabStrip,
|
||||
useDetachedTitleBarTabStrip ? kBorderlessTitleBarHeightDips : 0.0f);
|
||||
const UIEditorShellInteractionFrame& shellFrame =
|
||||
m_composition.shellRuntime.GetShellFrame();
|
||||
m_state->composition.shellRuntime.GetShellFrame();
|
||||
const UIEditorDockHostInteractionState& dockHostInteractionState =
|
||||
m_composition.shellRuntime
|
||||
m_state->composition.shellRuntime
|
||||
.GetShellInteractionState()
|
||||
.workspaceInteractionState
|
||||
.dockHostInteractionState;
|
||||
@@ -253,14 +254,15 @@ EditorWindowFrameTransferRequests EditorWindow::RenderRuntimeFrame(
|
||||
BuildShellTransferRequests(globalTabDragActive, dockHostInteractionState, shellFrame);
|
||||
|
||||
ApplyHostCaptureRequests(shellFrame.result);
|
||||
for (const WorkspaceTraceEntry& entry : m_composition.shellRuntime.GetTraceEntries()) {
|
||||
for (const WorkspaceTraceEntry& entry :
|
||||
m_state->composition.shellRuntime.GetTraceEntries()) {
|
||||
LogRuntimeTrace(entry.channel, entry.message);
|
||||
}
|
||||
ApplyHostedContentCaptureRequests();
|
||||
ApplyCurrentCursor();
|
||||
m_composition.shellRuntime.Append(drawList);
|
||||
m_state->composition.shellRuntime.Append(drawList);
|
||||
if (frameContext.canRenderViewports) {
|
||||
m_composition.shellRuntime.RenderRequestedViewports(frameContext.renderContext);
|
||||
m_state->composition.shellRuntime.RenderRequestedViewports(frameContext.renderContext);
|
||||
}
|
||||
return transferRequests;
|
||||
}
|
||||
@@ -301,7 +303,7 @@ void EditorWindow::LogFrameInteractionTrace(
|
||||
<< " commandExecuted="
|
||||
<< (shellFrame.result.workspaceResult.dockHostResult.commandExecuted ? "true" : "false")
|
||||
<< " active="
|
||||
<< m_composition.workspaceController.GetWorkspace().activePanelId
|
||||
<< m_state->composition.workspaceController.GetWorkspace().activePanelId
|
||||
<< " message="
|
||||
<< shellFrame.result.workspaceResult.dockHostResult.layoutResult.message;
|
||||
LogRuntimeTrace("frame", frameTrace.str());
|
||||
@@ -339,33 +341,33 @@ EditorWindowFrameTransferRequests EditorWindow::BuildShellTransferRequests(
|
||||
}
|
||||
|
||||
std::string EditorWindow::BuildCaptureStatusText() const {
|
||||
if (m_render.autoScreenshot.HasPendingCapture()) {
|
||||
if (m_state->render.autoScreenshot.HasPendingCapture()) {
|
||||
return "Shot pending...";
|
||||
}
|
||||
|
||||
if (!m_render.autoScreenshot.GetLastCaptureError().empty()) {
|
||||
return TruncateText(m_render.autoScreenshot.GetLastCaptureError(), 38u);
|
||||
if (!m_state->render.autoScreenshot.GetLastCaptureError().empty()) {
|
||||
return TruncateText(m_state->render.autoScreenshot.GetLastCaptureError(), 38u);
|
||||
}
|
||||
|
||||
if (!m_render.autoScreenshot.GetLastCaptureSummary().empty()) {
|
||||
return TruncateText(m_render.autoScreenshot.GetLastCaptureSummary(), 38u);
|
||||
if (!m_state->render.autoScreenshot.GetLastCaptureSummary().empty()) {
|
||||
return TruncateText(m_state->render.autoScreenshot.GetLastCaptureSummary(), 38u);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void EditorWindow::SyncShellCapturedPointerButtonsFromSystemState() {
|
||||
m_input.modifierTracker.SyncFromSystemState();
|
||||
m_state->input.modifierTracker.SyncFromSystemState();
|
||||
|
||||
const std::uint8_t expectedButtons =
|
||||
ResolveExpectedShellCaptureButtons(m_composition.shellRuntime);
|
||||
ResolveExpectedShellCaptureButtons(m_state->composition.shellRuntime);
|
||||
if (expectedButtons == 0u ||
|
||||
HasPendingPointerStateReconciliationEvent(m_input.pendingEvents)) {
|
||||
HasPendingPointerStateReconciliationEvent(m_state->input.pendingEvents)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const UIInputModifiers modifiers =
|
||||
m_input.modifierTracker.GetCurrentModifiers();
|
||||
m_state->input.modifierTracker.GetCurrentModifiers();
|
||||
if ((ButtonMaskFromModifiers(modifiers) & expectedButtons) == expectedButtons) {
|
||||
return;
|
||||
}
|
||||
@@ -383,12 +385,12 @@ void EditorWindow::ApplyHostCaptureRequests(const UIEditorShellInteractionResult
|
||||
}
|
||||
|
||||
void EditorWindow::ApplyHostedContentCaptureRequests() {
|
||||
if (m_composition.shellRuntime.WantsHostPointerCapture()) {
|
||||
if (m_state->composition.shellRuntime.WantsHostPointerCapture()) {
|
||||
AcquirePointerCapture(EditorWindowPointerCaptureOwner::HostedContent);
|
||||
}
|
||||
|
||||
if (m_composition.shellRuntime.WantsHostPointerRelease() &&
|
||||
!m_composition.shellRuntime.HasShellInteractiveCapture()) {
|
||||
if (m_state->composition.shellRuntime.WantsHostPointerRelease() &&
|
||||
!m_state->composition.shellRuntime.HasShellInteractiveCapture()) {
|
||||
ReleasePointerCapture(EditorWindowPointerCaptureOwner::HostedContent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
#include <XCEngine/UI/Types.h>
|
||||
@@ -128,59 +129,59 @@ bool EditorWindow::ApplyCurrentCursor() const {
|
||||
|
||||
|
||||
bool EditorWindow::HasInteractiveCaptureState() const {
|
||||
return m_composition.shellRuntime.HasInteractiveCapture() ||
|
||||
m_chrome.runtime.IsBorderlessWindowDragRestoreArmed() ||
|
||||
m_chrome.runtime.IsBorderlessResizeActive() ||
|
||||
m_input.pointerCaptureOwner != EditorWindowPointerCaptureOwner::None;
|
||||
return m_state->composition.shellRuntime.HasInteractiveCapture() ||
|
||||
m_state->chrome.runtime.IsBorderlessWindowDragRestoreArmed() ||
|
||||
m_state->chrome.runtime.IsBorderlessResizeActive() ||
|
||||
m_state->input.pointerCaptureOwner != EditorWindowPointerCaptureOwner::None;
|
||||
}
|
||||
|
||||
EditorWindowPointerCaptureOwner EditorWindow::GetPointerCaptureOwner() const {
|
||||
return m_input.pointerCaptureOwner;
|
||||
return m_state->input.pointerCaptureOwner;
|
||||
}
|
||||
|
||||
bool EditorWindow::OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const {
|
||||
return m_input.pointerCaptureOwner == owner;
|
||||
return m_state->input.pointerCaptureOwner == owner;
|
||||
}
|
||||
|
||||
void EditorWindow::AcquirePointerCapture(EditorWindowPointerCaptureOwner owner) {
|
||||
if (owner == EditorWindowPointerCaptureOwner::None ||
|
||||
m_window.hwnd == nullptr ||
|
||||
!IsWindow(m_window.hwnd)) {
|
||||
m_state->window.hwnd == nullptr ||
|
||||
!IsWindow(m_state->window.hwnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_input.pointerCaptureOwner = owner;
|
||||
if (GetCapture() != m_window.hwnd) {
|
||||
SetCapture(m_window.hwnd);
|
||||
m_state->input.pointerCaptureOwner = owner;
|
||||
if (GetCapture() != m_state->window.hwnd) {
|
||||
SetCapture(m_state->window.hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorWindow::ReleasePointerCapture(EditorWindowPointerCaptureOwner owner) {
|
||||
if (m_input.pointerCaptureOwner != owner) {
|
||||
if (m_state->input.pointerCaptureOwner != owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_input.pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
||||
if (m_window.hwnd != nullptr && GetCapture() == m_window.hwnd) {
|
||||
m_state->input.pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
||||
if (m_state->window.hwnd != nullptr && GetCapture() == m_state->window.hwnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorWindow::ForceReleasePointerCapture() {
|
||||
m_input.pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
||||
if (m_window.hwnd != nullptr && GetCapture() == m_window.hwnd) {
|
||||
m_state->input.pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
||||
if (m_state->window.hwnd != nullptr && GetCapture() == m_state->window.hwnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorWindow::ClearPointerCaptureOwner() {
|
||||
m_input.pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
||||
m_state->input.pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
||||
}
|
||||
|
||||
void EditorWindow::TryStartImmediateShellPointerCapture(LPARAM lParam) {
|
||||
if (m_window.hwnd == nullptr ||
|
||||
!IsWindow(m_window.hwnd) ||
|
||||
GetCapture() == m_window.hwnd) {
|
||||
if (m_state->window.hwnd == nullptr ||
|
||||
!IsWindow(m_state->window.hwnd) ||
|
||||
GetCapture() == m_state->window.hwnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -188,7 +189,7 @@ void EditorWindow::TryStartImmediateShellPointerCapture(LPARAM lParam) {
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam));
|
||||
if (!ShouldStartImmediateUIEditorShellPointerCapture(
|
||||
m_composition.shellRuntime.GetShellFrame(),
|
||||
m_state->composition.shellRuntime.GetShellFrame(),
|
||||
clientPoint)) {
|
||||
return;
|
||||
}
|
||||
@@ -207,16 +208,16 @@ void EditorWindow::QueuePointerEvent(
|
||||
event.position = ConvertClientPixelsToDips(
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam));
|
||||
event.modifiers = m_input.modifierTracker.ApplyPointerMessage(
|
||||
event.modifiers = m_state->input.modifierTracker.ApplyPointerMessage(
|
||||
type,
|
||||
button,
|
||||
static_cast<std::size_t>(wParam));
|
||||
m_input.pendingEvents.push_back(event);
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::QueueSyntheticPointerStateSyncEvent(
|
||||
const ::XCEngine::UI::UIInputModifiers& modifiers) {
|
||||
if (m_window.hwnd == nullptr || !IsWindow(m_window.hwnd)) {
|
||||
if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ void EditorWindow::QueueSyntheticPointerStateSyncEvent(
|
||||
if (!GetCursorPos(&screenPoint)) {
|
||||
return;
|
||||
}
|
||||
if (!ScreenToClient(m_window.hwnd, &screenPoint)) {
|
||||
if (!ScreenToClient(m_state->window.hwnd, &screenPoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -232,24 +233,24 @@ void EditorWindow::QueueSyntheticPointerStateSyncEvent(
|
||||
event.type = UIInputEventType::PointerMove;
|
||||
event.position = ConvertClientPixelsToDips(screenPoint.x, screenPoint.y);
|
||||
event.modifiers = modifiers;
|
||||
m_input.pendingEvents.push_back(event);
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::QueuePointerLeaveEvent() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerLeave;
|
||||
if (m_window.hwnd != nullptr) {
|
||||
if (m_state->window.hwnd != nullptr) {
|
||||
POINT clientPoint = {};
|
||||
GetCursorPos(&clientPoint);
|
||||
ScreenToClient(m_window.hwnd, &clientPoint);
|
||||
ScreenToClient(m_state->window.hwnd, &clientPoint);
|
||||
event.position = ConvertClientPixelsToDips(clientPoint.x, clientPoint.y);
|
||||
}
|
||||
event.modifiers = m_input.modifierTracker.GetCurrentModifiers();
|
||||
m_input.pendingEvents.push_back(event);
|
||||
event.modifiers = m_state->input.modifierTracker.GetCurrentModifiers();
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARAM lParam) {
|
||||
if (m_window.hwnd == nullptr) {
|
||||
if (m_state->window.hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,56 +258,56 @@ void EditorWindow::QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARA
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam)
|
||||
};
|
||||
ScreenToClient(m_window.hwnd, &screenPoint);
|
||||
ScreenToClient(m_state->window.hwnd, &screenPoint);
|
||||
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerWheel;
|
||||
event.position = ConvertClientPixelsToDips(screenPoint.x, screenPoint.y);
|
||||
event.wheelDelta = static_cast<float>(wheelDelta);
|
||||
event.modifiers = m_input.modifierTracker.ApplyPointerMessage(
|
||||
event.modifiers = m_state->input.modifierTracker.ApplyPointerMessage(
|
||||
UIInputEventType::PointerWheel,
|
||||
UIPointerButton::None,
|
||||
static_cast<std::size_t>(wParam));
|
||||
m_input.pendingEvents.push_back(event);
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::QueueKeyEvent(UIInputEventType type, WPARAM wParam, LPARAM lParam) {
|
||||
UIInputEvent event = {};
|
||||
event.type = type;
|
||||
event.keyCode = MapVirtualKeyToUIKeyCode(wParam);
|
||||
event.modifiers = m_input.modifierTracker.ApplyKeyMessage(type, wParam, lParam);
|
||||
event.modifiers = m_state->input.modifierTracker.ApplyKeyMessage(type, wParam, lParam);
|
||||
event.repeat = IsRepeatKeyMessage(lParam);
|
||||
m_input.pendingEvents.push_back(event);
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::QueueCharacterEvent(WPARAM wParam, LPARAM) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::Character;
|
||||
event.character = static_cast<std::uint32_t>(wParam);
|
||||
event.modifiers = m_input.modifierTracker.GetCurrentModifiers();
|
||||
m_input.pendingEvents.push_back(event);
|
||||
event.modifiers = m_state->input.modifierTracker.GetCurrentModifiers();
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::QueueWindowFocusEvent(UIInputEventType type) {
|
||||
UIInputEvent event = {};
|
||||
event.type = type;
|
||||
m_input.pendingEvents.push_back(event);
|
||||
m_state->input.pendingEvents.push_back(event);
|
||||
}
|
||||
|
||||
void EditorWindow::SyncInputModifiersFromSystemState() {
|
||||
m_input.modifierTracker.SyncFromSystemState();
|
||||
m_state->input.modifierTracker.SyncFromSystemState();
|
||||
}
|
||||
|
||||
void EditorWindow::ResetInputModifiers() {
|
||||
m_input.modifierTracker.Reset();
|
||||
m_state->input.modifierTracker.Reset();
|
||||
}
|
||||
|
||||
void EditorWindow::RequestManualScreenshot() {
|
||||
m_render.autoScreenshot.RequestCapture("manual_f12");
|
||||
m_state->render.autoScreenshot.RequestCapture("manual_f12");
|
||||
}
|
||||
|
||||
bool EditorWindow::IsPointerInsideClientArea() const {
|
||||
if (m_window.hwnd == nullptr || !IsWindow(m_window.hwnd)) {
|
||||
if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -315,26 +316,26 @@ bool EditorWindow::IsPointerInsideClientArea() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsScreenPointOverWindow(m_window.hwnd, screenPoint)) {
|
||||
if (!IsScreenPointOverWindow(m_state->window.hwnd, screenPoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const LPARAM pointParam = MAKELPARAM(
|
||||
static_cast<SHORT>(screenPoint.x),
|
||||
static_cast<SHORT>(screenPoint.y));
|
||||
return SendMessageW(m_window.hwnd, WM_NCHITTEST, 0, pointParam) == HTCLIENT;
|
||||
return SendMessageW(m_state->window.hwnd, WM_NCHITTEST, 0, pointParam) == HTCLIENT;
|
||||
}
|
||||
|
||||
LPCWSTR EditorWindow::ResolveCurrentCursorResource() const {
|
||||
const Host::BorderlessWindowResizeEdge borderlessResizeEdge =
|
||||
m_chrome.runtime.IsBorderlessResizeActive()
|
||||
? m_chrome.runtime.GetBorderlessResizeEdge()
|
||||
: m_chrome.runtime.GetHoveredBorderlessResizeEdge();
|
||||
m_state->chrome.runtime.IsBorderlessResizeActive()
|
||||
? m_state->chrome.runtime.GetBorderlessResizeEdge()
|
||||
: m_state->chrome.runtime.GetHoveredBorderlessResizeEdge();
|
||||
if (borderlessResizeEdge != Host::BorderlessWindowResizeEdge::None) {
|
||||
return Host::ResolveBorderlessWindowResizeCursor(borderlessResizeEdge);
|
||||
}
|
||||
|
||||
switch (m_composition.shellRuntime.GetHostedContentCursorKind()) {
|
||||
switch (m_state->composition.shellRuntime.GetHostedContentCursorKind()) {
|
||||
case ProjectPanel::CursorKind::ResizeEW:
|
||||
return IDC_SIZEWE;
|
||||
case ProjectPanel::CursorKind::Arrow:
|
||||
@@ -342,7 +343,7 @@ LPCWSTR EditorWindow::ResolveCurrentCursorResource() const {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (m_composition.shellRuntime.GetDockCursorKind()) {
|
||||
switch (m_state->composition.shellRuntime.GetDockCursorKind()) {
|
||||
case Widgets::UIEditorDockHostCursorKind::ResizeEW:
|
||||
return IDC_SIZEWE;
|
||||
case Widgets::UIEditorDockHostCursorKind::ResizeNS:
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "Platform/Win32/EditorWindowPointerCapture.h"
|
||||
#include "Composition/EditorShellRuntime.h"
|
||||
#include "Platform/Win32/EditorWindowPointerCapture.h"
|
||||
|
||||
#include <Platform/Win32/BorderlessWindowChrome.h>
|
||||
#include <Platform/Win32/HostRuntimeState.h>
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -63,23 +62,12 @@ struct EditorWindowChromeRuntimeState {
|
||||
Host::HostRuntimeState runtime = {};
|
||||
};
|
||||
|
||||
struct EditorWindowPanelTransferRequest {
|
||||
std::string nodeId = {};
|
||||
std::string panelId = {};
|
||||
POINT screenPoint = {};
|
||||
|
||||
bool IsValid() const {
|
||||
return !nodeId.empty() && !panelId.empty();
|
||||
}
|
||||
};
|
||||
|
||||
struct EditorWindowFrameTransferRequests {
|
||||
std::optional<EditorWindowPanelTransferRequest> beginGlobalTabDrag = {};
|
||||
std::optional<EditorWindowPanelTransferRequest> detachPanel = {};
|
||||
|
||||
bool HasPendingRequests() const {
|
||||
return beginGlobalTabDrag.has_value() || detachPanel.has_value();
|
||||
}
|
||||
struct EditorWindowState {
|
||||
EditorWindowWindowState window = {};
|
||||
EditorWindowRenderState render = {};
|
||||
EditorWindowInputState input = {};
|
||||
EditorWindowCompositionState composition = {};
|
||||
EditorWindowChromeRuntimeState chrome = {};
|
||||
};
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowConstants.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -10,13 +11,13 @@ namespace XCEngine::UI::Editor::App {
|
||||
using namespace EditorWindowInternal;
|
||||
|
||||
bool EditorWindow::UpdateBorderlessWindowChromeHover(LPARAM lParam) {
|
||||
if (m_chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
if (m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
Host::BorderlessWindowResizeEdge::None ||
|
||||
m_chrome.runtime.IsBorderlessResizeActive()) {
|
||||
m_state->chrome.runtime.IsBorderlessResizeActive()) {
|
||||
const bool changed =
|
||||
m_chrome.chromeState.hoveredTarget !=
|
||||
m_state->chrome.chromeState.hoveredTarget !=
|
||||
Host::BorderlessWindowChromeHitTarget::None;
|
||||
m_chrome.chromeState.hoveredTarget =
|
||||
m_state->chrome.chromeState.hoveredTarget =
|
||||
Host::BorderlessWindowChromeHitTarget::None;
|
||||
return changed;
|
||||
}
|
||||
@@ -29,18 +30,18 @@ bool EditorWindow::UpdateBorderlessWindowChromeHover(LPARAM lParam) {
|
||||
hitTarget == Host::BorderlessWindowChromeHitTarget::CloseButton
|
||||
? hitTarget
|
||||
: Host::BorderlessWindowChromeHitTarget::None;
|
||||
if (m_chrome.chromeState.hoveredTarget == buttonTarget) {
|
||||
if (m_state->chrome.chromeState.hoveredTarget == buttonTarget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chrome.chromeState.hoveredTarget = buttonTarget;
|
||||
m_state->chrome.chromeState.hoveredTarget = buttonTarget;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorWindow::HandleBorderlessWindowChromeButtonDown(LPARAM lParam) {
|
||||
if (m_chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
if (m_state->chrome.runtime.GetHoveredBorderlessResizeEdge() !=
|
||||
Host::BorderlessWindowResizeEdge::None ||
|
||||
m_chrome.runtime.IsBorderlessResizeActive()) {
|
||||
m_state->chrome.runtime.IsBorderlessResizeActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,23 +51,23 @@ bool EditorWindow::HandleBorderlessWindowChromeButtonDown(LPARAM lParam) {
|
||||
case Host::BorderlessWindowChromeHitTarget::MinimizeButton:
|
||||
case Host::BorderlessWindowChromeHitTarget::MaximizeRestoreButton:
|
||||
case Host::BorderlessWindowChromeHitTarget::CloseButton:
|
||||
m_chrome.chromeState.pressedTarget = hitTarget;
|
||||
m_state->chrome.chromeState.pressedTarget = hitTarget;
|
||||
AcquirePointerCapture(EditorWindowPointerCaptureOwner::BorderlessChrome);
|
||||
InvalidateHostWindow();
|
||||
return true;
|
||||
case Host::BorderlessWindowChromeHitTarget::DragRegion:
|
||||
if (m_window.hwnd != nullptr) {
|
||||
if (m_state->window.hwnd != nullptr) {
|
||||
if (IsBorderlessWindowMaximized()) {
|
||||
POINT screenPoint = {};
|
||||
if (GetCursorPos(&screenPoint)) {
|
||||
m_chrome.runtime.BeginBorderlessWindowDragRestore(screenPoint);
|
||||
m_state->chrome.runtime.BeginBorderlessWindowDragRestore(screenPoint);
|
||||
AcquirePointerCapture(EditorWindowPointerCaptureOwner::BorderlessChrome);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ForceReleasePointerCapture();
|
||||
SendMessageW(m_window.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
SendMessageW(m_state->window.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
}
|
||||
return true;
|
||||
case Host::BorderlessWindowChromeHitTarget::None:
|
||||
@@ -79,13 +80,13 @@ bool EditorWindow::HandleBorderlessWindowChromeButtonUp(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive,
|
||||
LPARAM lParam) {
|
||||
if (m_chrome.runtime.IsBorderlessWindowDragRestoreArmed()) {
|
||||
if (m_state->chrome.runtime.IsBorderlessWindowDragRestoreArmed()) {
|
||||
ClearBorderlessWindowChromeDragRestoreState();
|
||||
return true;
|
||||
}
|
||||
|
||||
const Host::BorderlessWindowChromeHitTarget pressedTarget =
|
||||
m_chrome.chromeState.pressedTarget;
|
||||
m_state->chrome.chromeState.pressedTarget;
|
||||
if (pressedTarget != Host::BorderlessWindowChromeHitTarget::MinimizeButton &&
|
||||
pressedTarget != Host::BorderlessWindowChromeHitTarget::MaximizeRestoreButton &&
|
||||
pressedTarget != Host::BorderlessWindowChromeHitTarget::CloseButton) {
|
||||
@@ -94,7 +95,7 @@ bool EditorWindow::HandleBorderlessWindowChromeButtonUp(
|
||||
|
||||
const Host::BorderlessWindowChromeHitTarget releasedTarget =
|
||||
HitTestBorderlessWindowChrome(lParam);
|
||||
m_chrome.chromeState.pressedTarget =
|
||||
m_state->chrome.chromeState.pressedTarget =
|
||||
Host::BorderlessWindowChromeHitTarget::None;
|
||||
ReleasePointerCapture(EditorWindowPointerCaptureOwner::BorderlessChrome);
|
||||
InvalidateHostWindow();
|
||||
@@ -112,7 +113,7 @@ bool EditorWindow::HandleBorderlessWindowChromeDoubleClick(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive,
|
||||
LPARAM lParam) {
|
||||
if (m_chrome.runtime.IsBorderlessWindowDragRestoreArmed()) {
|
||||
if (m_state->chrome.runtime.IsBorderlessWindowDragRestoreArmed()) {
|
||||
ClearBorderlessWindowChromeDragRestoreState();
|
||||
}
|
||||
|
||||
@@ -131,7 +132,8 @@ bool EditorWindow::HandleBorderlessWindowChromeDoubleClick(
|
||||
bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive) {
|
||||
if (!m_chrome.runtime.IsBorderlessWindowDragRestoreArmed() || m_window.hwnd == nullptr) {
|
||||
if (!m_state->chrome.runtime.IsBorderlessWindowDragRestoreArmed() ||
|
||||
m_state->window.hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -141,7 +143,7 @@ bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove(
|
||||
}
|
||||
|
||||
const POINT initialScreenPoint =
|
||||
m_chrome.runtime.GetBorderlessWindowDragRestoreInitialScreenPoint();
|
||||
m_state->chrome.runtime.GetBorderlessWindowDragRestoreInitialScreenPoint();
|
||||
const int dragThresholdX = (std::max)(GetSystemMetrics(SM_CXDRAG), 1);
|
||||
const int dragThresholdY = (std::max)(GetSystemMetrics(SM_CYDRAG), 1);
|
||||
const LONG deltaX = currentScreenPoint.x - initialScreenPoint.x;
|
||||
@@ -154,7 +156,7 @@ bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove(
|
||||
RECT restoreRect = {};
|
||||
RECT currentRect = {};
|
||||
RECT workAreaRect = {};
|
||||
if (!m_chrome.runtime.TryGetBorderlessWindowRestoreRect(restoreRect) ||
|
||||
if (!m_state->chrome.runtime.TryGetBorderlessWindowRestoreRect(restoreRect) ||
|
||||
!QueryCurrentWindowRect(currentRect) ||
|
||||
!QueryBorderlessWindowWorkAreaRect(workAreaRect)) {
|
||||
ClearBorderlessWindowChromeDragRestoreState();
|
||||
@@ -193,34 +195,34 @@ bool EditorWindow::HandleBorderlessWindowChromeDragRestorePointerMove(
|
||||
newTop + restoreHeight
|
||||
};
|
||||
|
||||
m_chrome.runtime.SetBorderlessWindowMaximized(false);
|
||||
m_state->chrome.runtime.SetBorderlessWindowMaximized(false);
|
||||
ApplyPredictedWindowRectTransition(
|
||||
editorContext,
|
||||
globalTabDragActive,
|
||||
targetRect);
|
||||
ClearBorderlessWindowChromeDragRestoreState();
|
||||
SendMessageW(m_window.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
SendMessageW(m_state->window.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditorWindow::ClearBorderlessWindowChromeDragRestoreState() {
|
||||
if (!m_chrome.runtime.IsBorderlessWindowDragRestoreArmed()) {
|
||||
if (!m_state->chrome.runtime.IsBorderlessWindowDragRestoreArmed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_chrome.runtime.EndBorderlessWindowDragRestore();
|
||||
m_state->chrome.runtime.EndBorderlessWindowDragRestore();
|
||||
ReleasePointerCapture(EditorWindowPointerCaptureOwner::BorderlessChrome);
|
||||
}
|
||||
|
||||
void EditorWindow::ClearBorderlessWindowChromeState() {
|
||||
if (m_chrome.chromeState.hoveredTarget ==
|
||||
if (m_state->chrome.chromeState.hoveredTarget ==
|
||||
Host::BorderlessWindowChromeHitTarget::None &&
|
||||
m_chrome.chromeState.pressedTarget ==
|
||||
m_state->chrome.chromeState.pressedTarget ==
|
||||
Host::BorderlessWindowChromeHitTarget::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_chrome.chromeState = {};
|
||||
m_state->chrome.chromeState = {};
|
||||
InvalidateHostWindow();
|
||||
}
|
||||
|
||||
@@ -228,19 +230,19 @@ void EditorWindow::ExecuteBorderlessWindowChromeAction(
|
||||
EditorContext& editorContext,
|
||||
bool globalTabDragActive,
|
||||
Host::BorderlessWindowChromeHitTarget target) {
|
||||
if (m_window.hwnd == nullptr) {
|
||||
if (m_state->window.hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case Host::BorderlessWindowChromeHitTarget::MinimizeButton:
|
||||
ShowWindow(m_window.hwnd, SW_MINIMIZE);
|
||||
ShowWindow(m_state->window.hwnd, SW_MINIMIZE);
|
||||
break;
|
||||
case Host::BorderlessWindowChromeHitTarget::MaximizeRestoreButton:
|
||||
ToggleBorderlessWindowMaximizeRestore(editorContext, globalTabDragActive);
|
||||
break;
|
||||
case Host::BorderlessWindowChromeHitTarget::CloseButton:
|
||||
PostMessageW(m_window.hwnd, WM_CLOSE, 0, 0);
|
||||
PostMessageW(m_state->window.hwnd, WM_CLOSE, 0, 0);
|
||||
break;
|
||||
case Host::BorderlessWindowChromeHitTarget::DragRegion:
|
||||
case Host::BorderlessWindowChromeHitTarget::None:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowConstants.h"
|
||||
#include "Platform/Win32/EditorWindowInternalState.h"
|
||||
#include "Platform/Win32/EditorWindowStyle.h"
|
||||
|
||||
#include <XCEditor/Foundation/UIEditorTheme.h>
|
||||
@@ -100,17 +101,18 @@ UIRect BuildDetachedTitleLogoRect(const Host::BorderlessWindowChromeLayout& layo
|
||||
} // namespace
|
||||
|
||||
bool EditorWindow::ShouldUseDetachedTitleBarTabStrip() const {
|
||||
return !m_window.primary && HasSingleVisibleRootTab(m_composition.workspaceController);
|
||||
return !m_state->window.primary &&
|
||||
HasSingleVisibleRootTab(m_state->composition.workspaceController);
|
||||
}
|
||||
|
||||
Host::BorderlessWindowChromeHitTarget EditorWindow::HitTestBorderlessWindowChrome(
|
||||
LPARAM lParam) const {
|
||||
if (!IsBorderlessWindowEnabled() || m_window.hwnd == nullptr) {
|
||||
if (!IsBorderlessWindowEnabled() || m_state->window.hwnd == nullptr) {
|
||||
return Host::BorderlessWindowChromeHitTarget::None;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
if (!GetClientRect(m_window.hwnd, &clientRect)) {
|
||||
if (!GetClientRect(m_state->window.hwnd, &clientRect)) {
|
||||
return Host::BorderlessWindowChromeHitTarget::None;
|
||||
}
|
||||
|
||||
@@ -156,11 +158,11 @@ void EditorWindow::AppendBorderlessWindowChrome(
|
||||
1.0f);
|
||||
}
|
||||
|
||||
if (!m_window.primary) {
|
||||
if (m_render.titleBarLogoIcon.IsValid()) {
|
||||
if (!m_state->window.primary) {
|
||||
if (m_state->render.titleBarLogoIcon.IsValid()) {
|
||||
drawList.AddImage(
|
||||
BuildDetachedTitleLogoRect(layout),
|
||||
m_render.titleBarLogoIcon,
|
||||
m_state->render.titleBarLogoIcon,
|
||||
UIColor(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
} else {
|
||||
@@ -168,19 +170,21 @@ void EditorWindow::AppendBorderlessWindowChrome(
|
||||
const float iconY =
|
||||
layout.titleBarRect.y +
|
||||
(std::max)(0.0f, (layout.titleBarRect.height - kTitleBarLogoExtent) * 0.5f);
|
||||
if (m_render.titleBarLogoIcon.IsValid()) {
|
||||
if (m_state->render.titleBarLogoIcon.IsValid()) {
|
||||
drawList.AddImage(
|
||||
UIRect(iconX, iconY, kTitleBarLogoExtent, kTitleBarLogoExtent),
|
||||
m_render.titleBarLogoIcon,
|
||||
m_state->render.titleBarLogoIcon,
|
||||
UIColor(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
const std::string& titleText =
|
||||
m_window.titleText.empty() ? std::string("XCEngine Editor") : m_window.titleText;
|
||||
m_state->window.titleText.empty()
|
||||
? std::string("XCEngine Editor")
|
||||
: m_state->window.titleText;
|
||||
drawList.AddText(
|
||||
UIPoint(
|
||||
iconX +
|
||||
(m_render.titleBarLogoIcon.IsValid()
|
||||
(m_state->render.titleBarLogoIcon.IsValid()
|
||||
? (kTitleBarLogoExtent + kTitleBarLogoTextGap)
|
||||
: 4.0f),
|
||||
layout.titleBarRect.y +
|
||||
@@ -195,7 +199,7 @@ void EditorWindow::AppendBorderlessWindowChrome(
|
||||
Host::AppendBorderlessWindowChrome(
|
||||
drawList,
|
||||
layout,
|
||||
m_chrome.chromeState,
|
||||
m_state->chrome.chromeState,
|
||||
IsBorderlessWindowMaximized());
|
||||
}
|
||||
|
||||
|
||||
33
new_editor/app/Platform/Win32/EditorWindowTransferRequests.h
Normal file
33
new_editor/app/Platform/Win32/EditorWindowTransferRequests.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
struct EditorWindowPanelTransferRequest {
|
||||
std::string nodeId = {};
|
||||
std::string panelId = {};
|
||||
POINT screenPoint = {};
|
||||
|
||||
bool IsValid() const {
|
||||
return !nodeId.empty() && !panelId.empty();
|
||||
}
|
||||
};
|
||||
|
||||
struct EditorWindowFrameTransferRequests {
|
||||
std::optional<EditorWindowPanelTransferRequest> beginGlobalTabDrag = {};
|
||||
std::optional<EditorWindowPanelTransferRequest> detachPanel = {};
|
||||
|
||||
bool HasPendingRequests() const {
|
||||
return beginGlobalTabDrag.has_value() || detachPanel.has_value();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
#include "Platform/Win32/EditorWindowManager.h"
|
||||
|
||||
#include <XCEditor/Workspace/UIEditorWindowWorkspaceController.h>
|
||||
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
|
||||
|
||||
namespace XCEngine::UI::Editor::App::Internal {
|
||||
|
||||
class EditorWindowHostRuntime final {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
|
||||
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
|
||||
#include <XCEditor/Workspace/UIEditorWindowWorkspaceController.h>
|
||||
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "WindowMessageDispatcher.h"
|
||||
|
||||
#include "Composition/EditorShellRuntime.h"
|
||||
#include "Platform/Win32/BorderlessWindowChrome.h"
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "Platform/Win32/EditorWindowPointerCapture.h"
|
||||
#include "WindowMessageHost.h"
|
||||
|
||||
Reference in New Issue
Block a user