Add hide-cursor command line argument & always hide cursor option (#4613)

* Add hide-cursor command line argument

* gtk: Adjust SettingsWindow for hide cursor options

* ava: Adjust SettingsWindow for hide cursor options

* ava: Add override check for HideCursor arg

* Remove copy&paste sins

* ava: Leave a little more room between the options

* gtk: Fix hide cursor issues

* ava: Only hide cursor if it's within the embedded window
This commit is contained in:
TSRBerry 2023-05-02 03:29:47 +02:00 committed by GitHub
parent 2c94ac455e
commit dd574146fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 266 additions and 99 deletions

View file

@ -157,7 +157,7 @@ namespace Ryujinx.Ava
_isFirmwareTitle = true; _isFirmwareTitle = true;
} }
ConfigurationState.Instance.HideCursorOnIdle.Event += HideCursorState_Changed; ConfigurationState.Instance.HideCursor.Event += HideCursorState_Changed;
_topLevel.PointerMoved += TopLevel_PointerMoved; _topLevel.PointerMoved += TopLevel_PointerMoved;
@ -468,9 +468,9 @@ namespace Ryujinx.Ava
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null); (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null);
} }
private void HideCursorState_Changed(object sender, ReactiveEventArgs<bool> state) private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursorMode> state)
{ {
if (state.NewValue) if (state.NewValue == HideCursorMode.OnIdle)
{ {
_lastCursorMoveTime = Stopwatch.GetTimestamp(); _lastCursorMoveTime = Stopwatch.GetTimestamp();
} }
@ -965,30 +965,38 @@ namespace Ryujinx.Ava
if (_viewModel.IsActive) if (_viewModel.IsActive)
{ {
if (ConfigurationState.Instance.Hid.EnableMouse) if (_isCursorInRenderer)
{ {
if (_isCursorInRenderer) if (ConfigurationState.Instance.Hid.EnableMouse)
{ {
HideCursor(); HideCursor();
} }
else else
{ {
ShowCursor(); switch (ConfigurationState.Instance.HideCursor.Value)
{
case HideCursorMode.Never:
ShowCursor();
break;
case HideCursorMode.OnIdle:
if (Stopwatch.GetTimestamp() - _lastCursorMoveTime >= CursorHideIdleTime * Stopwatch.Frequency)
{
HideCursor();
}
else
{
ShowCursor();
}
break;
case HideCursorMode.Always:
HideCursor();
break;
}
} }
} }
else else
{ {
if (ConfigurationState.Instance.HideCursorOnIdle) ShowCursor();
{
if (Stopwatch.GetTimestamp() - _lastCursorMoveTime >= CursorHideIdleTime * Stopwatch.Frequency)
{
HideCursor();
}
else
{
ShowCursor();
}
}
} }
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
@ -1133,4 +1141,4 @@ namespace Ryujinx.Ava
return state; return state;
} }
} }
} }

View file

@ -80,7 +80,10 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence", "SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Check for Updates on Launch", "SettingsTabGeneralCheckUpdatesOnLaunch": "Check for Updates on Launch",
"SettingsTabGeneralShowConfirmExitDialog": "Show \"Confirm Exit\" Dialog", "SettingsTabGeneralShowConfirmExitDialog": "Show \"Confirm Exit\" Dialog",
"SettingsTabGeneralHideCursorOnIdle": "Hide Cursor on Idle", "SettingsTabGeneralHideCursor": "Hide Cursor:",
"SettingsTabGeneralHideCursorNever": "Never",
"SettingsTabGeneralHideCursorOnIdle": "On Idle",
"SettingsTabGeneralHideCursorAlways": "Always",
"SettingsTabGeneralGameDirectories": "Game Directories", "SettingsTabGeneralGameDirectories": "Game Directories",
"SettingsTabGeneralAdd": "Add", "SettingsTabGeneralAdd": "Add",
"SettingsTabGeneralRemove": "Remove", "SettingsTabGeneralRemove": "Remove",

