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

@@ -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();
}

View File

@@ -53,6 +53,9 @@ public:
const std::vector<HierarchyPanel::Event>& GetHierarchyPanelEvents() const;
const std::vector<ProjectPanel::Event>& GetProjectPanelEvents() const;
const std::string& GetBuiltInIconError() const;
void SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview);
void ClearExternalDockHostDropPreview();
ProjectPanel::CursorKind GetHostedContentCursorKind() const;
Widgets::UIEditorDockHostCursorKind GetDockCursorKind() const;

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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) {

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;
}