#include "EditorWindowManager.h" #include "State/EditorContext.h" #include "EditorWindow.h" namespace XCEngine::UI::Editor::App { bool EditorWindowManager::IsGlobalTabDragActive() const { return m_globalTabDragSession.active; } bool EditorWindowManager::OwnsActiveGlobalTabDrag(std::string_view windowId) const { return m_globalTabDragSession.active && m_globalTabDragSession.panelWindowId == windowId; } void EditorWindowManager::BeginGlobalTabDragSession( std::string_view panelWindowId, std::string_view sourceNodeId, std::string_view panelId, const POINT& screenPoint) { m_globalTabDragSession.active = true; m_globalTabDragSession.panelWindowId = std::string(panelWindowId); m_globalTabDragSession.sourceNodeId = std::string(sourceNodeId); m_globalTabDragSession.panelId = std::string(panelId); m_globalTabDragSession.screenPoint = screenPoint; } void EditorWindowManager::EndGlobalTabDragSession() { if (!m_globalTabDragSession.active) { return; } if (EditorWindow* ownerWindow = FindWindow(m_globalTabDragSession.panelWindowId); ownerWindow != nullptr) { if (GetCapture() == ownerWindow->GetHwnd()) { ReleaseCapture(); } ownerWindow->ResetInteractionState(); } m_globalTabDragSession = {}; } bool EditorWindowManager::HandleGlobalTabDragPointerMove(HWND hwnd) { if (!m_globalTabDragSession.active) { return false; } const EditorWindow* ownerWindow = FindWindow(m_globalTabDragSession.panelWindowId); if (ownerWindow == nullptr || ownerWindow->GetHwnd() != hwnd) { return false; } POINT screenPoint = {}; if (GetCursorPos(&screenPoint)) { m_globalTabDragSession.screenPoint = screenPoint; } return true; } void EditorWindowManager::ProcessPendingGlobalTabDragStarts() { if (m_globalTabDragSession.active) { return; } for (const std::unique_ptr& window : m_windows) { if (window == nullptr || window->GetHwnd() == nullptr) { continue; } if (TryStartGlobalTabDrag(*window)) { return; } } } bool EditorWindowManager::TryStartGlobalTabDrag(EditorWindow& sourceWindow) { const std::optional pending = sourceWindow.ConsumePendingTabDragStart(); if (!pending.has_value()) { return false; } if (sourceWindow.IsPrimary()) { UIEditorWindowWorkspaceController windowWorkspaceController = BuildLiveWindowWorkspaceController(sourceWindow.GetWindowId()); const UIEditorWindowWorkspaceOperationResult result = windowWorkspaceController.DetachPanelToNewWindow( sourceWindow.GetWindowId(), pending->nodeId, pending->panelId); if (result.status != UIEditorWindowWorkspaceOperationStatus::Changed) { LogRuntimeTrace( "drag", "failed to start global tab drag from primary window: " + result.message); return false; } if (!SynchronizeWindowsFromController( windowWorkspaceController, result.targetWindowId, pending->screenPoint)) { LogRuntimeTrace("drag", "failed to synchronize detached drag window state"); return false; } EditorWindow* detachedWindow = FindWindow(result.targetWindowId); if (detachedWindow == nullptr || detachedWindow->GetHwnd() == nullptr) { LogRuntimeTrace("drag", "detached drag window was not created."); return false; } BeginGlobalTabDragSession( detachedWindow->GetWindowId(), detachedWindow->GetWorkspaceController().GetWorkspace().root.nodeId, pending->panelId, pending->screenPoint); SetCapture(detachedWindow->GetHwnd()); SetForegroundWindow(detachedWindow->GetHwnd()); LogRuntimeTrace( "drag", "started global tab drag by detaching panel '" + pending->panelId + "' into window '" + std::string(detachedWindow->GetWindowId()) + "'"); return true; } sourceWindow.ResetInteractionState(); BeginGlobalTabDragSession( sourceWindow.GetWindowId(), pending->nodeId, pending->panelId, pending->screenPoint); if (sourceWindow.GetHwnd() != nullptr) { SetCapture(sourceWindow.GetHwnd()); } LogRuntimeTrace( "drag", "started global tab drag from detached window '" + std::string(sourceWindow.GetWindowId()) + "' panel '" + pending->panelId + "'"); return true; } } // namespace XCEngine::UI::Editor::App