Просмотр исходного кода

Allow window to remember its size, position and state (GTK + Avalonia) (#4657)

* Update ConfigurationState.cs

* Update ConfigurationFileFormat.cs

* Update MainWindow.cs

* Update ConfigurationFileFormat.cs

* Update ConfigurationState.cs

* Update MainWindow.cs

* Update MainWindow.cs

* Update Ryujinx.Ui.Common/Configuration/ConfigurationState.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update MainWindow.cs

* Update Ryujinx/Ui/MainWindow.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Initial properties

* Viewmodel adjustments and additions

* abstract and monitor dimension changes

* Remove position from ViewModel and simplify methods

* Remove unused dep

* Update configuration and fix typo from AA

* review changes

* Review changes

* Screensize checks - Ava

* Review changes 2

* basic review changes

* Standardise GTK/Ava functions

* Actually call function

---------

Co-authored-by: HaizenTrist <123991082+HaizenTrist@users.noreply.github.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
MutantAura 3 лет назад
Родитель
Сommit
21c4176157

+ 25 - 0
src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

@@ -95,6 +95,9 @@ namespace Ryujinx.Ava.UI.ViewModels
         private string _currentEmulatedGamePath;
         private AutoResetEvent _rendererWaitEvent;
         private WindowState _windowState;
+        private double _windowWidth;
+        private double _windowHeight;
+
         private bool _isActive;
 
         public ApplicationData ListSelectedApplication;
@@ -622,6 +625,28 @@ namespace Ryujinx.Ava.UI.ViewModels
                 OnPropertyChanged();
             }
         }
+        
+        public double WindowWidth
+        {
+            get => _windowWidth;
+            set
+            {
+                _windowWidth = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public double WindowHeight
+        {
+            get => _windowHeight;
+            set
+            {
+                _windowHeight = value;
+
+                OnPropertyChanged();
+            }
+        }
 
         public bool IsGrid => Glyph == Glyph.Grid;
         public bool IsList => Glyph == Glyph.List;

+ 2 - 3
src/Ryujinx.Ava/UI/Windows/MainWindow.axaml

@@ -12,15 +12,14 @@
     Cursor="{Binding Cursor}"
     Title="{Binding Title}"
     WindowState="{Binding WindowState}"
-    Width="1280"
-    Height="777"
+    Width="{Binding WindowWidth}"
+    Height="{Binding WindowHeight}"
     MinWidth="1092"
     MinHeight="672"
     d:DesignHeight="720"
     d:DesignWidth="1280"
     x:CompileBindings="True"
     x:DataType="viewModels:MainWindowViewModel"
-    WindowStartupLocation="CenterScreen"
     mc:Ignorable="d"
     Focusable="True">
     <Window.Styles>

+ 49 - 0
src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

@@ -62,6 +62,8 @@ namespace Ryujinx.Ava.UI.Windows
 
             DataContext = ViewModel;
 
+            SetWindowSizePosition();
+
             InitializeComponent();
             Load();
 
@@ -297,6 +299,51 @@ namespace Ryujinx.Ava.UI.Windows
             LoadHotKeys();
         }
 
+        private void SetWindowSizePosition()
+        {
+            PixelPoint SavedPoint = new PixelPoint(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX, 
+                                                   ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY);
+
+            ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor;
+            ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor;
+
+            ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value is true ? WindowState.Maximized : WindowState.Normal;
+        
+            if (CheckScreenBounds(SavedPoint))
+            {
+                Position = SavedPoint;
+            }
+
+            else WindowStartupLocation = WindowStartupLocation.CenterScreen;
+        }
+
+        private bool CheckScreenBounds(PixelPoint configPoint)
+        {   
+            for (int i = 0; i < Screens.ScreenCount; i++)
+            {
+                if (Screens.All[i].Bounds.Contains(configPoint))
+                {
+                    return true;
+                }
+            }
+
+            Logger.Warning?.Print(LogClass.Application, $"Failed to find valid start-up coordinates. Defaulting to primary monitor center.");
+            return false;
+        }
+
+        private void SaveWindowSizePosition()
+        {
+            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight.Value = (int)Height;
+            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth.Value = (int)Width;
+
+            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX.Value = Position.X;
+            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY.Value = Position.Y;
+
+            ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
+
+            MainWindowViewModel.SaveConfig();
+        }
+
         protected override void OnOpened(EventArgs e)
         {
             base.OnOpened(e);
@@ -388,6 +435,8 @@ namespace Ryujinx.Ava.UI.Windows
                 return;
             }
 
+            SaveWindowSizePosition();
+
             ApplicationLibrary.CancelLoading();
             InputManager.Dispose();
             Program.Exit();

+ 6 - 1
src/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs

@@ -14,7 +14,7 @@ namespace Ryujinx.Ui.Common.Configuration
         /// <summary>
         /// The current version of the file format
         /// </summary>
-        public const int CurrentVersion = 46;
+        public const int CurrentVersion = 47;
 
         /// <summary>
         /// Version of the configuration file format
@@ -251,6 +251,11 @@ namespace Ryujinx.Ui.Common.Configuration
         /// </summary>
         public ShownFileTypes ShownFileTypes { get; set; }
 
+        /// <summary>
+        /// Main window start-up position, size and state
+        /// </summary>
+        public WindowStartup WindowStartup { get; set; }
+
         /// <summary>
         /// Language Code for the UI
         /// </summary>

+ 65 - 4
src/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs

@@ -83,6 +83,27 @@ namespace Ryujinx.Ui.Common.Configuration
                 }
             }
 
