diff --git a/src/Dock.Model/FactoryBase.Dockable.cs b/src/Dock.Model/FactoryBase.Dockable.cs index 154d990b4..731321fa7 100644 --- a/src/Dock.Model/FactoryBase.Dockable.cs +++ b/src/Dock.Model/FactoryBase.Dockable.cs @@ -47,6 +47,11 @@ public virtual void RemoveDockable(IDockable dockable, bool collapse) var index = dock.VisibleDockables.IndexOf(dockable); if (index < 0) { + if (FindRoot(dockable, x => x.IsFocusableRoot) is { } root && + ReferenceEquals(root.FocusedDockable, dockable)) + { + SetFocusedDockable(dock, dock.ActiveDockable); + } return; } @@ -69,6 +74,12 @@ public virtual void RemoveDockable(IDockable dockable, bool collapse) } } + if (FindRoot(dockable, x => x.IsFocusableRoot) is { } rootDock && + ReferenceEquals(rootDock.FocusedDockable, dockable)) + { + SetFocusedDockable(dock, dock.ActiveDockable); + } + // Clean up orphaned splitters CleanupOrphanedSplitters(dock); diff --git a/src/Dock.Model/FactoryBase.Init.cs b/src/Dock.Model/FactoryBase.Init.cs index e73e47d0b..d43247902 100644 --- a/src/Dock.Model/FactoryBase.Init.cs +++ b/src/Dock.Model/FactoryBase.Init.cs @@ -275,47 +275,53 @@ private void SetIsActive(IDockable dockable, bool active) /// public virtual void SetFocusedDockable(IDock dock, IDockable? dockable) { - if (dock.ActiveDockable is not null && FindRoot(dock.ActiveDockable, x => x.IsFocusableRoot) is { } root) + if (FindRoot(dock, x => x.IsFocusableRoot) is not { } root) { - if (dockable is not null) - { - var results = Find(x => x is IRootDock); + return; + } - foreach (var result in results) + if (dockable is not null) + { + var results = Find(x => x is IRootDock); + + foreach (var result in results) + { + if (result is IRootDock rootDock + && rootDock.IsFocusableRoot + && rootDock != root) { - if (result is IRootDock rootDock - && rootDock.IsFocusableRoot - && rootDock != root) + if (rootDock.FocusedDockable?.Owner is not null) { - if (rootDock.FocusedDockable?.Owner is not null) - { - SetIsActive(rootDock.FocusedDockable.Owner, false); - // Trigger deactivation event for the dockable that lost focus - OnDockableDeactivated(rootDock.FocusedDockable); - } + SetIsActive(rootDock.FocusedDockable.Owner, false); + // Trigger deactivation event for the dockable that lost focus + OnDockableDeactivated(rootDock.FocusedDockable); } } } + } - if (root.FocusedDockable?.Owner is not null) - { - SetIsActive(root.FocusedDockable.Owner, false); - // Trigger deactivation event for the dockable that lost focus - OnDockableDeactivated(root.FocusedDockable); - } + if (root.FocusedDockable?.Owner is not null) + { + SetIsActive(root.FocusedDockable.Owner, false); + // Trigger deactivation event for the dockable that lost focus + OnDockableDeactivated(root.FocusedDockable); + } - if (dockable is not null) + if (dockable is not null) + { + if (root.FocusedDockable != dockable) { - if (root.FocusedDockable != dockable) - { - root.FocusedDockable = dockable; - } + root.FocusedDockable = dockable; } + } + else + { + root.FocusedDockable = null; + } - if (root.FocusedDockable?.Owner is not null) - { - SetIsActive(root.FocusedDockable.Owner, true); - } + if (root.FocusedDockable?.Owner is not null) + { + SetIsActive(root.FocusedDockable.Owner, true); } } } diff --git a/tests/Dock.Avalonia.HeadlessTests/FactoryDockableLifecycleTests.cs b/tests/Dock.Avalonia.HeadlessTests/FactoryDockableLifecycleTests.cs index c99c7b345..be42e9e16 100644 --- a/tests/Dock.Avalonia.HeadlessTests/FactoryDockableLifecycleTests.cs +++ b/tests/Dock.Avalonia.HeadlessTests/FactoryDockableLifecycleTests.cs @@ -104,4 +104,25 @@ public void CloseDockable_Active_Selects_Neighbour() Assert.Same(doc2, dock.ActiveDockable); Assert.Single(dock.VisibleDockables!); } + + [AvaloniaFact] + public void CloseDockable_Active_Clears_FocusedDockable() + { + var factory = new Factory(); + var root = new RootDock { VisibleDockables = factory.CreateList() }; + root.Factory = factory; + + var doc = new Document(); + factory.AddDockable(root, doc); + + root.ActiveDockable = doc; + + Assert.Same(doc, root.FocusedDockable); + + factory.CloseDockable(doc); + + Assert.Null(root.ActiveDockable); + Assert.Null(root.FocusedDockable); + Assert.Empty(root.VisibleDockables!); + } }