diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs index 79993d879f..901c823e5a 100644 --- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs +++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Configuration /// /// The current version of the file format /// - public const int CurrentVersion = 20; + public const int CurrentVersion = 22; public int Version { get; set; } @@ -133,6 +133,11 @@ namespace Ryujinx.Configuration /// public bool ShowConfirmExit { get; set; } + /// + /// Hide Cursor on Idle + /// + public bool HideCursorOnIdle { get; set; } + /// /// Enables or disables Vertical Sync /// @@ -253,4 +258,4 @@ namespace Ryujinx.Configuration JsonHelper.Serialize(fileStream, this, true); } } -} \ No newline at end of file +} diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs index 61cc8f899e..d51ee9efc6 100644 --- a/Ryujinx.Common/Configuration/ConfigurationState.cs +++ b/Ryujinx.Common/Configuration/ConfigurationState.cs @@ -365,6 +365,11 @@ namespace Ryujinx.Configuration /// public ReactiveObject ShowConfirmExit { get; private set; } + /// + /// Hide Cursor on Idle + /// + public ReactiveObject HideCursorOnIdle { get; private set; } + private ConfigurationState() { Ui = new UiSection(); @@ -375,6 +380,7 @@ namespace Ryujinx.Configuration EnableDiscordIntegration = new ReactiveObject(); CheckUpdatesOnStart = new ReactiveObject(); ShowConfirmExit = new ReactiveObject(); + HideCursorOnIdle = new ReactiveObject(); } public ConfigurationFileFormat ToFileFormat() @@ -420,6 +426,7 @@ namespace Ryujinx.Configuration EnableDiscordIntegration = EnableDiscordIntegration, CheckUpdatesOnStart = CheckUpdatesOnStart, ShowConfirmExit = ShowConfirmExit, + HideCursorOnIdle = HideCursorOnIdle, EnableVsync = Graphics.EnableVsync, EnableShaderCache = Graphics.EnableShaderCache, EnablePtc = System.EnablePtc, @@ -483,6 +490,7 @@ namespace Ryujinx.Configuration EnableDiscordIntegration.Value = true; CheckUpdatesOnStart.Value = true; ShowConfirmExit.Value = true; + HideCursorOnIdle.Value = false; Graphics.EnableVsync.Value = true; Graphics.EnableShaderCache.Value = true; System.EnablePtc.Value = true; @@ -787,6 +795,15 @@ namespace Ryujinx.Configuration configurationFileUpdated = true; } + if (configurationFileFormat.Version < 22) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22."); + + configurationFileFormat.HideCursorOnIdle = false; + + configurationFileUpdated = true; + } + List inputConfig = new List(); inputConfig.AddRange(configurationFileFormat.ControllerConfig); inputConfig.AddRange(configurationFileFormat.KeyboardConfig); @@ -814,6 +831,7 @@ namespace Ryujinx.Configuration EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; + HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; System.EnablePtc.Value = configurationFileFormat.EnablePtc; diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json index 76c0a139aa..804b020c4d 100644 --- a/Ryujinx/Config.json +++ b/Ryujinx/Config.json @@ -1,5 +1,5 @@ { - "version": 20, + "version": 22, "res_scale": 1, "res_scale_custom": 1, "max_anisotropy": -1, @@ -22,6 +22,7 @@ "enable_discord_integration": true, "check_updates_on_start": true, "show_confirm_exit": true, + "hide_cursor_on_idle": false, "enable_vsync": true, "enable_shader_cache": true, "enable_ptc": true, diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs index 35c00a332f..52dcedbc9a 100644 --- a/Ryujinx/Ui/GLRenderer.cs +++ b/Ryujinx/Ui/GLRenderer.cs @@ -42,6 +42,8 @@ namespace Ryujinx.Ui private double _mouseY; private bool _mousePressed; + private DateTime _lastCursorMoveTime = DateTime.Now; + private bool _toggleFullscreen; private bool _toggleDockedMode; @@ -62,6 +64,8 @@ namespace Ryujinx.Ui private GraphicsDebugLevel _glLogLevel; private readonly ManualResetEvent _exitEvent; + + private Gdk.Cursor _invisibleCursor = new Gdk.Cursor (Gdk.Display.Default, Gdk.CursorType.BlankCursor); public GlRenderer(Switch device, GraphicsDebugLevel glLogLevel) : base (GetGraphicsMode(), @@ -304,9 +308,37 @@ namespace Ryujinx.Ui _mouseY = evnt.Y; } + ResetCursorIdle(); + return false; } + private void ResetCursorIdle() + { + if (ConfigurationState.Instance.HideCursorOnIdle) + { + _lastCursorMoveTime = DateTime.Now; + } + + if (Window.Cursor != null) + { + Window.Cursor = null; + } + } + + private void HideCursorIdle() + { + if (ConfigurationState.Instance.HideCursorOnIdle) + { + TimeSpan elapsedTime = DateTime.Now.Subtract(_lastCursorMoveTime); + + if (elapsedTime.TotalSeconds > 8) + { + Gtk.Application.Invoke(delegate { Window.Cursor = _invisibleCursor; }); + } + } + } + protected override void OnGetPreferredHeight(out int minimumHeight, out int naturalHeight) { Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window); @@ -485,6 +517,8 @@ namespace Ryujinx.Ui MotionDevice motionDevice = new MotionDevice(_dsuClient); + HideCursorIdle(); + foreach (InputConfig inputConfig in ConfigurationState.Instance.Hid.InputConfig.Value) { ControllerKeys currentButton = 0; diff --git a/Ryujinx/Ui/Windows/SettingsWindow.cs b/Ryujinx/Ui/Windows/SettingsWindow.cs index ba64226c37..e839a366c6 100644 --- a/Ryujinx/Ui/Windows/SettingsWindow.cs +++ b/Ryujinx/Ui/Windows/SettingsWindow.cs @@ -43,6 +43,7 @@ namespace Ryujinx.Ui.Windows [GUI] CheckButton _discordToggle; [GUI] CheckButton _checkUpdatesToggle; [GUI] CheckButton _showConfirmExitToggle; + [GUI] CheckButton _hideCursorOnIdleToggle; [GUI] CheckButton _vSyncToggle; [GUI] CheckButton _shaderCacheToggle; [GUI] CheckButton _ptcToggle; @@ -185,6 +186,11 @@ namespace Ryujinx.Ui.Windows _showConfirmExitToggle.Click(); } + if (ConfigurationState.Instance.HideCursorOnIdle) + { + _hideCursorOnIdleToggle.Click(); + } + if (ConfigurationState.Instance.Graphics.EnableVsync) { _vSyncToggle.Click(); @@ -403,6 +409,7 @@ namespace Ryujinx.Ui.Windows ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active; ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active; + ConfigurationState.Instance.HideCursorOnIdle.Value = _hideCursorOnIdleToggle.Active; ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active; ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active; @@ -582,4 +589,4 @@ namespace Ryujinx.Ui.Windows Dispose(); } } -} \ No newline at end of file +} diff --git a/Ryujinx/Ui/Windows/SettingsWindow.glade b/Ryujinx/Ui/Windows/SettingsWindow.glade index 5ead8dd820..e9d241f80b 100644 --- a/Ryujinx/Ui/Windows/SettingsWindow.glade +++ b/Ryujinx/Ui/Windows/SettingsWindow.glade @@ -150,7 +150,23 @@ False True 5 - 1 + 2 + + + + + Hide Cursor On Idle + True + True + False + start + True + + + False + True + 5 + 3 diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json index eff1f9d4cf..b61e9ed259 100644 --- a/Ryujinx/_schema.json +++ b/Ryujinx/_schema.json @@ -1209,6 +1209,17 @@ true, false ] + }, + "hide_cursor_on_idle": { + "$id": "#/properties/hide_cursor_on_idle", + "type": "boolean", + "title": "Hide Cursor On Idle", + "description": "Hides the cursor after being idle for 5 seconds", + "default": false, + "examples": [ + true, + false + ] }, "enable_vsync": { "$id": "#/properties/enable_vsync",