Răsfoiți Sursa

Merge pull request #9221 from AvaloniaUI/fixes/8869-show-windowstate

Fix setting WindowState before showing Window.
Max Katz 2 ani în urmă
părinte
comite
fc6645e229

+ 6 - 0
samples/IntegrationTestApp/MainWindow.axaml

@@ -128,6 +128,12 @@
             <ComboBoxItem>CenterScreen</ComboBoxItem>
             <ComboBoxItem>CenterOwner</ComboBoxItem>
           </ComboBox>
+          <ComboBox Name="ShowWindowState" SelectedIndex="0">
+            <ComboBoxItem>Normal</ComboBoxItem>
+            <ComboBoxItem>Minimized</ComboBoxItem>
+            <ComboBoxItem>Maximized</ComboBoxItem>
+            <ComboBoxItem>FullScreen</ComboBoxItem>
+          </ComboBox>
           <Button Name="ShowWindow">Show Window</Button>
           <Button Name="SendToBack">Send to Back</Button>
           <Button Name="ExitFullscreen">Exit Fullscreen</Button>

+ 2 - 0
samples/IntegrationTestApp/MainWindow.axaml.cs

@@ -59,6 +59,7 @@ namespace IntegrationTestApp
             var sizeTextBox = this.GetControl<TextBox>("ShowWindowSize");
             var modeComboBox = this.GetControl<ComboBox>("ShowWindowMode");
             var locationComboBox = this.GetControl<ComboBox>("ShowWindowLocation");
+            var stateComboBox = this.GetControl<ComboBox>("ShowWindowState");
             var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null;
             var owner = (Window)this.GetVisualRoot()!;
 
@@ -85,6 +86,7 @@ namespace IntegrationTestApp
             }
 
             sizeTextBox.Text = string.Empty;
+            window.WindowState = (WindowState)stateComboBox.SelectedIndex;
 
             switch (modeComboBox.SelectedIndex)
             {

+ 1 - 1
samples/IntegrationTestApp/ShowWindowTest.axaml

@@ -30,7 +30,7 @@
       <ComboBoxItem>Normal</ComboBoxItem>
       <ComboBoxItem>Minimized</ComboBoxItem>
       <ComboBoxItem>Maximized</ComboBoxItem>
-      <ComboBoxItem>Fullscreen</ComboBoxItem>
+      <ComboBoxItem>FullScreen</ComboBoxItem>
     </ComboBox>
 
     <Label Grid.Column="0" Grid.Row="8">Order (mac)</Label>

+ 7 - 3
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@@ -588,9 +588,13 @@ namespace Avalonia.Win32
                             Resized(clientSize / RenderScaling, _resizeReason);
                         }
 
