aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs')
-rw-r--r--src/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs b/src/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
new file mode 100644
index 00000000..8c3412ff
--- /dev/null
+++ b/src/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
@@ -0,0 +1,164 @@
+using Ryujinx.Input;
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using static SDL2.SDL;
+
+namespace Ryujinx.Headless.SDL2
+{
+ class SDL2MouseDriver : IGamepadDriver
+ {
+ private const int CursorHideIdleTime = 5; // seconds
+
+ private bool _isDisposed;
+ private HideCursor _hideCursor;
+ private bool _isHidden;
+ private long _lastCursorMoveTime;
+
+ public bool[] PressedButtons { get; }
+
+ public Vector2 CurrentPosition { get; private set; }
+ public Vector2 Scroll { get; private set; }
+ public Size _clientSize;
+
+ public SDL2MouseDriver(HideCursor hideCursor)
+ {
+ PressedButtons = new bool[(int)MouseButton.Count];
+ _hideCursor = hideCursor;
+
+ if (_hideCursor == HideCursor.Always)
+ {
+ SDL_ShowCursor(SDL_DISABLE);
+ _isHidden = true;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static MouseButton DriverButtonToMouseButton(uint rawButton)
+ {
+ Debug.Assert(rawButton > 0 && rawButton <= (int)MouseButton.Count);
+
+ return (MouseButton)(rawButton - 1);
+ }
+
+ public void UpdatePosition()
+ {
+ SDL_GetMouseState(out int posX, out int posY);
+ Vector2 position = new(posX, posY);
+
+ if (CurrentPosition != position)
+ {
+ CurrentPosition = position;
+ _lastCursorMoveTime = Stopwatch.GetTimestamp();
+ }
+
+ CheckIdle();
+ }
+
+ private void CheckIdle()
+ {
+ if (_hideCursor != HideCursor.OnIdle)
+ {
+ return;
+ }
+
+ long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
+
+ if (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency)
+ {
+ if (!_isHidden)
+ {
+ SDL_ShowCursor(SDL_DISABLE);
+ _isHidden = true;
+ }
+ }
+ else
+ {
+ if (_isHidden)
+ {
+ SDL_ShowCursor(SDL_ENABLE);
+ _isHidden = false;
+ }
+ }
+ }
+
+ public void Update(SDL_Event evnt)
+ {
+ switch (evnt.type)
+ {
+ case SDL_EventType.SDL_MOUSEBUTTONDOWN:
+ case SDL_EventType.SDL_MOUSEBUTTONUP:
+ uint rawButton = evnt.button.button;
+
+ if (rawButton > 0 && rawButton <= (int)MouseButton.Count)
+ {
+ PressedButtons[(int)DriverButtonToMouseButton(rawButton)] = evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN;
+
+ CurrentPosition = new Vector2(evnt.button.x, evnt.button.y);
+ }
+
+ break;
+
+ // NOTE: On Linux using Wayland mouse motion events won't be received at all.
+ case SDL_EventType.SDL_MOUSEMOTION:
+ CurrentPosition = new Vector2(evnt.motion.x, evnt.motion.y);
+ _lastCursorMoveTime = Stopwatch.GetTimestamp();
+
+ break;
+
+ case SDL_EventType.SDL_MOUSEWHEEL:
+ Scroll = new Vector2(evnt.wheel.x, evnt.wheel.y);
+
+ break;
+ }
+ }
+
+ public void SetClientSize(int width, int height)
+ {
+ _clientSize = new Size(width, height);
+ }
+
+ public bool IsButtonPressed(MouseButton button)
+ {
+ return PressedButtons[(int)button];
+ }
+
+ public Size GetClientSize()
+ {
+ return _clientSize;
+ }
+
+ public string DriverName => "SDL2";
+
+ public event Action<string> OnGamepadConnected
+ {
+ add { }
+ remove { }
+ }
+
+ public event Action<string> OnGamepadDisconnected
+ {
+ add { }
+ remove { }
+ }
+
+ public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
+
+ public IGamepad GetGamepad(string id)
+ {
+ return new SDL2Mouse(this);
+ }
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ {
+ return;
+ }
+
+ _isDisposed = true;
+ }
+ }
+} \ No newline at end of file