View file

@ -183,6 +183,18 @@ namespace Ryujinx.Ava
{ {
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value; ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
} }
// Check if HideCursor was overridden.
if (CommandLineState.OverrideHideCursor is not null)
{
ConfigurationState.Instance.HideCursor.Value = CommandLineState.OverrideHideCursor!.ToLower() switch
{
"never" => HideCursorMode.Never,
"onidle" => HideCursorMode.OnIdle,
"always" => HideCursorMode.Always,
_ => ConfigurationState.Instance.HideCursor.Value
};
}
} }
private static void PrintSystemInfo() private static void PrintSystemInfo()
@ -226,4 +238,4 @@ namespace Ryujinx.Ava
Logger.Shutdown(); Logger.Shutdown();
} }
} }
} }

View file

@ -132,7 +132,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableDiscordIntegration { get; set; } public bool EnableDiscordIntegration { get; set; }
public bool CheckUpdatesOnStart { get; set; } public bool CheckUpdatesOnStart { get; set; }
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
public bool HideCursorOnIdle { get; set; } public int HideCursor { get; set; }
public bool EnableDockedMode { get; set; } public bool EnableDockedMode { get; set; }
public bool EnableKeyboard { get; set; } public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; } public bool EnableMouse { get; set; }
@ -375,7 +375,7 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableDiscordIntegration = config.EnableDiscordIntegration; EnableDiscordIntegration = config.EnableDiscordIntegration;
CheckUpdatesOnStart = config.CheckUpdatesOnStart; CheckUpdatesOnStart = config.CheckUpdatesOnStart;
ShowConfirmExit = config.ShowConfirmExit; ShowConfirmExit = config.ShowConfirmExit;
HideCursorOnIdle = config.HideCursorOnIdle; HideCursor = (int)config.HideCursor.Value;
GameDirectories.Clear(); GameDirectories.Clear();
GameDirectories.AddRange(config.Ui.GameDirs.Value); GameDirectories.AddRange(config.Ui.GameDirs.Value);
@ -458,7 +458,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.EnableDiscordIntegration.Value = EnableDiscordIntegration; config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart; config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
config.ShowConfirmExit.Value = ShowConfirmExit; config.ShowConfirmExit.Value = ShowConfirmExit;
config.HideCursorOnIdle.Value = HideCursorOnIdle; config.HideCursor.Value = (HideCursorMode)HideCursor;
if (_directoryChanged) if (_directoryChanged)
{ {

View file

@ -1,4 +1,4 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsUIView" x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsUIView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -12,7 +12,7 @@
<Design.DataContext> <Design.DataContext>
<viewModels:SettingsViewModel /> <viewModels:SettingsViewModel />
</Design.DataContext> </Design.DataContext>
<ScrollViewer <ScrollViewer
Name="UiPage" Name="UiPage"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
@ -37,9 +37,24 @@
<CheckBox IsChecked="{Binding ShowConfirmExit}"> <CheckBox IsChecked="{Binding ShowConfirmExit}">
<TextBlock Text="{locale:Locale SettingsTabGeneralShowConfirmExitDialog}" /> <TextBlock Text="{locale:Locale SettingsTabGeneralShowConfirmExitDialog}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding HideCursorOnIdle}"> <StackPanel Margin="0, 15, 0, 10" Orientation="Horizontal">
<TextBlock Text="{locale:Locale SettingsTabGeneralHideCursorOnIdle}" /> <TextBlock VerticalAlignment="Center"
</CheckBox> Text="{locale:Locale SettingsTabGeneralHideCursor}"
Width="150" />
<ComboBox SelectedIndex="{Binding HideCursor}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralHideCursorNever}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralHideCursorOnIdle}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralHideCursorAlways}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel> </StackPanel>
<Separator Height="1" /> <Separator Height="1" />
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabGeneralGameDirectories}" /> <TextBlock Classes="h1" Text="{locale:Locale SettingsTabGeneralGameDirectories}" />
@ -105,7 +120,7 @@
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<CheckBox <CheckBox
IsChecked="{Binding EnableCustomTheme}" IsChecked="{Binding EnableCustomTheme}"
ToolTip.Tip="{locale:Locale CustomThemeCheckTooltip}"> ToolTip.Tip="{locale:Locale CustomThemeCheckTooltip}">
<TextBlock Text="{locale:Locale SettingsTabGeneralThemeEnableCustomTheme}" /> <TextBlock Text="{locale:Locale SettingsTabGeneralThemeEnableCustomTheme}" />
@ -122,7 +137,7 @@
Grid.Column="1" Grid.Column="1"
Margin="0,10,0,0" Margin="0,10,0,0"
Text="{Binding CustomThemePath}" /> Text="{Binding CustomThemePath}" />
<Button <Button
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
Margin="10,10,0,0" Margin="10,10,0,0"
@ -153,4 +168,4 @@
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>

View file

@ -0,0 +1,9 @@
namespace Ryujinx.Common.Configuration
{
public enum HideCursorMode
{
Never,
OnIdle,
Always
}
}

View file

@ -1,9 +0,0 @@
namespace Ryujinx.Headless.SDL2
{
public enum HideCursor
{
Never,
OnIdle,
Always
}
}

View file

@ -107,8 +107,8 @@ namespace Ryujinx.Headless.SDL2.OpenGL
GraphicsDebugLevel glLogLevel, GraphicsDebugLevel glLogLevel,
AspectRatio aspectRatio, AspectRatio aspectRatio,
bool enableMouse, bool enableMouse,
HideCursor hideCursor) HideCursorMode hideCursorMode)
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursor) : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode)
{ {
_glLogLevel = glLogLevel; _glLogLevel = glLogLevel;
} }