-                        var windowState = size == SizeCommand.Maximized ?
-                            WindowState.Maximized :
-                            (size == SizeCommand.Minimized ? WindowState.Minimized : WindowState.Normal);
+                        var windowState = size switch
+                        {
+                            SizeCommand.Maximized => WindowState.Maximized,
+                            SizeCommand.Minimized => WindowState.Minimized,
+                            _ when _isFullScreenActive => WindowState.FullScreen,
+                            _ => WindowState.Normal,
+                        };
 
                         if (windowState != _lastWindowState)
                         {

+ 9 - 2
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -269,6 +269,11 @@ namespace Avalonia.Win32
         {
             get
             {
+                if (!IsWindowVisible(_hwnd))
+                {
+                    return _showWindowState;
+                }
+
                 if (_isFullScreenActive)
                 {
                     return WindowState.FullScreen;
@@ -562,6 +567,9 @@ namespace Avalonia.Win32
 
         public void Resize(Size value, PlatformResizeReason reason)
         {
+            if (WindowState != WindowState.Normal)
+                return;
+
             int requestedClientWidth = (int)(value.Width * RenderScaling);
             int requestedClientHeight = (int)(value.Height * RenderScaling);
 
@@ -902,11 +910,10 @@ namespace Avalonia.Win32
 
                 var window_rect = monitor_info.rcMonitor.ToPixelRect();
 
+                _isFullScreenActive = true;
                 SetWindowPos(_hwnd, IntPtr.Zero, window_rect.X, window_rect.Y,
                              window_rect.Width, window_rect.Height,
                              SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_FRAMECHANGED);
-
-                _isFullScreenActive = true;
             }
             else
             {

+ 12 - 5
tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Reactive.Disposables;
 using System.Runtime.InteropServices;
+using System.Threading;
 using OpenQA.Selenium;
 using OpenQA.Selenium.Appium;
 using OpenQA.Selenium.Interactions;
@@ -110,24 +111,30 @@ namespace Avalonia.IntegrationTests.Appium
             {
                 var oldWindows = session.FindElements(By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow"));
                 var oldWindowTitles = oldWindows.ToDictionary(x => x.Text);
-                
+
                 element.Click();
+                
+                // Wait for animations to run.
+                Thread.Sleep(1000);
 
                 var newWindows = session.FindElements(By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow"));
                 var newWindowTitles = newWindows.ToDictionary(x => x.Text);
                 var newWindowTitle = Assert.Single(newWindowTitles.Keys.Except(oldWindowTitles.Keys));
-                var newWindow = (AppiumWebElement)newWindowTitles[newWindowTitle]; 
-                
+
                 return Disposable.Create(() =>
                 {
                     // TODO: We should be able to use Cmd+W here but Avalonia apps don't seem to have this shortcut
                     // set up by default.
-                    var (close, _, _) = newWindow.GetChromeButtons();
+                    var windows = session.FindElements(By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow"));
+                    var text = windows.Select(x => x.Text).ToList();
+                    var newWindow = session.FindElements(By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow"))
+                        .First(x => x.Text == newWindowTitle);
+                    var (close, _, _) = ((AppiumWebElement)newWindow).GetChromeButtons();
                     close!.Click();
                 });
             }
         }
-
+    
         public static void SendClick(this AppiumWebElement element)
         {
             // The Click() method seems to correspond to accessibilityPerformPress on macOS but certain controls

+ 92 - 7
tests/Avalonia.IntegrationTests.Appium/WindowTests.cs

@@ -57,7 +57,53 @@ namespace Avalonia.IntegrationTests.Appium
                 }
             }
         }
-        
+
+        [Theory]
+        [MemberData(nameof(WindowStateData))]
+        public void WindowState(Size? size, ShowWindowMode mode, WindowState state)
+        {
+            using var window = OpenWindow(size, mode, state: state);
+
+            try
+            {
+                var info = GetWindowInfo();
+
+                Assert.Equal(state, info.WindowState);
+
+                switch (state)
+                {
+                    case Controls.WindowState.Normal:
+                        Assert.True(info.FrameSize.Width * info.Scaling < info.ScreenRect.Size.Width);
+                        Assert.True(info.FrameSize.Height * info.Scaling < info.ScreenRect.Size.Height);
+                        break;
+                    case Controls.WindowState.Maximized:
+                    case Controls.WindowState.FullScreen:
+                        Assert.True(info.FrameSize.Width * info.Scaling >= info.ScreenRect.Size.Width);
+                        Assert.True(info.FrameSize.Height * info.Scaling >= info.ScreenRect.Size.Height);
+                        break;
+                }
+            }
+            finally
+            {
+                if (state == Controls.WindowState.FullScreen)
+                {
+                    try
+                    {
+                        _session.FindElementByAccessibilityId("WindowState").SendClick();
+                        _session.FindElementByName("Normal").SendClick();
+
+                        // Wait for animations to run.
+                        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+                            Thread.Sleep(1000);
+                    }
+                    catch
+                    {
+                        /* Ignore errors in cleanup */
+                    }
+                }
+            }
+        }
+
         [PlatformFact(TestPlatforms.Windows)]
         public void OnWindows_Docked_Windows_Retain_Size_Position_When_Restored()
         {
@@ -100,7 +146,7 @@ namespace Avalonia.IntegrationTests.Appium
         [InlineData(ShowWindowMode.NonOwned)]
         [InlineData(ShowWindowMode.Owned)]
         [InlineData(ShowWindowMode.Modal)]
-        public void WindowState(ShowWindowMode mode)
+        public void ShowMode(ShowWindowMode mode)
         {
             using var window = OpenWindow(null, mode, WindowStartupLocation.Manual);
             var windowState = _session.FindElementByAccessibilityId("WindowState");
@@ -123,8 +169,8 @@ namespace Avalonia.IntegrationTests.Appium
             if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned)
             {
                 windowState.Click();
-                _session.FindElementByName("Fullscreen").SendClick();
-                Assert.Equal("Fullscreen", windowState.GetComboBoxValue());
+                _session.FindElementByName("FullScreen").SendClick();
+                Assert.Equal("FullScreen", windowState.GetComboBoxValue());
 
                 current = GetWindowInfo();
                 var clientSize = PixelSize.FromSize(current.ClientSize, current.Scaling);
@@ -163,6 +209,35 @@ namespace Avalonia.IntegrationTests.Appium
             return data;
         }
 
+        public static TheoryData<Size?, ShowWindowMode, WindowState> WindowStateData()
+        {
+            var sizes = new Size?[] { null, new Size(400, 300) };
+            var data = new TheoryData<Size?, ShowWindowMode, WindowState>();
+
+            foreach (var size in sizes)
+            {
+                foreach (var mode in Enum.GetValues<ShowWindowMode>())
+                {
+                    foreach (var state in Enum.GetValues<WindowState>())
+                    {
+                        // 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);
+                    }
+                }
+            }
+
+            return data;
+        }
+
         private static void AssertCloseEnough(PixelPoint expected, PixelPoint actual)
         {
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -189,11 +264,16 @@ namespace Avalonia.IntegrationTests.Appium
             }
         }
 
-        private IDisposable OpenWindow(Size? size, ShowWindowMode mode, WindowStartupLocation location)
+        private IDisposable OpenWindow(
+            Size? size,
+            ShowWindowMode mode,
+            WindowStartupLocation location = WindowStartupLocation.Manual,
+            WindowState state = Controls.WindowState.Normal)
         {
             var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize");
             var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode");
             var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation");
+            var stateComboBox = _session.FindElementByAccessibilityId("ShowWindowState");
             var showButton = _session.FindElementByAccessibilityId("ShowWindow");
 
             if (size.HasValue)
@@ -205,6 +285,9 @@ namespace Avalonia.IntegrationTests.Appium
             locationComboBox.Click();
             _session.FindElementByName(location.ToString()).SendClick();
 
+            stateComboBox.Click();
+            _session.FindElementByName(state.ToString()).SendClick();
+
             return showButton.OpenWindowWithClick();
         }
 
@@ -228,7 +311,8 @@ namespace Avalonia.IntegrationTests.Appium
                         PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text),
                         ReadOwnerRect(),
                         PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text),
-                        double.Parse(_session.FindElementByAccessibilityId("Scaling").Text));
+                        double.Parse(_session.FindElementByAccessibilityId("Scaling").Text),
+                        Enum.Parse<WindowState>(_session.FindElementByAccessibilityId("WindowState").Text));
                 }
                 catch (OpenQA.Selenium.NoSuchElementException) when (retry++ < 3)
                 {
@@ -252,6 +336,7 @@ namespace Avalonia.IntegrationTests.Appium
             PixelPoint Position,
             PixelRect? OwnerRect,
             PixelRect ScreenRect,
-            double Scaling);
+            double Scaling,
+            WindowState WindowState);
     }
 }