Procházet zdrojové kódy

Improve macOS and window resizing behavior

- Added macOS-specific centering for rotated windows.
- Refactored `WindowResizing2` logic for fullscreen, maximized, and auto-fit modes.
- Updated method parameters to use `MainWindow` for better type consistency.
- Enhanced macOS window state transitions, including proper size and centering adjustments.
Ruben před 1 dnem
rodič
revize
16e7b8df4a

+ 7 - 0
src/PicView.Avalonia.MacOS/WindowImpl/MacOSWindow2.cs

@@ -102,6 +102,13 @@ public static class MacOSWindow2
         vm.IsFullscreen.Value = true;
         vm.IsMaximized.Value = false;
         
+        // Set the window size to the screen size
+        window.Width = ScreenHelper.ScreenSize.Width;
+        window.Height = ScreenHelper.ScreenSize.Height;
+        
+        // Sometimes the window is not centered properly, so center it again
+        WindowFunctions2.CenterWindowOnScreen(window);
+        
         WindowResizing2.SetSize(vm, WindowResizeReason.Application);
         
         // Reset changing state flag so subscription can fire again. Need to be delayed by dispatcher to not be misfired. 

+ 2 - 2
src/PicView.Avalonia/CustomControls/MainWindow.cs

@@ -24,7 +24,7 @@ public class MainWindow : Window, IMainWindow
     public UserControl? SharedTitleBar { get; set; }
     public AvaloniaRenderingFrameProvider? FrameProvider { get; set; }
 
-    public MainWindow()
+    protected MainWindow()
     {
         FrameProvider = new AvaloniaRenderingFrameProvider(GetTopLevel(this));
         UIHelper2.SetFrameProvider(FrameProvider);
@@ -54,7 +54,7 @@ public class MainWindow : Window, IMainWindow
     
     private void OnActivated(object? sender, EventArgs e)
     {
-        if (Application.Current.DataContext is not CoreViewModel core || Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
+        if (Application.Current.DataContext is not CoreViewModel core || Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
         {
             return;
         }

+ 7 - 2
src/PicView.Avalonia/ImageTransformations/Rotation/RotationTransformer2.cs

@@ -1,3 +1,4 @@
+using System.Runtime.InteropServices;
 using Avalonia.Animation;
 using Avalonia.Controls;
 using Avalonia.Media;
@@ -40,13 +41,17 @@ public class RotationTransformer2(
         }
 
         WindowResizing2.SetSize(vm, WindowResizeReason.Layout);
-        mainImage.InvalidateVisual();
+
+        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && Settings.WindowProperties.Fullscreen)
+        {
+            // Sometimes the window is off-center after rotating on macOS fullscreen view
+            WindowFunctions2.CenterWindowOnScreen();
+        }
     }
 
     public void Rotate(double angle)
     {
         WindowResizing2.SetSize(vm, WindowResizeReason.Layout);
-        mainImage.InvalidateVisual();
     }
 
     private ScaleTransform? _scaleTransform;

+ 27 - 19
src/PicView.Avalonia/StartUp/StartUpHelper2.cs

@@ -9,6 +9,7 @@ using Avalonia.Interactivity;
 using Avalonia.Threading;
 using ImageMagick;
 using PicView.Avalonia.ColorManagement;
+using PicView.Avalonia.CustomControls;
 using PicView.Avalonia.Functions;
 using PicView.Avalonia.Input;
 using PicView.Avalonia.Navigation;
@@ -28,7 +29,7 @@ namespace PicView.Avalonia.StartUp;
 public static class StartUpHelper2
 {
     public static void StartWithArguments(CoreViewModel vm, bool settingsExists,
-        IClassicDesktopStyleApplicationLifetime desktop, Window window)
+        IClassicDesktopStyleApplicationLifetime desktop, MainWindow window)
     {
         var args = Environment.GetCommandLineArgs();
         if (args.Length > 1)
@@ -100,7 +101,7 @@ public static class StartUpHelper2
 
     
     public static void StartUpBlank(CoreViewModel vm, bool settingsExists, bool setPos,
-        IClassicDesktopStyleApplicationLifetime desktop, Window window)
+        IClassicDesktopStyleApplicationLifetime desktop, MainWindow window)
     {
         SettingsUpdater2.InitializeSettings(vm.MainWindows.ActiveWindow.CurrentValue, settingsExists);
         
@@ -113,7 +114,7 @@ public static class StartUpHelper2
     
     public static void RegularStartUp(CoreViewModel vm, bool settingsExists,
         IClassicDesktopStyleApplicationLifetime desktop,
-        Window window)
+        MainWindow window)
     {
         TranslationManager.Init();
         SettingsUpdater2.InitializeSettings(vm.MainWindows.ActiveWindow.CurrentValue, settingsExists);
@@ -126,9 +127,7 @@ public static class StartUpHelper2
         HandlePostWindowUpdates(vm, settingsExists, desktop, window);
     }
     
-    
-
-    public static void HandleWindowScalingMode(CoreViewModel vm, Window window, bool setPos = true)
+    public static void HandleWindowScalingMode(CoreViewModel vm, MainWindow window, bool setPos = true)
     {
         ScreenHelper.UpdateScreenSize(window);
 
@@ -148,7 +147,7 @@ public static class StartUpHelper2
     }
 
     public static void HandlePostWindowUpdates(CoreViewModel vm, bool settingsExists,
-        IClassicDesktopStyleApplicationLifetime desktop, Window window)
+        IClassicDesktopStyleApplicationLifetime desktop, MainWindow window)
     {
         SetMemorySettings();
         
@@ -159,23 +158,32 @@ public static class StartUpHelper2
 
         UIHelper2.SetControls(window);
 
-        if (!Settings.WindowProperties.AutoFit)
-        {
-            // Need to update the screen size after the window is shown,
-            // to avoid rendering error when switching between auto-fit
-            ScreenHelper.UpdateScreenSize(window);
-        }
-
         // Need to delay setting fullscreen or maximized until after the window is shown to select the correct monitor
         if (Settings.WindowProperties.Maximized && !Settings.WindowProperties.Fullscreen)
         {
-            // Dispatcher.UIThread
-            //     .InvokeAsync(() => { window Maximize(false); }, DispatcherPriority.Background);
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                vm.MainWindows.ActiveWindow.CurrentValue.PlatformWindowService.Maximize(false);
+            }
+            else
+            {
+                Dispatcher.UIThread.Post(() =>
+                    vm.MainWindows.ActiveWindow.CurrentValue.PlatformWindowService.Maximize(false),
+                    DispatcherPriority.Background);
+            }
         }
         else if (Settings.WindowProperties.Fullscreen)
         {
-            // Dispatcher.UIThread.InvokeAsync(() => { vm.PlatformWindowService.Fullscreen(false); },
-            //     DispatcherPriority.Background);
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                vm.MainWindows.ActiveWindow.CurrentValue.PlatformWindowService.Fullscreen(false);
+            }
+            else
+            {
+                Dispatcher.UIThread.Post(() =>
+                    vm.MainWindows.ActiveWindow.CurrentValue.PlatformWindowService.Fullscreen(false),
+                    DispatcherPriority.Background);
+            }
         }
 
         if (Settings.UIProperties.ShowHoverNavigationBar)