View file

@ -76,8 +76,8 @@ namespace Ryujinx.Headless.SDL2
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")] [Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
public bool EnableMouse { get; set; } public bool EnableMouse { get; set; }
[Option("hide-cursor", Required = false, Default = HideCursor.OnIdle, HelpText = "Change when the cursor gets hidden.")] [Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
public HideCursor HideCursor { get; set; } public HideCursorMode HideCursorMode { get; set; }
[Option("list-input-profiles", Required = false, HelpText = "List inputs profiles.")] [Option("list-input-profiles", Required = false, HelpText = "List inputs profiles.")]
public bool ListInputProfiles { get; set; } public bool ListInputProfiles { get; set; }

View file

@ -478,8 +478,8 @@ namespace Ryujinx.Headless.SDL2
private static WindowBase CreateWindow(Options options) private static WindowBase CreateWindow(Options options)
{ {
return options.GraphicsBackend == GraphicsBackend.Vulkan return options.GraphicsBackend == GraphicsBackend.Vulkan
? new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursor) ? new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode)
: new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursor); : new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode);
} }
private static IRenderer CreateRenderer(Options options, WindowBase window) private static IRenderer CreateRenderer(Options options, WindowBase window)

View file

@ -1,4 +1,5 @@
using Ryujinx.Input; using Ryujinx.Common.Configuration;
using Ryujinx.Input;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
@ -13,7 +14,7 @@ namespace Ryujinx.Headless.SDL2
private const int CursorHideIdleTime = 5; // seconds private const int CursorHideIdleTime = 5; // seconds
private bool _isDisposed; private bool _isDisposed;
private HideCursor _hideCursor; private HideCursorMode _hideCursorMode;
private bool _isHidden; private bool _isHidden;
private long _lastCursorMoveTime; private long _lastCursorMoveTime;
@ -23,12 +24,12 @@ namespace Ryujinx.Headless.SDL2
public Vector2 Scroll { get; private set; } public Vector2 Scroll { get; private set; }
public Size _clientSize; public Size _clientSize;
public SDL2MouseDriver(HideCursor hideCursor) public SDL2MouseDriver(HideCursorMode hideCursorMode)
{ {
PressedButtons = new bool[(int)MouseButton.Count]; PressedButtons = new bool[(int)MouseButton.Count];
_hideCursor = hideCursor; _hideCursorMode = hideCursorMode;
if (_hideCursor == HideCursor.Always) if (_hideCursorMode == HideCursorMode.Always)
{ {
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
_isHidden = true; _isHidden = true;
@ -59,7 +60,7 @@ namespace Ryujinx.Headless.SDL2
private void CheckIdle() private void CheckIdle()
{ {
if (_hideCursor != HideCursor.OnIdle) if (_hideCursorMode != HideCursorMode.OnIdle)
{ {
return; return;
} }

View file

@ -17,8 +17,8 @@ namespace Ryujinx.Headless.SDL2.Vulkan
GraphicsDebugLevel glLogLevel, GraphicsDebugLevel glLogLevel,
AspectRatio aspectRatio, AspectRatio aspectRatio,
bool enableMouse, bool enableMouse,
HideCursor hideCursor) HideCursorMode hideCursorMode)
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursor) : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode)
{ {
_glLogLevel = glLogLevel; _glLogLevel = glLogLevel;
} }

View file

@ -78,9 +78,9 @@ namespace Ryujinx.Headless.SDL2
GraphicsDebugLevel glLogLevel, GraphicsDebugLevel glLogLevel,
AspectRatio aspectRatio, AspectRatio aspectRatio,
bool enableMouse, bool enableMouse,
HideCursor hideCursor) HideCursorMode hideCursorMode)
{ {
MouseDriver = new SDL2MouseDriver(hideCursor); MouseDriver = new SDL2MouseDriver(hideCursorMode);
_inputManager = inputManager; _inputManager = inputManager;
_inputManager.SetMouseDriver(MouseDriver); _inputManager.SetMouseDriver(MouseDriver);
NpadManager = _inputManager.CreateNpadManager(); NpadManager = _inputManager.CreateNpadManager();

View file

@ -162,9 +162,9 @@ namespace Ryujinx.Ui.Common.Configuration
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
/// <summary> /// <summary>
/// Hide Cursor on Idle /// Whether to hide cursor on idle, always or never
/// </summary> /// </summary>
public bool HideCursorOnIdle { get; set; } public HideCursorMode HideCursor { get; set; }
/// <summary> /// <summary>
/// Enables or disables Vertical Sync /// Enables or disables Vertical Sync
@ -395,4 +395,4 @@ namespace Ryujinx.Ui.Common.Configuration
JsonHelper.SerializeToFile(path, this, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat); JsonHelper.SerializeToFile(path, this, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat);
} }
} }
} }

