Browse Source

Ensure parent/owner windows are visible when showing child.

pull/6198/head
Steven Kirk 5 years ago
parent
commit
15cdee1bee
  1. 24
      src/Avalonia.Controls/Window.cs
  2. 50
      tests/Avalonia.Controls.UnitTests/WindowTests.cs

24
src/Avalonia.Controls/Window.cs

@ -639,13 +639,16 @@ namespace Avalonia.Controls
{ {
if (parent.PlatformImpl == null) if (parent.PlatformImpl == null)
{ {
throw new InvalidOperationException("Cannot Show a Window with a closed parent."); throw new InvalidOperationException("Cannot show a window with a closed parent.");
} }
else if (parent == this)
if (parent == this)
{ {
throw new InvalidOperationException("A Window cannot be its own parent."); throw new InvalidOperationException("A Window cannot be its own parent.");
} }
else if (!parent.IsVisible)
{
throw new InvalidOperationException("Cannot show window with non-visible parent.");
}
} }
if (IsVisible) if (IsVisible)
@ -721,21 +724,22 @@ namespace Avalonia.Controls
{ {
throw new ArgumentNullException(nameof(owner)); throw new ArgumentNullException(nameof(owner));
} }
else if (owner.PlatformImpl == null)
if (owner.PlatformImpl == null)
{ {
throw new InvalidOperationException("Cannot Show a Window with a closed owner."); throw new InvalidOperationException("Cannot show a window with a closed owner.");
} }
else if (owner == this)
if (owner == this)
{ {
throw new InvalidOperationException("A Window cannot be its own owner."); throw new InvalidOperationException("A Window cannot be its own owner.");
} }
else if (IsVisible)
if (IsVisible)
{ {
throw new InvalidOperationException("The window is already being shown."); throw new InvalidOperationException("The window is already being shown.");
} }
else if (!owner.IsVisible)
{
throw new InvalidOperationException("Cannot show window with non-visible parent.");
}
RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); RaiseEvent(new RoutedEventArgs(WindowOpenedEvent));

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

@ -279,10 +279,11 @@ namespace Avalonia.Controls.UnitTests
{ {
using (UnitTestApplication.Start(TestServices.StyledWindow)) using (UnitTestApplication.Start(TestServices.StyledWindow))
{ {
var parent = Mock.Of<Window>(); var parent = new Window();
var renderer = new Mock<IRenderer>(); var renderer = new Mock<IRenderer>();
var target = new Window(CreateImpl(renderer)); var target = new Window(CreateImpl(renderer));
parent.Show();
target.ShowDialog<object>(parent); target.ShowDialog<object>(parent);
renderer.Verify(x => x.Start(), Times.Once); renderer.Verify(x => x.Start(), Times.Once);
@ -294,10 +295,11 @@ namespace Avalonia.Controls.UnitTests
{ {
using (UnitTestApplication.Start(TestServices.StyledWindow)) using (UnitTestApplication.Start(TestServices.StyledWindow))
{ {
var parent = Mock.Of<Window>(); var parent = new Window();
var target = new Window(); var target = new Window();
var raised = false; var raised = false;
parent.Show();
target.Opened += (s, e) => raised = true; target.Opened += (s, e) => raised = true;
target.ShowDialog<object>(parent); target.ShowDialog<object>(parent);
@ -326,14 +328,15 @@ namespace Avalonia.Controls.UnitTests
{ {
using (UnitTestApplication.Start(TestServices.StyledWindow)) using (UnitTestApplication.Start(TestServices.StyledWindow))
{ {
var parent = new Mock<Window>(); var parent = new Window();
var windowImpl = new Mock<IWindowImpl>(); var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed); windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.DesktopScaling).Returns(1); windowImpl.Setup(x => x.DesktopScaling).Returns(1);
windowImpl.Setup(x => x.RenderScaling).Returns(1); windowImpl.Setup(x => x.RenderScaling).Returns(1);
parent.Show();
var target = new Window(windowImpl.Object); var target = new Window(windowImpl.Object);
var task = target.ShowDialog<bool>(parent.Object); var task = target.ShowDialog<bool>(parent);
windowImpl.Object.Closed(); windowImpl.Object.Closed();
@ -366,14 +369,16 @@ namespace Avalonia.Controls.UnitTests
{ {
using (UnitTestApplication.Start(TestServices.StyledWindow)) using (UnitTestApplication.Start(TestServices.StyledWindow))
{ {
var parent = new Mock<Window>(); var parent = new Window();
var windowImpl = new Mock<IWindowImpl>(); var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed); windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.DesktopScaling).Returns(1); windowImpl.Setup(x => x.DesktopScaling).Returns(1);
windowImpl.Setup(x => x.RenderScaling).Returns(1); windowImpl.Setup(x => x.RenderScaling).Returns(1);
parent.Show();
var target = new Window(windowImpl.Object); var target = new Window(windowImpl.Object);
var task = target.ShowDialog<bool>(parent.Object); var task = target.ShowDialog<bool>(parent);
windowImpl.Object.Closed(); windowImpl.Object.Closed();
await task; await task;
@ -381,7 +386,7 @@ namespace Avalonia.Controls.UnitTests
var openedRaised = false; var openedRaised = false;
target.Opened += (s, e) => openedRaised = true; target.Opened += (s, e) => openedRaised = true;
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog<bool>(parent.Object)); var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog<bool>(parent));
Assert.Equal("Cannot re-show a closed window.", ex.Message); Assert.Equal("Cannot re-show a closed window.", ex.Message);
Assert.False(openedRaised); Assert.False(openedRaised);
} }
@ -398,7 +403,7 @@ namespace Avalonia.Controls.UnitTests
parent.Close(); parent.Close();
var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent)); var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent));
Assert.Equal("Cannot Show a Window with a closed parent.", ex.Message); Assert.Equal("Cannot show a window with a closed parent.", ex.Message);
} }
} }
@ -413,7 +418,33 @@ namespace Avalonia.Controls.UnitTests
parent.Close(); parent.Close();
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent)); var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent));
Assert.Equal("Cannot Show a Window with a closed owner.", ex.Message); Assert.Equal("Cannot show a window with a closed owner.", ex.Message);
}
}
[Fact]
public void Calling_Show_With_Invisible_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Window();
var target = new Window();
var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent));
Assert.Equal("Cannot show window with non-visible parent.", ex.Message);
}
}
[Fact]
public async Task Calling_ShowDialog_With_Invisible_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Window();
var target = new Window();
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent));
Assert.Equal("Cannot show window with non-visible parent.", ex.Message);
} }
} }
@ -740,6 +771,7 @@ namespace Avalonia.Controls.UnitTests
protected override void Show(Window window) protected override void Show(Window window)
{ {
var owner = new Window(); var owner = new Window();
owner.Show();
window.ShowDialog(owner); window.ShowDialog(owner);
} }
} }

Loading…
Cancel
Save