+            // <summary>
+            /// Determines main window start-up position, size and state
+            ///<summary>
+            public class WindowStartupSettings
+            {
+                public ReactiveObject<int> WindowSizeWidth { get; private set; }
+                public ReactiveObject<int> WindowSizeHeight { get; private set; }
+                public ReactiveObject<int> WindowPositionX { get; private set; }
+                public ReactiveObject<int> WindowPositionY { get; private set; }
+                public ReactiveObject<bool> WindowMaximized { get; private set; }
+
+                public WindowStartupSettings()
+                {
+                    WindowSizeWidth = new ReactiveObject<int>();
+                    WindowSizeHeight = new ReactiveObject<int>();
+                    WindowPositionX = new ReactiveObject<int>();
+                    WindowPositionY = new ReactiveObject<int>();
+                    WindowMaximized = new ReactiveObject<bool>();
+                }
+            }
+
             /// <summary>
             /// Used to toggle columns in the GUI
             /// </summary>
@@ -103,6 +124,11 @@ namespace Ryujinx.Ui.Common.Configuration
             /// </summary>
             public ShownFileTypeSettings ShownFileTypes { get; private set; }
 
+            /// <summary>
+            /// Determines main window start-up position, size and state
+            /// </summary>
+            public WindowStartupSettings WindowStartup { get; private set; }
+
             /// <summary>
             /// Language Code for the UI
             /// </summary>
@@ -163,7 +189,8 @@ namespace Ryujinx.Ui.Common.Configuration
                 GuiColumns        = new Columns();
                 ColumnSort        = new ColumnSortSettings();
                 GameDirs          = new ReactiveObject<List<string>>();
-                ShownFileTypes   = new ShownFileTypeSettings();
+                ShownFileTypes    = new ShownFileTypeSettings();
+                WindowStartup     = new WindowStartupSettings();
                 EnableCustomTheme = new ReactiveObject<bool>();
                 CustomThemePath   = new ReactiveObject<string>();
                 BaseStyle         = new ReactiveObject<string>();
@@ -663,12 +690,12 @@ namespace Ryujinx.Ui.Common.Configuration
                     FileSizeColumn   = Ui.GuiColumns.FileSizeColumn,
                     PathColumn       = Ui.GuiColumns.PathColumn
                 },
-                ColumnSort                 = new ColumnSort
+                ColumnSort                = new ColumnSort
                 {
                     SortColumnId  = Ui.ColumnSort.SortColumnId,
                     SortAscending = Ui.ColumnSort.SortAscending
                 },
-                GameDirs                   = Ui.GameDirs,
+                GameDirs                  = Ui.GameDirs,
                 ShownFileTypes            = new ShownFileTypes
                 {
                     NSP = Ui.ShownFileTypes.NSP,
@@ -678,6 +705,14 @@ namespace Ryujinx.Ui.Common.Configuration
                     NRO = Ui.ShownFileTypes.NRO,
                     NSO = Ui.ShownFileTypes.NSO,
                 },
+                WindowStartup              = new WindowStartup
+                {
+                    WindowSizeWidth = Ui.WindowStartup.WindowSizeWidth,
+                    WindowSizeHeight = Ui.WindowStartup.WindowSizeHeight,
+                    WindowPositionX = Ui.WindowStartup.WindowPositionX,
+                    WindowPositionY = Ui.WindowStartup.WindowPositionY,
+                    WindowMaximized = Ui.WindowStartup.WindowMaximized,
+                },
                 LanguageCode               = Ui.LanguageCode,
                 EnableCustomTheme          = Ui.EnableCustomTheme,
                 CustomThemePath            = Ui.CustomThemePath,
@@ -781,6 +816,11 @@ namespace Ryujinx.Ui.Common.Configuration
             Ui.IsAscendingOrder.Value                 = true;
             Ui.StartFullscreen.Value                  = false;
             Ui.ShowConsole.Value                      = true;
+            Ui.WindowStartup.WindowSizeWidth.Value    = 1280;
+            Ui.WindowStartup.WindowSizeHeight.Value   = 760;
+            Ui.WindowStartup.WindowPositionX.Value    = 0;
+            Ui.WindowStartup.WindowPositionY.Value    = 0;
+            Ui.WindowStartup.WindowMaximized.Value    = false;
             Hid.EnableKeyboard.Value                  = false;
             Hid.EnableMouse.Value                     = false;
             Hid.Hotkeys.Value = new KeyboardHotkeys
