From 5ceb7c11edb704da69c7cf53182c687d053186f8 Mon Sep 17 00:00:00 2001 From: Misaki Date: Sat, 28 Mar 2026 16:47:08 +0900 Subject: [PATCH] fix(dock): add drag payload validation and ensure unconditional state cleanup --- .../Ghost.Editor/View/Controls/DockLayout.cs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs b/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs index df2f142..0d4f28c 100644 --- a/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs +++ b/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs @@ -386,7 +386,8 @@ public sealed partial class DockLayout : Control { if (_dropTargetOverlay != null) _dropTargetOverlay.Visibility = Visibility.Collapsed; - if (_draggedItem == null || _sourceNode == null || !(sender is FrameworkElement targetElement) || !(targetElement.Tag is DockPanelNode targetNode)) + if (!e.DataView.Properties.ContainsKey(DRAG_PROPERTY_DOCK_TAB) || + _draggedItem == null || _sourceNode == null || !(sender is FrameworkElement targetElement) || !(targetElement.Tag is DockPanelNode targetNode)) { ClearDragOperationState(); return; @@ -421,19 +422,24 @@ public sealed partial class DockLayout : Control private void TabView_TabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args) { - if (_sourceNode != null && _draggedItem != null) + try { - var result = TabTearOffService.TryTearOffTab(_sourceNode.Items, _draggedItem, _sourceNode); - - if (result.IsSuccess) + if (_sourceNode != null && _draggedItem != null) { - DockMutationEngine.CleanupEmptyNodes(_sourceNode); - } - else - { - Logger.LogWarning($"Tab tear-off failed: {result.Message}"); - } + var result = TabTearOffService.TryTearOffTab(_sourceNode.Items, _draggedItem, _sourceNode); + if (result.IsSuccess) + { + DockMutationEngine.CleanupEmptyNodes(_sourceNode); + } + else + { + Logger.LogWarning($"Tab tear-off failed: {result.Message}"); + } + } + } + finally + { ClearDragOperationState(); } }