From 7e21e3887e0b5ccda68770e69cff8da6c5e82f5a Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 15 Apr 2026 13:22:58 +0800 Subject: [PATCH] fix(new_editor/docking): restore cross-window drop preview --- .../app/Composition/EditorShellRuntime.cpp | 11 ++++ .../app/Composition/EditorShellRuntime.h | 3 + new_editor/app/Platform/Win32/EditorWindow.h | 3 + .../Platform/Win32/EditorWindowLifecycle.cpp | 9 +++ .../app/Platform/Win32/EditorWindowManager.h | 3 + ...ditorWindowManagerCrossWindowDropSupport.h | 2 +- .../Win32/EditorWindowManagerTabDrag.cpp | 61 +++++++++++++++++++ 7 files changed, 91 insertions(+), 1 deletion(-) diff --git a/new_editor/app/Composition/EditorShellRuntime.cpp b/new_editor/app/Composition/EditorShellRuntime.cpp index 8b79df9f..bc4a4fc9 100644 --- a/new_editor/app/Composition/EditorShellRuntime.cpp +++ b/new_editor/app/Composition/EditorShellRuntime.cpp @@ -65,6 +65,17 @@ const std::string& EditorShellRuntime::GetBuiltInIconError() const { return m_builtInIcons.GetLastError(); } +void EditorShellRuntime::SetExternalDockHostDropPreview( + const Widgets::UIEditorDockHostDropPreviewState& preview) { + m_shellInteractionState.workspaceInteractionState.dockHostInteractionState + .dockHostState.dropPreview = preview; +} + +void EditorShellRuntime::ClearExternalDockHostDropPreview() { + m_shellInteractionState.workspaceInteractionState.dockHostInteractionState + .dockHostState.dropPreview = {}; +} + ProjectPanel::CursorKind EditorShellRuntime::GetHostedContentCursorKind() const { return m_projectPanel.GetCursorKind(); } diff --git a/new_editor/app/Composition/EditorShellRuntime.h b/new_editor/app/Composition/EditorShellRuntime.h index 469893cb..766f1fb5 100644 --- a/new_editor/app/Composition/EditorShellRuntime.h +++ b/new_editor/app/Composition/EditorShellRuntime.h @@ -53,6 +53,9 @@ public: const std::vector& GetHierarchyPanelEvents() const; const std::vector& GetProjectPanelEvents() const; const std::string& GetBuiltInIconError() const; + void SetExternalDockHostDropPreview( + const Widgets::UIEditorDockHostDropPreviewState& preview); + void ClearExternalDockHostDropPreview(); ProjectPanel::CursorKind GetHostedContentCursorKind() const; Widgets::UIEditorDockHostCursorKind GetDockCursorKind() const; diff --git a/new_editor/app/Platform/Win32/EditorWindow.h b/new_editor/app/Platform/Win32/EditorWindow.h index e42b57f4..4d461dba 100644 --- a/new_editor/app/Platform/Win32/EditorWindow.h +++ b/new_editor/app/Platform/Win32/EditorWindow.h @@ -60,6 +60,9 @@ public: const UIEditorShellInteractionState& GetShellInteractionState() const; ::XCEngine::UI::UIPoint ConvertScreenPixelsToClientDips(const POINT& screenPoint) const; void InvalidateHostWindow() const; + void SetExternalDockHostDropPreview( + const Widgets::UIEditorDockHostDropPreviewState& preview); + void ClearExternalDockHostDropPreview(); void AttachHwnd(HWND hwnd); void MarkDestroyed(); diff --git a/new_editor/app/Platform/Win32/EditorWindowLifecycle.cpp b/new_editor/app/Platform/Win32/EditorWindowLifecycle.cpp index cd0e744f..0e0a2635 100644 --- a/new_editor/app/Platform/Win32/EditorWindowLifecycle.cpp +++ b/new_editor/app/Platform/Win32/EditorWindowLifecycle.cpp @@ -77,6 +77,15 @@ const UIEditorShellInteractionState& EditorWindow::GetShellInteractionState() co return m_composition.shellRuntime.GetShellInteractionState(); } +void EditorWindow::SetExternalDockHostDropPreview( + const Widgets::UIEditorDockHostDropPreviewState& preview) { + m_composition.shellRuntime.SetExternalDockHostDropPreview(preview); +} + +void EditorWindow::ClearExternalDockHostDropPreview() { + m_composition.shellRuntime.ClearExternalDockHostDropPreview(); +} + void EditorWindow::AttachHwnd(HWND hwnd) { m_window.hwnd = hwnd; } diff --git a/new_editor/app/Platform/Win32/EditorWindowManager.h b/new_editor/app/Platform/Win32/EditorWindowManager.h index 6b34b8d9..f87cbc8b 100644 --- a/new_editor/app/Platform/Win32/EditorWindowManager.h +++ b/new_editor/app/Platform/Win32/EditorWindowManager.h @@ -87,6 +87,7 @@ private: std::string panelWindowId = {}; std::string sourceNodeId = {}; std::string panelId = {}; + std::string previewWindowId = {}; POINT screenPoint = {}; POINT dragHotspot = {}; }; @@ -121,6 +122,8 @@ private: std::string_view panelId, const POINT& screenPoint, POINT& outDragHotspot) const; + void ClearGlobalTabDragDropPreview(); + void UpdateGlobalTabDragDropPreview(); void UpdateGlobalTabDragOwnerWindowPosition(); EditorWindow* FindTopmostWindowAtScreenPoint( const POINT& screenPoint, diff --git a/new_editor/app/Platform/Win32/EditorWindowManagerCrossWindowDropSupport.h b/new_editor/app/Platform/Win32/EditorWindowManagerCrossWindowDropSupport.h index 1e607f8e..77b47d88 100644 --- a/new_editor/app/Platform/Win32/EditorWindowManagerCrossWindowDropSupport.h +++ b/new_editor/app/Platform/Win32/EditorWindowManagerCrossWindowDropSupport.h @@ -19,7 +19,7 @@ struct CrossWindowDockDropTarget { std::size_t insertionIndex = Widgets::UIEditorTabStripInvalidIndex; }; -bool TryResolveCrossWindowDockDropTarget( +inline bool TryResolveCrossWindowDockDropTarget( const Widgets::UIEditorDockHostLayout& layout, const ::XCEngine::UI::UIPoint& point, CrossWindowDockDropTarget& outTarget) { diff --git a/new_editor/app/Platform/Win32/EditorWindowManagerTabDrag.cpp b/new_editor/app/Platform/Win32/EditorWindowManagerTabDrag.cpp index 3765ba08..90288bf0 100644 --- a/new_editor/app/Platform/Win32/EditorWindowManagerTabDrag.cpp +++ b/new_editor/app/Platform/Win32/EditorWindowManagerTabDrag.cpp @@ -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; }