aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAc_K <Acoustik666@gmail.com>2023-01-15 01:05:44 +0100
committerGitHub <noreply@github.com>2023-01-15 01:05:44 +0100
commit8071c8c8c044ee56bc7578a4ba3178d2d03733db (patch)
treea4b12e0be1afe859b9a8a9dd0c4441f7a168331a
parentb402b4e7f6463c42ac5afcfaee45592e75851dc3 (diff)
Ava UI: Fixes "Hide Cursor on Idle" for Windows (#4266)1.1.557
* Ava: Fixes "Hide Cursor on Idle" for Windows * Add check in MouseDriver and reduce the time of idling * Fix linux error * Change idle time everywhere for consistencies
-rw-r--r--Ryujinx.Ava/AppHost.cs128
-rw-r--r--Ryujinx.Ava/Input/AvaloniaMouseDriver.cs32
-rw-r--r--Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs7
-rw-r--r--Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs16
-rw-r--r--Ryujinx.Headless.SDL2/SDL2MouseDriver.cs2
-rw-r--r--Ryujinx/Ui/RendererWidgetBase.cs2
6 files changed, 125 insertions, 62 deletions
diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs
index 65f84c49..5c4f5bd8 100644
--- a/Ryujinx.Ava/AppHost.cs
+++ b/Ryujinx.Ava/AppHost.cs
@@ -44,8 +44,10 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
+using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop;
using Image = SixLabors.ImageSharp.Image;
using InputManager = Ryujinx.Input.HLE.InputManager;
using Key = Ryujinx.Input.Key;
@@ -58,12 +60,14 @@ namespace Ryujinx.Ava
{
internal class AppHost
{
- private const int CursorHideIdleTime = 8; // Hide Cursor seconds.
+ private const int CursorHideIdleTime = 5; // Hide Cursor seconds.
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
private const int TargetFps = 60;
private const float VolumeDelta = 0.05f;
private static readonly Cursor InvisibleCursor = new(StandardCursorType.None);
+ private readonly IntPtr InvisibleCursorWin;
+ private readonly IntPtr DefaultCursorWin;
private readonly long _ticksPerFrame;
private readonly Stopwatch _chrono;
@@ -81,7 +85,6 @@ namespace Ryujinx.Ava
private float _newVolume;
private KeyboardHotkeyState _prevHotkeyState;
- private bool _hideCursorOnIdle;
private long _lastCursorMoveTime;
private bool _isCursorInRenderer;
@@ -131,7 +134,6 @@ namespace Ryujinx.Ava
_accountManager = accountManager;
_userChannelPersistence = userChannelPersistence;
_renderingThread = new Thread(RenderLoop, 1 * 1024 * 1024) { Name = "GUI.RenderThread" };
- _hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
_lastCursorMoveTime = Stopwatch.GetTimestamp();
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
_topLevel = topLevel;
@@ -159,9 +161,14 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.HideCursorOnIdle.Event += HideCursorState_Changed;
- _topLevel.PointerLeave += TopLevel_PointerLeave;
_topLevel.PointerMoved += TopLevel_PointerMoved;
+ if (OperatingSystem.IsWindows())
+ {
+ InvisibleCursorWin = CreateEmptyCursor();
+ DefaultCursorWin = CreateArrowCursor();
+ }
+
ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
@@ -172,20 +179,47 @@ namespace Ryujinx.Ava
private void TopLevel_PointerMoved(object sender, PointerEventArgs e)
{
- if (sender is Control visual)
+ if (sender is MainWindow window)
{
_lastCursorMoveTime = Stopwatch.GetTimestamp();
- var point = e.GetCurrentPoint(visual).Position;
+ if ((Renderer.Content as EmbeddedWindow).TransformedBounds != null)
+ {
+ var point = e.GetCurrentPoint(window).Position;
+ var bounds = (Renderer.Content as EmbeddedWindow).TransformedBounds.Value.Clip;
- _isCursorInRenderer = Equals(visual.InputHitTest(point), Renderer);
+ _isCursorInRenderer = point.X >= bounds.X &&
+ point.X <= bounds.Width + bounds.X &&
+ point.Y >= bounds.Y &&
+ point.Y <= bounds.Height + bounds.Y;
+ }
}
}
- private void TopLevel_PointerLeave(object sender, PointerEventArgs e)
+ private void ShowCursor()
{
- _isCursorInRenderer = false;
- _viewModel.Cursor = Cursor.Default;
+ Dispatcher.UIThread.Post(() =>
+ {
+ _viewModel.Cursor = Cursor.Default;
+
+ if (OperatingSystem.IsWindows())
+ {
+ SetCursor(DefaultCursorWin);
+ }
+ });
+ }
+
+ private void HideCursor()
+ {
+ Dispatcher.UIThread.Post(() =>
+ {
+ _viewModel.Cursor = InvisibleCursor;
+
+ if (OperatingSystem.IsWindows())
+ {
+ SetCursor(InvisibleCursorWin);
+ }
+ });
}
private void SetRendererWindowSize(Size size)
@@ -380,7 +414,6 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState;
ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState;
- _topLevel.PointerLeave -= TopLevel_PointerLeave;
_topLevel.PointerMoved -= TopLevel_PointerMoved;
_gpuCancellationTokenSource.Cancel();
@@ -406,19 +439,10 @@ namespace Ryujinx.Ava
private void HideCursorState_Changed(object sender, ReactiveEventArgs<bool> state)
{
- Dispatcher.UIThread.InvokeAsync(delegate
+ if (state.NewValue)
{
- _hideCursorOnIdle = state.NewValue;
-
- if (_hideCursorOnIdle)
- {
- _lastCursorMoveTime = Stopwatch.GetTimestamp();
- }
- else
- {
- _viewModel.Cursor = Cursor.Default;
- }
- });
+ _lastCursorMoveTime = Stopwatch.GetTimestamp();
+ }
}
public async Task<bool> LoadGuestApplication()
@@ -860,29 +884,6 @@ namespace Ryujinx.Ava
}
}
- private void HandleScreenState()
- {
- if (ConfigurationState.Instance.Hid.EnableMouse)
- {
- Dispatcher.UIThread.Post(() =>
- {
- _viewModel.Cursor = _isCursorInRenderer ? InvisibleCursor : Cursor.Default;
- });
- }
- else
- {
- if (_hideCursorOnIdle)
- {
- long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
-
- Dispatcher.UIThread.Post(() =>
- {
- _viewModel.Cursor = cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency ? InvisibleCursor : Cursor.Default;
- });
- }
- }
- }
-
private bool UpdateFrame()
{
if (!_isActive)
@@ -890,23 +891,44 @@ namespace Ryujinx.Ava
return false;
}
+ NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
+
if (_viewModel.IsActive)
{
- Dispatcher.UIThread.Post(() =>
+ if (ConfigurationState.Instance.Hid.EnableMouse)
{
- HandleScreenState();
+ if (_isCursorInRenderer)
+ {
+ HideCursor();
+ }
+ else
+ {
+ ShowCursor();
+ }
+ }
+ else
+ {
+ if (ConfigurationState.Instance.HideCursorOnIdle)
+ {
+ if (Stopwatch.GetTimestamp() - _lastCursorMoveTime >= CursorHideIdleTime * Stopwatch.Frequency)
+ {
+ HideCursor();
+ }
+ else
+ {
+ ShowCursor();
+ }
+ }
+ }
+ Dispatcher.UIThread.Post(() =>
+ {
if (_keyboardInterface.GetKeyboardStateSnapshot().IsPressed(Key.Delete) && _viewModel.WindowState != WindowState.FullScreen)
{
Device.Application.DiskCacheLoadState?.Cancel();
}
});
- }
- NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
-
- if (_viewModel.IsActive)
- {
KeyboardHotkeyState currentHotkeyState = GetHotkeyState();
if (currentHotkeyState != _prevHotkeyState)
diff --git a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
index b0b6cdf0..b3e1a21a 100644
--- a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
+++ b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
+using FluentAvalonia.Core;
using Ryujinx.Input;
using System;
using System.Numerics;
@@ -69,12 +70,22 @@ namespace Ryujinx.Ava.Input
private void Parent_PointerReleaseEvent(object o, PointerReleasedEventArgs args)
{
- PressedButtons[(int)args.InitialPressMouseButton - 1] = false;
+ int button = (int)args.InitialPressMouseButton - 1;
+
+ if (PressedButtons.Count() >= button)
+ {
+ PressedButtons[button] = false;
+ }
}
private void Parent_PointerPressEvent(object o, PointerPressedEventArgs args)
{
- PressedButtons[(int)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind] = true;
+ int button = (int)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind;
+
+ if (PressedButtons.Count() >= button)
+ {
+ PressedButtons[button] = true;
+ }
}
private void Parent_PointerMovedEvent(object o, PointerEventArgs args)
@@ -86,12 +97,18 @@ namespace Ryujinx.Ava.Input
public void SetMousePressed(MouseButton button)
{
- PressedButtons[(int)button] = true;
+ if (PressedButtons.Count() >= (int)button)
+ {
+ PressedButtons[(int)button] = true;
+ }
}
public void SetMouseReleased(MouseButton button)
{
- PressedButtons[(int)button] = false;
+ if (PressedButtons.Count() >= (int)button)
+ {
+ PressedButtons[(int)button] = false;
+ }
}
public void SetPosition(double x, double y)
@@ -101,7 +118,12 @@ namespace Ryujinx.Ava.Input
public bool IsButtonPressed(MouseButton button)
{
- return PressedButtons[(int)button];
+ if (PressedButtons.Count() >= (int)button)
+ {
+ return PressedButtons[(int)button];
+ }
+
+ return false;
}
public Size GetClientSize()
diff --git a/Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs b/Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs
index 8247a89b..67ab80aa 100644
--- a/Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs
+++ b/Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs
@@ -34,6 +34,8 @@ namespace Ryujinx.Ava.UI.Helpers
{
WindowHandle = IntPtr.Zero;
X11Display = IntPtr.Zero;
+ NsView = IntPtr.Zero;
+ MetalLayer = IntPtr.Zero;
}
public EmbeddedWindow()
@@ -42,7 +44,7 @@ namespace Ryujinx.Ava.UI.Helpers
stateObserverable.Subscribe(StateChanged);
- this.Initialized += NativeEmbeddedWindow_Initialized;
+ Initialized += NativeEmbeddedWindow_Initialized;
}
public virtual void OnWindowCreated() { }
@@ -127,7 +129,7 @@ namespace Ryujinx.Ava.UI.Helpers
lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate),
style = ClassStyles.CS_OWNDC,
lpszClassName = Marshal.StringToHGlobalUni(_className),
- hCursor = LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IDC_ARROW)
+ hCursor = CreateArrowCursor()
};
var atom = RegisterClassEx(ref wndClassEx);
@@ -198,6 +200,7 @@ namespace Ryujinx.Ava.UI.Helpers
KeyModifiers.None));
break;
}
+
return DefWindowProc(hWnd, msg, wParam, lParam);
}
diff --git a/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs b/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs
index 1e6e3c3b..03d3a49f 100644
--- a/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs
+++ b/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs
@@ -70,6 +70,22 @@ namespace Ryujinx.Ava.UI.Helpers
}
}
+ public static IntPtr CreateEmptyCursor()
+ {
+ return CreateCursor(IntPtr.Zero, 0, 0, 1, 1, new byte[] { 0xFF }, new byte[] { 0x00 });
+ }
+
+ public static IntPtr CreateArrowCursor()
+ {
+ return LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IDC_ARROW);
+ }
+
+ [LibraryImport("user32.dll")]
+ public static partial IntPtr SetCursor(IntPtr handle);
+
+ [LibraryImport("user32.dll")]
+ public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte[] pvANDPlane, byte[] pvXORPlane);
+
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")]
public static partial ushort RegisterClassEx(ref WNDCLASSEX param);
diff --git a/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs b/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
index bdf428cc..8c3412ff 100644
--- a/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
+++ b/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.Headless.SDL2
{
class SDL2MouseDriver : IGamepadDriver
{
- private const int CursorHideIdleTime = 8; // seconds
+ private const int CursorHideIdleTime = 5; // seconds
private bool _isDisposed;
private HideCursor _hideCursor;
diff --git a/Ryujinx/Ui/RendererWidgetBase.cs b/Ryujinx/Ui/RendererWidgetBase.cs
index 8db023be..4bf2a70f 100644
--- a/Ryujinx/Ui/RendererWidgetBase.cs
+++ b/Ryujinx/Ui/RendererWidgetBase.cs
@@ -68,7 +68,7 @@ namespace Ryujinx.Ui
private readonly CancellationTokenSource _gpuCancellationTokenSource;
// Hide Cursor
- const int CursorHideIdleTime = 8; // seconds
+ const int CursorHideIdleTime = 5; // seconds
private static readonly Cursor _invisibleCursor = new Cursor(Display.Default, CursorType.BlankCursor);
private long _lastCursorMoveTime;
private bool _hideCursorOnIdle;