View file

@ -613,7 +613,7 @@ namespace Ryujinx.Ui.Common.Configuration
/// <summary> /// <summary>
/// Hide Cursor on Idle /// Hide Cursor on Idle
/// </summary> /// </summary>
public ReactiveObject<bool> HideCursorOnIdle { get; private set; } public ReactiveObject<HideCursorMode> HideCursor { get; private set; }
private ConfigurationState() private ConfigurationState()
{ {
@ -626,7 +626,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDiscordIntegration = new ReactiveObject<bool>(); EnableDiscordIntegration = new ReactiveObject<bool>();
CheckUpdatesOnStart = new ReactiveObject<bool>(); CheckUpdatesOnStart = new ReactiveObject<bool>();
ShowConfirmExit = new ReactiveObject<bool>(); ShowConfirmExit = new ReactiveObject<bool>();
HideCursorOnIdle = new ReactiveObject<bool>(); HideCursor = new ReactiveObject<HideCursorMode>();
} }
public ConfigurationFileFormat ToFileFormat() public ConfigurationFileFormat ToFileFormat()
@ -662,7 +662,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDiscordIntegration = EnableDiscordIntegration, EnableDiscordIntegration = EnableDiscordIntegration,
CheckUpdatesOnStart = CheckUpdatesOnStart, CheckUpdatesOnStart = CheckUpdatesOnStart,
ShowConfirmExit = ShowConfirmExit, ShowConfirmExit = ShowConfirmExit,
HideCursorOnIdle = HideCursorOnIdle, HideCursor = HideCursor,
EnableVsync = Graphics.EnableVsync, EnableVsync = Graphics.EnableVsync,
EnableShaderCache = Graphics.EnableShaderCache, EnableShaderCache = Graphics.EnableShaderCache,
EnableTextureRecompression = Graphics.EnableTextureRecompression, EnableTextureRecompression = Graphics.EnableTextureRecompression,
@ -767,7 +767,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDiscordIntegration.Value = true; EnableDiscordIntegration.Value = true;
CheckUpdatesOnStart.Value = true; CheckUpdatesOnStart.Value = true;
ShowConfirmExit.Value = true; ShowConfirmExit.Value = true;
HideCursorOnIdle.Value = false; HideCursor.Value = Ryujinx.Common.Configuration.HideCursorMode.Never;
Graphics.EnableVsync.Value = true; Graphics.EnableVsync.Value = true;
Graphics.EnableShaderCache.Value = true; Graphics.EnableShaderCache.Value = true;
Graphics.EnableTextureRecompression.Value = false; Graphics.EnableTextureRecompression.Value = false;
@ -1046,7 +1046,7 @@ namespace Ryujinx.Ui.Common.Configuration
{ {
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22."); Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
configurationFileFormat.HideCursorOnIdle = false; configurationFileFormat.HideCursor = HideCursorMode.Never;
configurationFileUpdated = true; configurationFileUpdated = true;
} }
@ -1427,7 +1427,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; HideCursor.Value = configurationFileFormat.HideCursor;
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression; Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;

