2026-04-15 08:24:06 +08:00
|
|
|
#include "EditorWindowManager.h"
|
|
|
|
|
|
2026-04-15 08:56:57 +08:00
|
|
|
#include "Platform/Win32/EditorWindowManagerCrossWindowDropSupport.h"
|
2026-04-15 08:24:06 +08:00
|
|
|
#include "State/EditorContext.h"
|
|
|
|
|
#include "EditorWindow.h"
|
|
|
|
|
|
|
|
|
|
namespace XCEngine::UI::Editor::App {
|
|
|
|
|
|
2026-04-15 08:56:57 +08:00
|
|
|
using EditorWindowManagerCrossWindowDropSupport::CrossWindowDockDropTarget;
|
|
|
|
|
using EditorWindowManagerCrossWindowDropSupport::TryResolveCrossWindowDockDropTarget;
|
2026-04-15 08:24:06 +08:00
|
|
|
using ::XCEngine::UI::UIPoint;
|
|
|
|
|
|
|
|
|
|
bool EditorWindowManager::HandleGlobalTabDragPointerButtonUp(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 = m_globalTabDragSession.screenPoint;
|
|
|
|
|
GetCursorPos(&screenPoint);
|
|
|
|
|
|
|
|
|
|
const std::string panelWindowId = m_globalTabDragSession.panelWindowId;
|
|
|
|
|
const std::string sourceNodeId = m_globalTabDragSession.sourceNodeId;
|
|
|
|
|
const std::string panelId = m_globalTabDragSession.panelId;
|
|
|
|
|
EndGlobalTabDragSession();
|
|
|
|
|
|
|
|
|
|
EditorWindow* targetWindow = FindTopmostWindowAtScreenPoint(screenPoint, panelWindowId);
|
|
|
|
|
if (targetWindow == nullptr || targetWindow->GetHwnd() == nullptr) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const UIPoint targetPoint =
|
|
|
|
|
targetWindow->ConvertScreenPixelsToClientDips(screenPoint);
|
|
|
|
|
const Widgets::UIEditorDockHostLayout& targetLayout =
|
|
|
|
|
targetWindow->GetShellFrame()
|
|
|
|
|
.workspaceInteractionFrame
|
|
|
|
|
.dockHostFrame
|
|
|
|
|
.layout;
|
|
|
|
|
CrossWindowDockDropTarget dropTarget = {};
|
|
|
|
|
if (!TryResolveCrossWindowDockDropTarget(targetLayout, targetPoint, dropTarget)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UIEditorWindowWorkspaceController windowWorkspaceController =
|
|
|
|
|
BuildLiveWindowWorkspaceController(targetWindow->GetWindowId());
|
|
|
|
|
const UIEditorWindowWorkspaceOperationResult result =
|
|
|
|
|
dropTarget.placement == UIEditorWorkspaceDockPlacement::Center
|
|
|
|
|
? windowWorkspaceController.MovePanelToStack(
|
|
|
|
|
panelWindowId,
|
|
|
|
|
sourceNodeId,
|
|
|
|
|
panelId,
|
|
|
|
|
targetWindow->GetWindowId(),
|
|
|
|
|
dropTarget.nodeId,
|
|
|
|
|
dropTarget.insertionIndex)
|
|
|
|
|
: windowWorkspaceController.DockPanelRelative(
|
|
|
|
|
panelWindowId,
|
|
|
|
|
sourceNodeId,
|
|
|
|
|
panelId,
|
|
|
|
|
targetWindow->GetWindowId(),
|
|
|
|
|
dropTarget.nodeId,
|
|
|
|
|
dropTarget.placement);
|
|
|
|
|
if (result.status != UIEditorWindowWorkspaceOperationStatus::Changed) {
|
|
|
|
|
LogRuntimeTrace("drag", "cross-window drop rejected: " + result.message);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!SynchronizeWindowsFromController(
|
|
|
|
|
windowWorkspaceController,
|
|
|
|
|
{},
|
|
|
|
|
screenPoint)) {
|
|
|
|
|
LogRuntimeTrace("drag", "failed to synchronize windows after cross-window drop");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (targetWindow->GetHwnd() != nullptr) {
|
|
|
|
|
SetForegroundWindow(targetWindow->GetHwnd());
|
|
|
|
|
}
|
|
|
|
|
LogRuntimeTrace(
|
|
|
|
|
"drag",
|
|
|
|
|
"committed cross-window drop panel '" + panelId +
|
|
|
|
|
"' into window '" + std::string(targetWindow->GetWindowId()) + "'");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace XCEngine::UI::Editor::App
|