@@ -312,7 +320,7 @@ public static class StartUpHelper2
         }
     }
 
-    private static void HandleAutoFit(MainWindowViewModel vm, Window window)
+    private static void HandleAutoFit(MainWindowViewModel vm, MainWindow window)
     {
         WindowFunctions2.SetAutoFit(vm, window);
         vm.IsAutoFit.Value = true;

+ 1 - 5
src/PicView.Avalonia/WindowBehavior/WindowFunctions2.cs

@@ -33,7 +33,7 @@ public static class WindowFunctions2
     {
         WindowResizing2.SaveSize(window);
 
-        if (Application.Current?.DataContext is not CoreViewModel core)
+        if (Application.Current.DataContext is not CoreViewModel core)
         {
             return;
         }
@@ -268,10 +268,6 @@ public static class WindowFunctions2
         Dispatcher.UIThread.Post(() =>
         {
             window ??= desktop.MainWindow;
-            if (window.WindowState is WindowState.Maximized or WindowState.FullScreen)
-            {
-                return;
-            }
 
             ScreenHelper.UpdateScreenSize(window);
             var screen = ScreenHelper.ScreenSize;

+ 21 - 19
src/PicView.Avalonia/WindowBehavior/WindowResizing2.cs

@@ -169,10 +169,24 @@ public static class WindowResizing2
         vm.ScrollViewerWidth.Value = size.ScrollViewerWidth;
         vm.ScrollViewerHeight.Value = size.ScrollViewerHeight;
         var rotationAngle = vm.WindowTabs.ActiveTab.CurrentValue.RotationAngle.CurrentValue;
-        if (Settings.WindowProperties.Maximized || Settings.WindowProperties.Fullscreen)
+        var isRotated = rotationAngle is 90 or 270;
+
+        var imageWidth = isRotated ? size.Height : size.Width;
+        var imageHeight = isRotated ? size.Width : size.Height;
+
+        if (Settings.WindowProperties.Fullscreen)
         {
-            vm.WindowMaxWidth.Value = vm.WindowMaxHeight.Value =
-            vm.ImageWidth.Value = vm.ImageHeight.Value = double.NaN;
+            vm.WindowMaxWidth.Value = ScreenHelper.ScreenSize.Width;
+            vm.WindowMaxHeight.Value = ScreenHelper.ScreenSize.Height;
+            vm.ImageWidth.Value = imageWidth;
+            vm.ImageHeight.Value = imageHeight;
+        }
+        else if (Settings.WindowProperties.Maximized)
+        {
+            vm.WindowMaxWidth.Value = ScreenHelper.ScreenSize.WorkingAreaWidth;
+            vm.WindowMaxHeight.Value = ScreenHelper.ScreenSize.WorkingAreaHeight;
+            vm.ImageWidth.Value = imageWidth;
+            vm.ImageHeight.Value = imageHeight;
         }
         else if (Settings.WindowProperties.AutoFit)
         {
@@ -183,22 +197,10 @@ public static class WindowResizing2
             }
             else
             {
-                if (rotationAngle is 90 or 270)
-                {
-                    vm.WindowMaxWidth.Value = size.WindowHeight;
-                    vm.WindowMaxHeight.Value = size.WindowWidth;
-
-                    vm.ImageWidth.Value = size.Height;
-                    vm.ImageHeight.Value = size.Width;
-                }
-                else
-                {
-                    vm.WindowMaxWidth.Value = size.WindowWidth;
-                    vm.WindowMaxHeight.Value = size.WindowHeight;
-
-                    vm.ImageWidth.Value = size.Width;
-                    vm.ImageHeight.Value = size.Height;
-                }
+                vm.WindowMaxWidth.Value = isRotated ? size.WindowHeight : size.WindowWidth;
+                vm.WindowMaxHeight.Value = isRotated ? size.WindowWidth : size.WindowHeight;
+                vm.ImageWidth.Value = imageWidth;
+                vm.ImageHeight.Value = imageHeight;
             }
         }
         else