Browse Source

UI: Fix some MainWindow bugs and implement menubar items to change window size. (#6750)

* Do not save window dimensions when maximized.

* Implement option to disable window size/position memory.

* Remove logging statements

* Implement menubar items for common window sizes.

* formatting fixes

* Set 720p window as a composite value.

* Remove unused using

* Fix exception paramter.

* Force restore window when a size change is requested

* Fix some resizing bugs.
MutantAura 1 year ago
parent
commit
d0cc13ce0b

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

@@ -15,7 +15,7 @@ namespace Ryujinx.UI.Common.Configuration
         /// <summary>
         /// The current version of the file format
         /// </summary>
-        public const int CurrentVersion = 50;
+        public const int CurrentVersion = 51;
 
         /// <summary>
         /// Version of the configuration file format
@@ -162,6 +162,11 @@ namespace Ryujinx.UI.Common.Configuration
         /// </summary>
         public bool ShowConfirmExit { get; set; }
 
+        /// <summary>
+        /// Enables or disables save window size, position and state on close.
+        /// </summary>
+        public bool RememberWindowState { get; set; }
+
         /// <summary>
         /// Enables hardware-accelerated rendering for Avalonia
         /// </summary>

+ 18 - 0
src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs

@@ -626,6 +626,11 @@ namespace Ryujinx.UI.Common.Configuration
         /// </summary>
         public ReactiveObject<bool> ShowConfirmExit { get; private set; }
 
+        /// <summary>
+        /// Enables or disables save window size, position and state on close.
+        /// </summary>
+        public ReactiveObject<bool> RememberWindowState { get; private set; }
+
         /// <summary>
         /// Enables hardware-accelerated rendering for Avalonia
         /// </summary>
@@ -647,6 +652,7 @@ namespace Ryujinx.UI.Common.Configuration
             EnableDiscordIntegration = new ReactiveObject<bool>();
             CheckUpdatesOnStart = new ReactiveObject<bool>();
             ShowConfirmExit = new ReactiveObject<bool>();
+            RememberWindowState = new ReactiveObject<bool>();
             EnableHardwareAcceleration = new ReactiveObject<bool>();
             HideCursor = new ReactiveObject<HideCursorMode>();
         }
@@ -684,6 +690,7 @@ namespace Ryujinx.UI.Common.Configuration
                 EnableDiscordIntegration = EnableDiscordIntegration,
                 CheckUpdatesOnStart = CheckUpdatesOnStart,
                 ShowConfirmExit = ShowConfirmExit,
+                RememberWindowState = RememberWindowState,
                 EnableHardwareAcceleration = EnableHardwareAcceleration,
                 HideCursor = HideCursor,
                 EnableVsync = Graphics.EnableVsync,
@@ -792,6 +799,7 @@ namespace Ryujinx.UI.Common.Configuration
             EnableDiscordIntegration.Value = true;
             CheckUpdatesOnStart.Value = true;
             ShowConfirmExit.Value = true;
+            RememberWindowState.Value = true;
             EnableHardwareAcceleration.Value = true;
             HideCursor.Value = HideCursorMode.OnIdle;
             Graphics.EnableVsync.Value = true;
@@ -1459,6 +1467,15 @@ namespace Ryujinx.UI.Common.Configuration
                 configurationFileUpdated = true;
             }
 
+            if (configurationFileFormat.Version < 51)
+            {
+                Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 51.");
+
+                configurationFileFormat.RememberWindowState = true;
+
+                configurationFileUpdated = true;
+            }
+
             Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
             Graphics.ResScale.Value = configurationFileFormat.ResScale;
             Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
@@ -1489,6 +1506,7 @@ namespace Ryujinx.UI.Common.Configuration
             EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
             CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
             ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
+            RememberWindowState.Value = configurationFileFormat.RememberWindowState;
             EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration;
             HideCursor.Value = configurationFileFormat.HideCursor;
             Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;

+ 5 - 0
src/Ryujinx/Assets/Locales/en_US.json

