Skip to content

Commit 4c1edc2

Browse files
authored
Fix - Complete window dialog task when dialog is hidden (#18047)
* complete window dialog task when dialog is hidden * change window IsVisible behavior for dialogs to hide window instead. update tests * unset owner before hiding window to prevent OS from updating owner visibility or window order
1 parent eafb41d commit 4c1edc2

2 files changed

Lines changed: 30 additions & 31 deletions

File tree

src/Avalonia.Controls/Window.cs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ public class Window : WindowBase, IFocusScope, ILayoutRoot
201201
private bool _showingAsDialog;
202202
private bool _positionWasSet;
203203
private bool _wasShownBefore;
204+
private IDisposable? _modalSubscription;
204205

205206
/// <summary>
206207
/// Initializes static members of the <see cref="Window"/> class.
@@ -612,11 +613,12 @@ public override void Hide()
612613
}
613614
}
614615

616+
Owner = null;
615617
PlatformImpl?.Hide();
616618
IsVisible = false;
617-
_shown = false;
618619

619-
Owner = null;
620+
_modalSubscription?.Dispose();
621+
_shown = false;
620622
}
621623
}
622624

@@ -645,14 +647,7 @@ protected override void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e)
645647
}
646648
else
647649
{
648-
if (_showingAsDialog)
649-
{
650-
Close(false);
651-
}
652-
else
653-
{
654-
Hide();
655-
}
650+
Hide();
656651
}
657652
}
658653
}
@@ -706,7 +701,7 @@ private void EnsureParentStateBeforeShow(Window owner)
706701
using (FreezeVisibilityChangeHandling())
707702
{
708703
EnsureStateBeforeShow();
709-
704+
710705
if (modal && owner == null)
711706
{
712707
throw new ArgumentNullException(nameof(owner));
@@ -738,14 +733,14 @@ private void EnsureParentStateBeforeShow(Window owner)
738733
var initialSize = new Size(
739734
double.IsNaN(Width) ? ClientSize.Width : Width,
740735
double.IsNaN(Height) ? ClientSize.Height : Height);
741-
736+
742737
initialSize = new Size(
743738
MathUtilities.Clamp(initialSize.Width, MinWidth, MaxWidth),
744739
MathUtilities.Clamp(initialSize.Height, MinHeight, MaxHeight));
745740

746741
var clientSizeChanged = initialSize != ClientSize;
747742
ClientSize = initialSize; // ClientSize is required for Measure and Arrange
748-
743+
749744
// this will call ArrangeSetBounds
750745
LayoutManager.ExecuteInitialLayoutPass();
751746

@@ -762,21 +757,21 @@ private void EnsureParentStateBeforeShow(Window owner)
762757
clientSizeChanged |= initialSize != ClientSize;
763758
ClientSize = initialSize;
764759
}
765-
760+
766761
Owner = owner;
767762

768763
SetWindowStartupLocation(owner);
769-
764+
770765
DesktopScalingOverride = null;
771-
766+
772767
if (clientSizeChanged || ClientSize != PlatformImpl?.ClientSize)
773768
{
774769
// Previously it was called before ExecuteInitialLayoutPass
775770
PlatformImpl?.Resize(ClientSize, WindowResizeReason.Layout);
776-
771+
777772
// we do not want PlatformImpl?.Resize to trigger HandleResized yet because it will set Width and Height.
778773
// So perform some important actions from HandleResized
779-
774+
780775
Renderer.Resized(ClientSize);
781776
OnResized(new WindowResizedEventArgs(ClientSize, WindowResizeReason.Layout));
782777

@@ -788,8 +783,8 @@ private void EnsureParentStateBeforeShow(Window owner)
788783

789784
FrameSize = PlatformImpl?.FrameSize;
790785

791-
_canHandleResized = true;
792-
786+
_canHandleResized = true;
787+
793788
StartRendering();
794789
PlatformImpl?.Show(ShowActivated, modal);
795790

@@ -798,22 +793,32 @@ private void EnsureParentStateBeforeShow(Window owner)
798793
{
799794
var tcs = new TaskCompletionSource<TResult>();
800795

801-
Observable.FromEventPattern(
796+
var disposables = new CompositeDisposable(
797+
[
798+
Observable.FromEventPattern(
802799
x => Closed += x,
803800
x => Closed -= x)
804801
.Take(1)
805802
.Subscribe(_ =>
806803
{
804+
_modalSubscription?.Dispose();
805+
}),
806+
Disposable.Create(() =>
807+
{
808+
_modalSubscription = null;
807809
owner!.Activate();
808810
tcs.SetResult((TResult)(_dialogResult ?? default(TResult)!));
809-
});
811+
})
812+
]);
813+
814+
_modalSubscription = disposables;
810815
result = tcs.Task;
811816
}
812817

813818
OnOpened(EventArgs.Empty);
814819
if (!modal)
815820
_wasShownBefore = true;
816-
821+
817822
return result;
818823
}
819824
}

tests/Avalonia.Controls.UnitTests/WindowTests.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,26 +1060,20 @@ public void IsVisible_Should_Open_Window()
10601060
}
10611061

10621062
[Fact]
1063-
public void IsVisible_Should_Close_DialogWindow()
1063+
public void Hiding_DialogWindow_Should_Complete_Task()
10641064
{
10651065
using (UnitTestApplication.Start(TestServices.StyledWindow))
10661066
{
10671067
var parent = new Window();
10681068
parent.Show();
10691069

10701070
var target = new Window();
1071-
1072-
var raised = false;
10731071

10741072
var task = target.ShowDialog<bool>(parent);
1075-
1076-
target.Closed += (sender, args) => raised = true;
10771073

10781074
target.IsVisible = false;
1079-
1080-
Assert.True(raised);
10811075

1082-
Assert.False(task.Result);
1076+
Assert.True(task.IsCompletedSuccessfully);
10831077
}
10841078
}
10851079

0 commit comments

Comments
 (0)