fix(new_editor/docking): restore cross-window drop preview

This commit is contained in:
2026-04-15 13:22:58 +08:00
parent 07516b8c2c
commit 7e21e3887e
7 changed files with 91 additions and 1 deletions

View File

@@ -1,5 +1,6 @@
#include "EditorWindowManager.h"
#include "Platform/Win32/EditorWindowManagerCrossWindowDropSupport.h"
#include "State/EditorContext.h"
#include "EditorWindow.h"
@@ -10,6 +11,9 @@ namespace XCEngine::UI::Editor::App {
namespace {
using EditorWindowManagerCrossWindowDropSupport::CrossWindowDockDropTarget;
using EditorWindowManagerCrossWindowDropSupport::TryResolveCrossWindowDockDropTarget;
constexpr LONG kFallbackDragHotspotX = 40;
constexpr LONG kFallbackDragHotspotY = 12;
@@ -134,11 +138,67 @@ void EditorWindowManager::UpdateGlobalTabDragOwnerWindowPosition() {
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
void EditorWindowManager::ClearGlobalTabDragDropPreview() {
if (m_globalTabDragSession.previewWindowId.empty()) {
return;
}
if (EditorWindow* previewWindow = FindWindow(m_globalTabDragSession.previewWindowId);
previewWindow != nullptr) {
previewWindow->ClearExternalDockHostDropPreview();
previewWindow->InvalidateHostWindow();
}
m_globalTabDragSession.previewWindowId.clear();
}
void EditorWindowManager::UpdateGlobalTabDragDropPreview() {
if (!m_globalTabDragSession.active) {
return;
}
EditorWindow* targetWindow = FindTopmostWindowAtScreenPoint(
m_globalTabDragSession.screenPoint,
m_globalTabDragSession.panelWindowId);
if (targetWindow == nullptr || targetWindow->GetHwnd() == nullptr) {
ClearGlobalTabDragDropPreview();
return;
}
const ::XCEngine::UI::UIPoint targetPoint =
targetWindow->ConvertScreenPixelsToClientDips(m_globalTabDragSession.screenPoint);
const Widgets::UIEditorDockHostLayout& targetLayout =
targetWindow->GetShellFrame().workspaceInteractionFrame.dockHostFrame.layout;
CrossWindowDockDropTarget dropTarget = {};
if (!TryResolveCrossWindowDockDropTarget(targetLayout, targetPoint, dropTarget) ||
!dropTarget.valid) {
ClearGlobalTabDragDropPreview();
return;
}
if (!m_globalTabDragSession.previewWindowId.empty() &&
m_globalTabDragSession.previewWindowId != targetWindow->GetWindowId()) {
ClearGlobalTabDragDropPreview();
}
Widgets::UIEditorDockHostDropPreviewState preview = {};
preview.visible = true;
preview.sourceNodeId = m_globalTabDragSession.sourceNodeId;
preview.sourcePanelId = m_globalTabDragSession.panelId;
preview.targetNodeId = dropTarget.nodeId;
preview.placement = dropTarget.placement;
preview.insertionIndex = dropTarget.insertionIndex;
targetWindow->SetExternalDockHostDropPreview(preview);
targetWindow->InvalidateHostWindow();
m_globalTabDragSession.previewWindowId = std::string(targetWindow->GetWindowId());
}
void EditorWindowManager::EndGlobalTabDragSession() {
if (!m_globalTabDragSession.active) {
return;
}
ClearGlobalTabDragDropPreview();
if (EditorWindow* ownerWindow = FindWindow(m_globalTabDragSession.panelWindowId);
ownerWindow != nullptr) {
if (GetCapture() == ownerWindow->GetHwnd()) {
@@ -164,6 +224,7 @@ bool EditorWindowManager::HandleGlobalTabDragPointerMove(HWND hwnd) {
if (GetCursorPos(&screenPoint)) {
m_globalTabDragSession.screenPoint = screenPoint;
UpdateGlobalTabDragOwnerWindowPosition();
UpdateGlobalTabDragDropPreview();
}
return true;
}