From f4804551316b4141367f3ef3fa38c50d9a702fc0 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 29 Nov 2022 12:39:24 +0100 Subject: [PATCH 1/4] Added failing test for #9565. And another (passing) test for checking that window order is correct when a child window is shown in fullscreen. --- samples/IntegrationTestApp/MainWindow.axaml | 7 +- .../IntegrationTestApp/MainWindow.axaml.cs | 3 + .../WindowTests_MacOS.cs | 74 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml index 038ced4e5c..801ff765c8 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -17,11 +17,15 @@ - + + + WindowState: + + @@ -136,6 +140,7 @@ + diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index c1acc7ca88..841947673a 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Avalonia; @@ -178,6 +179,8 @@ namespace IntegrationTestApp ShowWindow(); if (source?.Name == "SendToBack") SendToBack(); + if (source?.Name == "EnterFullscreen") + WindowState = WindowState.FullScreen; if (source?.Name == "ExitFullscreen") WindowState = WindowState.Normal; if (source?.Name == "RestoreAll") diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index 05ed0616a8..8f4417a451 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using Avalonia.Controls; +using Avalonia.Utilities; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Interactions; @@ -114,6 +115,79 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal(1, secondaryWindowIndex); } } + + [PlatformFact(TestPlatforms.MacOS)] + public void WindowOrder_Owned_Dialog_Stays_InFront_Of_FullScreen_Parent() + { + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + + // Enter fullscreen + mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click(); + + // Wait for fullscreen transition. + Thread.Sleep(1000); + + // Make sure we entered fullscreen. + var windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + Assert.Equal("FullScreen", windowState.Text); + + // Open child window. + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) + { + mainWindow.SendClick(); + var secondaryWindowIndex = GetWindowOrder("SecondaryWindow"); + Assert.Equal(1, secondaryWindowIndex); + } + + // Exit fullscreen by menu shortcut Command+R + mainWindow.FindElementByAccessibilityId("ExitFullscreen").Click(); + + // Wait for restore transition. + Thread.Sleep(1000); + + // Make sure we exited fullscreen. + mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + Assert.Equal("Normal", windowState.Text); + } + + [PlatformFact(TestPlatforms.MacOS)] + public void Does_Not_Switch_Space_From_FullScreen_To_Main_Desktop_When_FullScreen_Window_Clicked() + { + // Issue #9565 + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + AppiumWebElement windowState; + + // Open child window. + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) + { + // Enter fullscreen + mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click(); + + // Wait for fullscreen transition. + Thread.Sleep(1000); + + // Make sure we entered fullscreen. + mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + Assert.Equal("FullScreen", windowState.Text); + + // Click on main window + mainWindow.Click(); + + // Failed here due to #9565: main window is no longer visible as the main space is now shown instead + // of the fullscreen space. + mainWindow.FindElementByAccessibilityId("ExitFullscreen").Click(); + + // Wait for restore transition. + Thread.Sleep(1000); + } + + // Make sure we exited fullscreen. + mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + Assert.Equal("Normal", windowState.Text); + } [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() From d00f19d55671373ea0329e35e4a52afb3815364b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 29 Nov 2022 12:40:02 +0100 Subject: [PATCH 2/4] Fix #9565 - Only bring window to front if it's on the currently active space - Ensure correct order of child windows after fullscreen transition --- native/Avalonia.Native/src/OSX/WindowImpl.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 2443965957..b6dacb6ce4 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -137,7 +137,11 @@ void WindowImpl::BringToFront() for(auto iterator = _children.begin(); iterator != _children.end(); iterator++) { - (*iterator)->BringToFront(); + auto window = (*iterator)->Window; + + // #9565: Only bring window to front if it's on the currently active space + if ([window isOnActiveSpace]) + (*iterator)->BringToFront(); } } } @@ -161,6 +165,9 @@ void WindowImpl::StartStateTransition() { void WindowImpl::EndStateTransition() { _transitioningWindowState = false; + + // Ensure correct order of child windows after fullscreen transition. + BringToFront(); } SystemDecorations WindowImpl::Decorations() { From 003923b50d635eadd18b979c98d9ec753630e5c6 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 6 Dec 2022 11:42:37 +0100 Subject: [PATCH 3/4] Fix integration tests on Windows. We need to be explicit about which element we're talking about when there are two elements with the same content, and so use accessibility IDs rather than Name. --- samples/IntegrationTestApp/MainWindow.axaml | 10 +++++----- samples/IntegrationTestApp/ShowWindowTest.axaml | 8 ++++---- .../WindowTests.cs | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml index 801ff765c8..54c0cb0655 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -24,7 +24,7 @@ WindowState: - + @@ -133,10 +133,10 @@ CenterOwner - Normal - Minimized - Maximized - FullScreen + Normal + Minimized + Maximized + FullScreen diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index c3a0d8d2e2..00987429d0 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -27,10 +27,10 @@ - Normal - Minimized - Maximized - FullScreen + Normal + Minimized + Maximized + FullScreen diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index b6ac75b78e..4d833cdb1f 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -90,7 +90,7 @@ namespace Avalonia.IntegrationTests.Appium try { _session.FindElementByAccessibilityId("WindowState").SendClick(); - _session.FindElementByName("Normal").SendClick(); + _session.FindElementByAccessibilityId("WindowStateNormal").SendClick(); // Wait for animations to run. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) @@ -155,11 +155,11 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Normal", windowState.GetComboBoxValue()); windowState.Click(); - _session.FindElementByName("Maximized").SendClick(); + _session.FindElementByAccessibilityId("WindowStateMaximized").SendClick(); Assert.Equal("Maximized", windowState.GetComboBoxValue()); windowState.Click(); - _session.FindElementByName("Normal").SendClick(); + _session.FindElementByAccessibilityId("WindowStateNormal").SendClick(); var current = GetWindowInfo(); Assert.Equal(original.Position, current.Position); @@ -169,7 +169,7 @@ namespace Avalonia.IntegrationTests.Appium if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned) { windowState.Click(); - _session.FindElementByName("FullScreen").SendClick(); + _session.FindElementByAccessibilityId("WindowStateFullScreen").SendClick(); Assert.Equal("FullScreen", windowState.GetComboBoxValue()); current = GetWindowInfo(); @@ -179,7 +179,7 @@ namespace Avalonia.IntegrationTests.Appium windowState.SendClick(); - _session.FindElementByName("Normal").SendClick(); + _session.FindElementByAccessibilityId("WindowStateNormal").SendClick(); current = GetWindowInfo(); Assert.Equal(original.Position, current.Position); @@ -223,13 +223,13 @@ namespace Avalonia.IntegrationTests.Appium // Not sure how to handle testing minimized windows currently. if (state == Controls.WindowState.Minimized) continue; - + // Child/Modal windows cannot be fullscreen on macOS. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && state == Controls.WindowState.FullScreen && mode != ShowWindowMode.NonOwned) continue; - + data.Add(size, mode, state); } } @@ -286,7 +286,7 @@ namespace Avalonia.IntegrationTests.Appium _session.FindElementByName(location.ToString()).SendClick(); stateComboBox.Click(); - _session.FindElementByName(state.ToString()).SendClick(); + _session.FindElementByAccessibilityId($"ShowWindowState{state}").SendClick(); return showButton.OpenWindowWithClick(); } From 23e45beb906fff790715a530ee1d2663601dbff3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 6 Dec 2022 12:00:25 +0100 Subject: [PATCH 4/4] Fix integration tests on macOS. --- .../Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index 8f4417a451..6c61a85561 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -128,7 +128,7 @@ namespace Avalonia.IntegrationTests.Appium Thread.Sleep(1000); // Make sure we entered fullscreen. - var windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + var windowState = mainWindow.FindElementByAccessibilityId("MainWindowState"); Assert.Equal("FullScreen", windowState.Text); // Open child window. @@ -147,7 +147,7 @@ namespace Avalonia.IntegrationTests.Appium // Make sure we exited fullscreen. mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + windowState = mainWindow.FindElementByAccessibilityId("MainWindowState"); Assert.Equal("Normal", windowState.Text); } @@ -169,7 +169,7 @@ namespace Avalonia.IntegrationTests.Appium // Make sure we entered fullscreen. mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + windowState = mainWindow.FindElementByAccessibilityId("MainWindowState"); Assert.Equal("FullScreen", windowState.Text); // Click on main window @@ -185,7 +185,7 @@ namespace Avalonia.IntegrationTests.Appium // Make sure we exited fullscreen. mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - windowState = mainWindow.FindElementByAccessibilityId("WindowState"); + windowState = mainWindow.FindElementByAccessibilityId("MainWindowState"); Assert.Equal("Normal", windowState.Text); }