#pragma once #ifndef NOMINMAX #define NOMINMAX #endif #include "Platform/Win32/EditorWindowPointerCapture.h" #include "Platform/Win32/EditorWindowTransferRequests.h" #include #include #include #include #include #include #include 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; class EditorWindowWorkspaceCoordinator; } } // namespace XCEngine::UI::Editor::App namespace XCEngine::UI::Editor::Host { class WindowMessageDispatcher; } namespace XCEngine::UI::Editor::App { class EditorWindow { public: EditorWindow( std::string windowId, std::wstring title, bool primary, UIEditorWorkspaceController workspaceController); ~EditorWindow(); EditorWindow(const EditorWindow&) = delete; EditorWindow& operator=(const EditorWindow&) = delete; EditorWindow(EditorWindow&&) = delete; EditorWindow& operator=(EditorWindow&&) = delete; std::string_view GetWindowId() const; HWND GetHwnd() const; bool HasHwnd() const; bool IsPrimary() const; bool IsClosing() const; const std::wstring& GetTitle() const; const UIEditorWorkspaceController& GetWorkspaceController() const; UIEditorWorkspaceController& GetWorkspaceController(); const UIEditorShellInteractionFrame& GetShellFrame() const; ::XCEngine::UI::UIPoint ConvertScreenPixelsToClientDips(const POINT& screenPoint) const; private: friend class Host::WindowMessageDispatcher; friend class Internal::EditorWindowHostRuntime; friend class Internal::EditorWindowWorkspaceCoordinator; bool IsRenderReady() const; bool IsTrackingMouseLeave() const; bool HasHoveredBorderlessResizeEdge() const; const EditorShellRuntime& GetShellRuntime() const; EditorShellRuntime& GetShellRuntime(); const UIEditorShellInteractionState& GetShellInteractionState() const; void InvalidateHostWindow() const; void SetExternalDockHostDropPreview( const Widgets::UIEditorDockHostDropPreviewState& preview); void ClearExternalDockHostDropPreview(); void AttachHwnd(HWND hwnd); void MarkDestroyed(); void MarkClosing(); void ClearClosing(); void SetTrackingMouseLeave(bool trackingMouseLeave); void SetTitle(std::wstring title); void ReplaceWorkspaceController(UIEditorWorkspaceController workspaceController); bool Initialize( const std::filesystem::path& repoRoot, EditorContext& editorContext, const std::filesystem::path& captureRoot, bool autoCaptureOnStartup); void Shutdown(); void ResetInteractionState(); EditorWindowFrameTransferRequests RenderFrame( EditorContext& editorContext, bool globalTabDragActive); EditorWindowFrameTransferRequests OnPaintMessage( EditorContext& editorContext, bool globalTabDragActive); void OnResize(UINT width, UINT height); void OnEnterSizeMove(); void OnExitSizeMove(); void OnDpiChanged(UINT dpi, const RECT& suggestedRect); bool IsBorderlessWindowEnabled() const; bool IsBorderlessWindowMaximized() const; bool HandleBorderlessWindowSystemCommand( EditorContext& editorContext, bool globalTabDragActive, WPARAM wParam); bool HandleBorderlessWindowGetMinMaxInfo(LPARAM lParam) const; LRESULT HandleBorderlessWindowNcCalcSize(WPARAM wParam, LPARAM lParam) const; bool ApplyCurrentCursor() const; bool UpdateBorderlessWindowResizeHover(LPARAM lParam); bool HandleBorderlessWindowResizeButtonDown(LPARAM lParam); bool HandleBorderlessWindowResizeButtonUp(); bool HandleBorderlessWindowResizePointerMove( EditorContext& editorContext, bool globalTabDragActive); void ClearBorderlessWindowResizeState(); void ForceClearBorderlessWindowResizeState(); Host::BorderlessWindowChromeHitTarget HitTestBorderlessWindowChrome(LPARAM lParam) const; bool UpdateBorderlessWindowChromeHover(LPARAM lParam); bool HandleBorderlessWindowChromeButtonDown(LPARAM lParam); bool HandleBorderlessWindowChromeButtonUp( EditorContext& editorContext, bool globalTabDragActive, LPARAM lParam); bool HandleBorderlessWindowChromeDoubleClick( EditorContext& editorContext, bool globalTabDragActive, LPARAM lParam); bool HandleBorderlessWindowChromeDragRestorePointerMove( EditorContext& editorContext, bool globalTabDragActive); void ClearBorderlessWindowChromeDragRestoreState(); void ClearBorderlessWindowChromeState(); bool HasInteractiveCaptureState() const; EditorWindowPointerCaptureOwner GetPointerCaptureOwner() const; bool OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const; void AcquirePointerCapture(EditorWindowPointerCaptureOwner owner); void ReleasePointerCapture(EditorWindowPointerCaptureOwner owner); void ForceReleasePointerCapture(); void ClearPointerCaptureOwner(); void TryStartImmediateShellPointerCapture(LPARAM lParam); void QueuePointerEvent( ::XCEngine::UI::UIInputEventType type, ::XCEngine::UI::UIPointerButton button, WPARAM wParam, LPARAM lParam); void QueueSyntheticPointerStateSyncEvent( const ::XCEngine::UI::UIInputModifiers& modifiers); void QueuePointerLeaveEvent(); void QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARAM lParam); void QueueKeyEvent(::XCEngine::UI::UIInputEventType type, WPARAM wParam, LPARAM lParam); void QueueCharacterEvent(WPARAM wParam, LPARAM lParam); void QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType type); void SyncInputModifiersFromSystemState(); void SyncShellCapturedPointerButtonsFromSystemState(); void ResetInputModifiers(); void RequestManualScreenshot(); bool ApplyWindowResize(UINT width, UINT height); bool QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const; bool ResolveRenderClientPixelSize(UINT& outWidth, UINT& outHeight) const; ::XCEngine::UI::UIRect ResolveWorkspaceBounds( float clientWidthDips, float clientHeightDips) const; EditorWindowFrameTransferRequests RenderRuntimeFrame( EditorContext& editorContext, bool globalTabDragActive, const ::XCEngine::UI::UIRect& workspaceBounds, ::XCEngine::UI::UIDrawList& drawList); void RenderInvalidFrame( EditorContext& editorContext, ::XCEngine::UI::UIDrawList& drawList) const; void LogFrameInteractionTrace( EditorContext& editorContext, const std::vector<::XCEngine::UI::UIInputEvent>& frameEvents, const UIEditorShellInteractionFrame& shellFrame) const; EditorWindowFrameTransferRequests BuildShellTransferRequests( bool globalTabDragActive, const UIEditorDockHostInteractionState& dockHostInteractionState, const UIEditorShellInteractionFrame& shellFrame) const; bool IsPointerInsideClientArea() const; LPCWSTR ResolveCurrentCursorResource() const; float GetDpiScale() const; float PixelsToDips(float pixels) const; ::XCEngine::UI::UIPoint ConvertClientPixelsToDips(LONG x, LONG y) const; std::string BuildCaptureStatusText() const; void ApplyHostCaptureRequests(const UIEditorShellInteractionResult& result); void ApplyHostedContentCaptureRequests(); std::string DescribeInputEvents( const std::vector<::XCEngine::UI::UIInputEvent>& events) const; Host::BorderlessWindowResizeEdge HitTestBorderlessWindowResizeEdge(LPARAM lParam) const; void ApplyBorderlessWindowResizeCursorHoverPriority(); Host::BorderlessWindowChromeLayout ResolveBorderlessWindowChromeLayout( float clientWidthDips) const; bool QueryCurrentWindowRect(RECT& outRect) const; bool QueryBorderlessWindowWorkAreaRect(RECT& outRect) const; bool ApplyPredictedWindowRectTransition( EditorContext& editorContext, bool globalTabDragActive, const RECT& targetRect); bool ShouldUseDetachedTitleBarTabStrip() const; void ToggleBorderlessWindowMaximizeRestore( EditorContext& editorContext, bool globalTabDragActive); void AppendBorderlessWindowChrome( ::XCEngine::UI::UIDrawList& drawList, float clientWidthDips) const; void ExecuteBorderlessWindowChromeAction( EditorContext& editorContext, bool globalTabDragActive, Host::BorderlessWindowChromeHitTarget target); void UpdateCachedTitleText(); static bool IsVerboseRuntimeTraceEnabled(); std::unique_ptr m_state = {}; }; } // namespace XCEngine::UI::Editor::App