Browse Source

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
pull/18132/head
Emmanuel Hansen 2 years ago
committed by GitHub
parent
commit
4c1edc2d1e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 51
      src/Avalonia.Controls/Window.cs
  2. 10
      tests/Avalonia.Controls.UnitTests/WindowTests.cs

51
src/Avalonia.Controls/Window.cs

@ -201,6 +201,7 @@ namespace Avalonia.Controls
private bool _showingAsDialog;
private bool _positionWasSet;
private bool _wasShownBefore;
private IDisposable? _modalSubscription;
/// <summary>
/// Initializes static members of the <see cref="Window"/> class.
@ -612,11 +613,12 @@ namespace Avalonia.Controls
}
}
Owner = null;
PlatformImpl?.Hide();
IsVisible = false;
_shown = false;
Owner = null;
_modalSubscription?.Dispose();
_shown = false;
}
}
@ -645,14 +647,7 @@ namespace Avalonia.Controls
}
else
{
if (_showingAsDialog)
{
Close(false);
}
else
{
Hide();
}
Hide();
}
}
}
@ -706,7 +701,7 @@ namespace Avalonia.Controls
using (FreezeVisibilityChangeHandling())
{
EnsureStateBeforeShow();
if (modal && owner == null)
{
throw new ArgumentNullException(nameof(owner));
@ -738,14 +733,14 @@ namespace Avalonia.Controls
var initialSize = new Size(
double.IsNaN(Width) ? ClientSize.Width : Width,
double.IsNaN(Height) ? ClientSize.Height : Height);
initialSize = new Size(
MathUtilities.Clamp(initialSize.Width, MinWidth, MaxWidth),
MathUtilities.Clamp(initialSize.Height, MinHeight, MaxHeight));
var clientSizeChanged = initialSize != ClientSize;
ClientSize = initialSize; // ClientSize is required for Measure and Arrange
// this will call ArrangeSetBounds
LayoutManager.ExecuteInitialLayoutPass();
@ -762,21 +757,21 @@ namespace Avalonia.Controls
clientSizeChanged |= initialSize != ClientSize;
ClientSize = initialSize;
}
Owner = owner;
SetWindowStartupLocation(owner);
DesktopScalingOverride = null;
if (clientSizeChanged || ClientSize != PlatformImpl?.ClientSize)
{
// Previously it was called before ExecuteInitialLayoutPass
PlatformImpl?.Resize(ClientSize, WindowResizeReason.Layout);
// we do not want PlatformImpl?.Resize to trigger HandleResized yet because it will set Width and Height.
// So perform some important actions from HandleResized
Renderer.Resized(ClientSize);
OnResized(new WindowResizedEventArgs(ClientSize, WindowResizeReason.Layout));
@ -788,8 +783,8 @@ namespace Avalonia.Controls
FrameSize = PlatformImpl?.FrameSize;
_canHandleResized = true;
_canHandleResized = true;
StartRendering();
PlatformImpl?.Show(ShowActivated, modal);
@ -798,22 +793,32 @@ namespace Avalonia.Controls
{
var tcs = new TaskCompletionSource<TResult>();
Observable.FromEventPattern(
var disposables = new CompositeDisposable(
[
Observable.FromEventPattern(
x => Closed += x,
x => Closed -= x)
.Take(1)
.Subscribe(_ =>
{
_modalSubscription?.Dispose();
}),
Disposable.Create(() =>
{
_modalSubscription = null;
owner!.Activate();
tcs.SetResult((TResult)(_dialogResult ?? default(TResult)!));
});
})
]);
_modalSubscription = disposables;
result = tcs.Task;
}
OnOpened(EventArgs.Empty);
if (!modal)
_wasShownBefore = true;
return result;
}
}

10
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -1060,7 +1060,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void IsVisible_Should_Close_DialogWindow()
public void Hiding_DialogWindow_Should_Complete_Task()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@ -1068,18 +1068,12 @@ namespace Avalonia.Controls.UnitTests
parent.Show();
var target = new Window();
var raised = false;
var task = target.ShowDialog<bool>(parent);
target.Closed += (sender, args) => raised = true;
target.IsVisible = false;
Assert.True(raised);
Assert.False(task.Result);
Assert.True(task.IsCompletedSuccessfully);
}
}

Loading…
Cancel
Save