View file

@ -9,6 +9,7 @@ namespace Ryujinx.Ui.Common.Helper
public static bool? OverrideDockedMode { get; private set; } public static bool? OverrideDockedMode { get; private set; }
public static string OverrideGraphicsBackend { get; private set; } public static string OverrideGraphicsBackend { get; private set; }
public static string OverrideHideCursor { get; private set; }
public static string BaseDirPathArg { get; private set; } public static string BaseDirPathArg { get; private set; }
public static string Profile { get; private set; } public static string Profile { get; private set; }
public static string LaunchPathArg { get; private set; } public static string LaunchPathArg { get; private set; }
@ -76,6 +77,16 @@ namespace Ryujinx.Ui.Common.Helper
case "--handheld-mode": case "--handheld-mode":
OverrideDockedMode = false; OverrideDockedMode = false;
break; break;
case "--hide-cursor":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
OverrideHideCursor = args[++i];
break;
default: default:
LaunchPathArg = arg; LaunchPathArg = arg;
break; break;

View file

@ -209,7 +209,7 @@ namespace Ryujinx
} }
} }
// Check if graphics backend was overridden // Check if graphics backend was overridden.
if (CommandLineState.OverrideGraphicsBackend != null) if (CommandLineState.OverrideGraphicsBackend != null)
{ {
if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl") if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl")
@ -224,7 +224,19 @@ namespace Ryujinx
} }
} }
// Check if docked mode was overriden. // Check if HideCursor was overridden.
if (CommandLineState.OverrideHideCursor is not null)
{
ConfigurationState.Instance.HideCursor.Value = CommandLineState.OverrideHideCursor!.ToLower() switch
{
"never" => HideCursorMode.Never,
"onidle" => HideCursorMode.OnIdle,
"always" => HideCursorMode.Always,
_ => ConfigurationState.Instance.HideCursor.Value
};
}
// Check if docked mode was overridden.
if (CommandLineState.OverrideDockedMode.HasValue) if (CommandLineState.OverrideDockedMode.HasValue)
{ {
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value; ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;

View file

@ -72,7 +72,7 @@ namespace Ryujinx.Ui
const int CursorHideIdleTime = 5; // seconds const int CursorHideIdleTime = 5; // seconds
private static readonly Cursor _invisibleCursor = new Cursor(Display.Default, CursorType.BlankCursor); private static readonly Cursor _invisibleCursor = new Cursor(Display.Default, CursorType.BlankCursor);
private long _lastCursorMoveTime; private long _lastCursorMoveTime;
private bool _hideCursorOnIdle; private HideCursorMode _hideCursorMode;
private InputManager _inputManager; private InputManager _inputManager;
private IKeyboard _keyboardInterface; private IKeyboard _keyboardInterface;
private GraphicsDebugLevel _glLogLevel; private GraphicsDebugLevel _glLogLevel;
@ -113,10 +113,10 @@ namespace Ryujinx.Ui
_gpuCancellationTokenSource = new CancellationTokenSource(); _gpuCancellationTokenSource = new CancellationTokenSource();
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle; _hideCursorMode = ConfigurationState.Instance.HideCursor;
_lastCursorMoveTime = Stopwatch.GetTimestamp(); _lastCursorMoveTime = Stopwatch.GetTimestamp();
ConfigurationState.Instance.HideCursorOnIdle.Event += HideCursorStateChanged; ConfigurationState.Instance.HideCursor.Event += HideCursorStateChanged;
ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAnriAliasing; ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAnriAliasing;
ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter; ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel; ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
@ -145,26 +145,32 @@ namespace Ryujinx.Ui
return Renderer.GetHardwareInfo().GpuVendor; return Renderer.GetHardwareInfo().GpuVendor;
} }
private void HideCursorStateChanged(object sender, ReactiveEventArgs<bool> state) private void HideCursorStateChanged(object sender, ReactiveEventArgs<HideCursorMode> state)
{ {
Application.Invoke(delegate Application.Invoke(delegate
{ {
_hideCursorOnIdle = state.NewValue; _hideCursorMode = state.NewValue;
if (_hideCursorOnIdle) switch (_hideCursorMode)
{ {
_lastCursorMoveTime = Stopwatch.GetTimestamp(); case HideCursorMode.Never:
} Window.Cursor = null;
else break;
{ case HideCursorMode.OnIdle:
Window.Cursor = null; _lastCursorMoveTime = Stopwatch.GetTimestamp();
break;
case HideCursorMode.Always:
Window.Cursor = _invisibleCursor;
break;
default:
throw new ArgumentOutOfRangeException();
} }
}); });
} }
private void Renderer_Destroyed(object sender, EventArgs e) private void Renderer_Destroyed(object sender, EventArgs e)
{ {
ConfigurationState.Instance.HideCursorOnIdle.Event -= HideCursorStateChanged; ConfigurationState.Instance.HideCursor.Event -= HideCursorStateChanged;
ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAnriAliasing; ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAnriAliasing;
ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter; ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter;
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel; ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
@ -180,7 +186,7 @@ namespace Ryujinx.Ui
protected override bool OnMotionNotifyEvent(EventMotion evnt) protected override bool OnMotionNotifyEvent(EventMotion evnt)
{ {
if (_hideCursorOnIdle) if (_hideCursorMode == HideCursorMode.OnIdle)
{ {
_lastCursorMoveTime = Stopwatch.GetTimestamp(); _lastCursorMoveTime = Stopwatch.GetTimestamp();
} }
@ -315,15 +321,28 @@ namespace Ryujinx.Ui
_toggleDockedMode = toggleDockedMode; _toggleDockedMode = toggleDockedMode;
if (_hideCursorOnIdle && !ConfigurationState.Instance.Hid.EnableMouse) if (ConfigurationState.Instance.Hid.EnableMouse.Value)
{ {
long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime; if (_isMouseInClient)
Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null; {
Window.Cursor = _invisibleCursor;
}
} }
else
if (ConfigurationState.Instance.Hid.EnableMouse && _isMouseInClient)
{ {
Window.Cursor = _invisibleCursor; switch (_hideCursorMode)
{
case HideCursorMode.OnIdle:
long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null;
break;
case HideCursorMode.Always:
Window.Cursor = _invisibleCursor;
break;
case HideCursorMode.Never:
Window.Cursor = null;
break;
}
} }
} }
@ -775,4 +794,4 @@ namespace Ryujinx.Ui
return state; return state;
} }
} }
} }