@@ -30,6 +30,10 @@
   "MenuBarToolsManageFileTypes": "Manage file types",
   "MenuBarToolsInstallFileTypes": "Install file types",
   "MenuBarToolsUninstallFileTypes": "Uninstall file types",
+  "MenuBarView": "_View",
+  "MenuBarViewWindow": "Window Size",
+  "MenuBarViewWindow720": "720p",
+  "MenuBarViewWindow1080": "1080p",
   "MenuBarHelp": "_Help",
   "MenuBarHelpCheckForUpdates": "Check for Updates",
   "MenuBarHelpAbout": "About",
@@ -92,6 +96,7 @@
   "SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence",
   "SettingsTabGeneralCheckUpdatesOnLaunch": "Check for Updates on Launch",
   "SettingsTabGeneralShowConfirmExitDialog": "Show \"Confirm Exit\" Dialog",
+  "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
   "SettingsTabGeneralHideCursor": "Hide Cursor:",
   "SettingsTabGeneralHideCursorNever": "Never",
   "SettingsTabGeneralHideCursorOnIdle": "On Idle",

+ 3 - 0
src/Ryujinx/UI/ViewModels/SettingsViewModel.cs

@@ -131,6 +131,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         public bool EnableDiscordIntegration { get; set; }
         public bool CheckUpdatesOnStart { get; set; }
         public bool ShowConfirmExit { get; set; }
+        public bool RememberWindowState { get; set; }
         public int HideCursor { get; set; }
         public bool EnableDockedMode { get; set; }
         public bool EnableKeyboard { get; set; }
@@ -390,6 +391,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             EnableDiscordIntegration = config.EnableDiscordIntegration;
             CheckUpdatesOnStart = config.CheckUpdatesOnStart;
             ShowConfirmExit = config.ShowConfirmExit;
+            RememberWindowState = config.RememberWindowState;
             HideCursor = (int)config.HideCursor.Value;
 
             GameDirectories.Clear();
@@ -474,6 +476,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
             config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
             config.ShowConfirmExit.Value = ShowConfirmExit;
+            config.RememberWindowState.Value = RememberWindowState;
             config.HideCursor.Value = (HideCursorMode)HideCursor;
 
             if (_directoryChanged)

+ 6 - 0
src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml

@@ -186,6 +186,12 @@
                     <MenuItem Header="{locale:Locale MenuBarToolsUninstallFileTypes}" Click="UninstallFileTypes_Click"/>
                 </MenuItem>
             </MenuItem>
+            <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarView}">
+                <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarViewWindow}">
+                    <MenuItem Header="{locale:Locale MenuBarViewWindow720}" Tag="720" Click="ChangeWindowSize_Click" />
+                    <MenuItem Header="{locale:Locale MenuBarViewWindow1080}" Tag="1080" Click="ChangeWindowSize_Click" />
+                </MenuItem>
+            </MenuItem>
             <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarHelp}">
                 <MenuItem
                     Name="UpdateMenuItem"

+ 35 - 0
src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs

@@ -1,6 +1,7 @@
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Interactivity;
+using Avalonia.Threading;
 using LibHac.Ncm;
 using LibHac.Tools.FsSystem.NcaUtils;
 using Ryujinx.Ava.Common.Locale;
@@ -211,6 +212,40 @@ namespace Ryujinx.Ava.UI.Views.Main
             }
         }
 