@@ -1334,13 +1374,29 @@ namespace Ryujinx.Ui.Common.Configuration
 
             if (configurationFileFormat.Version < 46)
             {
-                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45.");
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46.");
 
                 configurationFileFormat.MultiplayerLanInterfaceId = "0";
 
                 configurationFileUpdated = true;
             }
 
+            if (configurationFileFormat.Version < 47)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47.");
+
+                configurationFileFormat.WindowStartup = new WindowStartup
+                {
+                    WindowPositionX = 0,
+                    WindowPositionY = 0,
+                    WindowSizeHeight = 760,
+                    WindowSizeWidth = 1280,
+                    WindowMaximized = false,
+                };
+                
+                configurationFileUpdated = true;
+            }
+
             Logger.EnableFileLog.Value                = configurationFileFormat.EnableFileLog;
             Graphics.ResScale.Value                   = configurationFileFormat.ResScale;
             Graphics.ResScaleCustom.Value             = configurationFileFormat.ResScaleCustom;
@@ -1416,6 +1472,11 @@ namespace Ryujinx.Ui.Common.Configuration
             Ui.ApplicationSort.Value                  = configurationFileFormat.ApplicationSort;
             Ui.StartFullscreen.Value                  = configurationFileFormat.StartFullscreen;
             Ui.ShowConsole.Value                      = configurationFileFormat.ShowConsole;
+            Ui.WindowStartup.WindowSizeWidth.Value    = configurationFileFormat.WindowStartup.WindowSizeWidth;
+            Ui.WindowStartup.WindowSizeHeight.Value   = configurationFileFormat.WindowStartup.WindowSizeHeight;
+            Ui.WindowStartup.WindowPositionX.Value    = configurationFileFormat.WindowStartup.WindowPositionX;
+            Ui.WindowStartup.WindowPositionY.Value    = configurationFileFormat.WindowStartup.WindowPositionY;
+            Ui.WindowStartup.WindowMaximized.Value    = configurationFileFormat.WindowStartup.WindowMaximized;
             Hid.EnableKeyboard.Value                  = configurationFileFormat.EnableKeyboard;
             Hid.EnableMouse.Value                     = configurationFileFormat.EnableMouse;
             Hid.Hotkeys.Value                         = configurationFileFormat.Hotkeys;

+ 11 - 0
src/Ryujinx.Ui.Common/Configuration/Ui/WindowStartup.cs

@@ -0,0 +1,11 @@
+namespace Ryujinx.Ui.Common.Configuration.Ui
+{
+    public struct WindowStartup
+    {
+        public int WindowSizeWidth { get; set; }
+        public int WindowSizeHeight { get; set; }
+        public int WindowPositionX { get; set; }
+        public int WindowPositionY { get; set; }
+        public bool WindowMaximized { get; set; }
+    }
+}

+ 31 - 7
src/Ryujinx/Ui/MainWindow.cs

@@ -153,13 +153,8 @@ namespace Ryujinx.Ui
 
             // Apply custom theme if needed.
             ThemeHelper.ApplyTheme();
-            Gdk.Monitor monitor = Display.GetMonitor(0);
-            // Sets overridden fields.
-            int monitorWidth  = monitor.Geometry.Width  * monitor.ScaleFactor;
-            int monitorHeight = monitor.Geometry.Height * monitor.ScaleFactor;
 
-            DefaultWidth  = monitorWidth  < 1280 ? monitorWidth  : 1280;
-            DefaultHeight = monitorHeight < 760  ? monitorHeight : 760;
+            SetWindowSizePosition();
 
             Icon  = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
             Title = $"Ryujinx {Program.Version}";
@@ -1314,6 +1309,7 @@ namespace Ryujinx.Ui
         {
             if (!_gameLoaded || !ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
             {
+                SaveWindowSizePosition();
                 End();
             }
         }
@@ -1322,6 +1318,7 @@ namespace Ryujinx.Ui
         {
             if (!_gameLoaded || !ConfigurationState.Instance.ShowConfirmExit || GtkDialog.CreateExitDialog())
             {
+                SaveWindowSizePosition();        
                 End();
             }
             else
@@ -1330,6 +1327,33 @@ namespace Ryujinx.Ui
             }
         }
 
+        private void SetWindowSizePosition()
+        {
+            DefaultWidth  = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth;
+            DefaultHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight;
+
+            Move(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX, ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY);
+
+            if (ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized) 
+            { 
+                Maximize(); 
+            }
+        }
+
+        private void SaveWindowSizePosition()
+        {
+            GetSize(out int windowWidth, out int windowHeight);
+            GetPosition(out int windowXPos, out int windowYPos);
+
+            ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value = IsMaximized;
+            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth.Value = windowWidth;
+            ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight.Value = windowHeight;
+            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX.Value = windowXPos;
+            ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY.Value = windowYPos;
+
+            SaveConfig();        
+        }
+
         private void StopEmulation_Pressed(object sender, EventArgs args)
         {
             if (_emulationContext != null)
@@ -1831,4 +1855,4 @@ namespace Ryujinx.Ui
             UpdateGameTable();
         }
     }
-}
+}