View file

@ -52,7 +52,9 @@ namespace Ryujinx.Ui.Windows
[GUI] CheckButton _discordToggle; [GUI] CheckButton _discordToggle;
[GUI] CheckButton _checkUpdatesToggle; [GUI] CheckButton _checkUpdatesToggle;
[GUI] CheckButton _showConfirmExitToggle; [GUI] CheckButton _showConfirmExitToggle;
[GUI] CheckButton _hideCursorOnIdleToggle; [GUI] RadioButton _hideCursorNever;
[GUI] RadioButton _hideCursorOnIdle;
[GUI] RadioButton _hideCursorAlways;
[GUI] CheckButton _vSyncToggle; [GUI] CheckButton _vSyncToggle;
[GUI] CheckButton _shaderCacheToggle; [GUI] CheckButton _shaderCacheToggle;
[GUI] CheckButton _textureRecompressionToggle; [GUI] CheckButton _textureRecompressionToggle;
@ -226,9 +228,17 @@ namespace Ryujinx.Ui.Windows
_showConfirmExitToggle.Click(); _showConfirmExitToggle.Click();
} }
if (ConfigurationState.Instance.HideCursorOnIdle) switch (ConfigurationState.Instance.HideCursor.Value)
{ {
_hideCursorOnIdleToggle.Click(); case HideCursorMode.Never:
_hideCursorNever.Click();
break;
case HideCursorMode.OnIdle:
_hideCursorOnIdle.Click();
break;
case HideCursorMode.Always:
_hideCursorAlways.Click();
break;
} }
if (ConfigurationState.Instance.Graphics.EnableVsync) if (ConfigurationState.Instance.Graphics.EnableVsync)
@ -560,6 +570,18 @@ namespace Ryujinx.Ui.Windows
_directoryChanged = false; _directoryChanged = false;
} }
HideCursorMode hideCursor = HideCursorMode.Never;
if (_hideCursorOnIdle.Active)
{
hideCursor = HideCursorMode.OnIdle;
}
if (_hideCursorAlways.Active)
{
hideCursor = HideCursorMode.Always;
}
if (!float.TryParse(_resScaleText.Buffer.Text, out float resScaleCustom) || resScaleCustom <= 0.0f) if (!float.TryParse(_resScaleText.Buffer.Text, out float resScaleCustom) || resScaleCustom <= 0.0f)
{ {
resScaleCustom = 1.0f; resScaleCustom = 1.0f;
@ -602,7 +624,7 @@ namespace Ryujinx.Ui.Windows
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active; ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active; ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active;
ConfigurationState.Instance.HideCursorOnIdle.Value = _hideCursorOnIdleToggle.Active; ConfigurationState.Instance.HideCursor.Value = hideCursor;
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active; ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active; ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active;
@ -813,4 +835,4 @@ namespace Ryujinx.Ui.Windows
Dispose(); Dispose();
} }
} }
} }

View file

@ -160,19 +160,83 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkCheckButton" id="_hideCursorOnIdleToggle"> <object class="GtkBox" id="_hideCursorBox">
<property name="label" translatable="yes">Hide Cursor On Idle</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">False</property>
<property name="receives-default">False</property> <child>
<property name="halign">start</property> <object class="GtkLabel">
<property name="draw-indicator">True</property> <property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Hide Cursor:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="_hideCursorNever">
<property name="label" translatable="yes">Never</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="_hideCursorOnIdle">
<property name="label" translatable="yes">On Idle</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
<property name="group">_hideCursorNever</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="_hideCursorAlways">
<property name="label" translatable="yes">Always</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
<property name="group">_hideCursorNever</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="padding">5</property> <property name="padding">5</property>
<property name="position">3</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
</object> </object>