+        private async void ChangeWindowSize_Click(object sender, RoutedEventArgs e)
+        {
+            if (sender is MenuItem item)
+            {
+                int height;
+                int width;
+
+                switch (item.Tag)
+                {
+                    case "720":
+                        height = 720;
+                        width = 1280;
+                        break;
+
+                    case "1080":
+                        height = 1080;
+                        width = 1920;
+                        break;
+
+                    default:
+                        throw new ArgumentNullException($"Invalid Tag for {item}");
+                }
+
+                await Dispatcher.UIThread.InvokeAsync(() =>
+                {
+                    ViewModel.WindowState = WindowState.Normal;
+
+                    height += (int)Window.StatusBarHeight + (int)Window.MenuBarHeight;
+
+                    Window.Arrange(new Rect(Window.Position.X, Window.Position.Y, width, height));
+                });
+            }
+        }
+
         public async void CheckForUpdates(object sender, RoutedEventArgs e)
         {
             if (Updater.CanUpdate(true))

+ 3 - 0
src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml

@@ -36,6 +36,9 @@
                     <CheckBox IsChecked="{Binding ShowConfirmExit}">
                         <TextBlock Text="{locale:Locale SettingsTabGeneralShowConfirmExitDialog}" />
                     </CheckBox>
+                    <CheckBox IsChecked="{Binding RememberWindowState}">
+                        <TextBlock Text="{locale:Locale SettingsTabGeneralRememberWindowState}" />
+                    </CheckBox>
                     <StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
                         <TextBlock VerticalAlignment="Center"
                                    Text="{locale:Locale SettingsTabGeneralHideCursor}"

+ 26 - 8
src/Ryujinx/UI/Windows/MainWindow.axaml.cs

@@ -67,8 +67,6 @@ namespace Ryujinx.Ava.UI.Windows
 
             DataContext = ViewModel;
 
-            SetWindowSizePosition();
-
             InitializeComponent();
             Load();
 
@@ -83,6 +81,8 @@ namespace Ryujinx.Ava.UI.Windows
             Height = ((Height - barHeight) / Program.WindowScaleFactor) + barHeight;
             Width /= Program.WindowScaleFactor;
 
+            SetWindowSizePosition();
+
             if (Program.PreviewerDetached)
             {
                 InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
@@ -324,6 +324,17 @@ namespace Ryujinx.Ava.UI.Windows
 
         private void SetWindowSizePosition()
         {
+            if (!ConfigurationState.Instance.RememberWindowState)
+            {
+                ViewModel.WindowHeight = (720 + StatusBarHeight + MenuBarHeight) * Program.WindowScaleFactor;
+                ViewModel.WindowWidth = 1280 * Program.WindowScaleFactor;
+
+                WindowState = WindowState.Normal;
+                WindowStartupLocation = WindowStartupLocation.CenterScreen;
+
+                return;
+            }
+
             PixelPoint savedPoint = new(ConfigurationState.Instance.UI.WindowStartup.WindowPositionX,
                                         ConfigurationState.Instance.UI.WindowStartup.WindowPositionY);
 
@@ -358,13 +369,17 @@ namespace Ryujinx.Ava.UI.Windows
 
         private void SaveWindowSizePosition()
         {
-            ConfigurationState.Instance.UI.WindowStartup.WindowSizeHeight.Value = (int)Height;
-            ConfigurationState.Instance.UI.WindowStartup.WindowSizeWidth.Value = (int)Width;
+            ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
 
-            ConfigurationState.Instance.UI.WindowStartup.WindowPositionX.Value = Position.X;
-            ConfigurationState.Instance.UI.WindowStartup.WindowPositionY.Value = Position.Y;
+            // Only save rectangle properties if the window is not in a maximized state.
+            if (WindowState != WindowState.Maximized)
+            {
+                ConfigurationState.Instance.UI.WindowStartup.WindowSizeHeight.Value = (int)Height;
+                ConfigurationState.Instance.UI.WindowStartup.WindowSizeWidth.Value = (int)Width;
 
-            ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
+                ConfigurationState.Instance.UI.WindowStartup.WindowPositionX.Value = Position.X;
+                ConfigurationState.Instance.UI.WindowStartup.WindowPositionY.Value = Position.Y;
+            }
 
             MainWindowViewModel.SaveConfig();
         }
@@ -477,7 +492,10 @@ namespace Ryujinx.Ava.UI.Windows
                 return;
             }
 
-            SaveWindowSizePosition();
+            if (ConfigurationState.Instance.RememberWindowState)
+            {
+                SaveWindowSizePosition();
+            }
 
             ApplicationLibrary.CancelLoading();
             InputManager.Dispose();