infra: Make Avalonia the default UI (#6375)

* misc: Move Ryujinx project to Ryujinx.Gtk3

This breaks release CI for now but that's fine.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* misc: Move Ryujinx.Ava project to Ryujinx

This breaks CI for now, but it's fine.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* infra: Make Avalonia the default UI

Should fix CI after the previous changes.

GTK3 isn't build by the release job anymore, only by PR CI.

This also ensure that the test-ava update package is still generated to
allow update from the old testing channel.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Fix missing copy in create_app_bundle.sh

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Fix syntax error

Signed-off-by: Mary Guillemard <mary@mary.zone>

---------

Signed-off-by: Mary Guillemard <mary@mary.zone>
This commit is contained in:
Mary Guillemard 2024-03-02 12:51:05 +01:00 committed by GitHub
parent 53b5985da6
commit ec6cb0abb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
239 changed files with 1235 additions and 1232 deletions

View file

@ -1,18 +1,32 @@
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Input;
using System;
using System.Collections.Generic;
using System.Numerics;
using ConfigKey = Ryujinx.Common.Configuration.Hid.Key;
using Key = Ryujinx.Input.Key;
namespace Ryujinx.Input.GTK3
namespace Ryujinx.Ava.Input
{
public class GTK3Keyboard : IKeyboard
internal class AvaloniaKeyboard : IKeyboard
{
private readonly List<ButtonMappingEntry> _buttonsUserMapping;
private readonly AvaloniaKeyboardDriver _driver;
private StandardKeyboardInputConfig _configuration;
private readonly object _userMappingLock = new();
public string Id { get; }
public string Name { get; }
public bool IsConnected => true;
public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
private class ButtonMappingEntry
{
public readonly GamepadButtonInputId To;
public readonly Key From;
public readonly GamepadButtonInputId To;
public ButtonMappingEntry(GamepadButtonInputId to, Key from)
{
@ -21,34 +35,13 @@ namespace Ryujinx.Input.GTK3
}
}
private readonly object _userMappingLock = new();
private readonly GTK3KeyboardDriver _driver;
private StandardKeyboardInputConfig _configuration;
private readonly List<ButtonMappingEntry> _buttonsUserMapping;
public GTK3Keyboard(GTK3KeyboardDriver driver, string id, string name)
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
{
_buttonsUserMapping = new List<ButtonMappingEntry>();
_driver = driver;
Id = id;
Name = name;
_buttonsUserMapping = new List<ButtonMappingEntry>();
}
private bool HasConfiguration => _configuration != null;
public string Id { get; }
public string Name { get; }
public bool IsConnected => true;
public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
public void Dispose()
{
// No operations
GC.SuppressFinalize(this);
}
public KeyboardStateSnapshot GetKeyboardStateSnapshot()
@ -56,45 +49,6 @@ namespace Ryujinx.Input.GTK3
return IKeyboard.GetStateSnapshot(this);
}
private static float ConvertRawStickValue(short value)
{
const float ConvertRate = 1.0f / (short.MaxValue + 0.5f);
return value * ConvertRate;
}
private static (short, short) GetStickValues(ref KeyboardStateSnapshot snapshot, JoyconConfigKeyboardStick<ConfigKey> stickConfig)
{
short stickX = 0;
short stickY = 0;
if (snapshot.IsPressed((Key)stickConfig.StickUp))
{
stickY += 1;
}
if (snapshot.IsPressed((Key)stickConfig.StickDown))
{
stickY -= 1;
}
if (snapshot.IsPressed((Key)stickConfig.StickRight))
{
stickX += 1;
}
if (snapshot.IsPressed((Key)stickConfig.StickLeft))
{
stickX -= 1;
}
OpenTK.Mathematics.Vector2 stick = new(stickX, stickY);
stick.NormalizeFast();
return ((short)(stick.X * short.MaxValue), (short)(stick.Y * short.MaxValue));
}
public GamepadStateSnapshot GetMappedStateSnapshot()
{
KeyboardStateSnapshot rawState = GetKeyboardStateSnapshot();
@ -102,7 +56,7 @@ namespace Ryujinx.Input.GTK3
lock (_userMappingLock)
{
if (!HasConfiguration)
if (_configuration == null)
{
return result;
}
@ -114,7 +68,7 @@ namespace Ryujinx.Input.GTK3
continue;
}
// Do not touch state of button already pressed
// NOTE: Do not touch state of the button already pressed.
if (!result.IsPressed(entry.To))
{
result.SetPressed(entry.To, rawState.IsPressed(entry.From));
@ -148,7 +102,14 @@ namespace Ryujinx.Input.GTK3
public bool IsPressed(Key key)
{
return _driver.IsPressed(key);
try
{
return _driver.IsPressed(key);
}
catch
{
return false;
}
}
public void SetConfiguration(InputConfig configuration)
@ -159,47 +120,84 @@ namespace Ryujinx.Input.GTK3
_buttonsUserMapping.Clear();
// Then left joycon
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (Key)_configuration.LeftJoycon.DpadLeft));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (Key)_configuration.LeftJoycon.DpadRight));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (Key)_configuration.LeftJoycon.ButtonMinus));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (Key)_configuration.LeftJoycon.ButtonL));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (Key)_configuration.LeftJoycon.ButtonZl));
#pragma warning disable IDE0055 // Disable formatting
// Left JoyCon
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (Key)_configuration.LeftJoycon.DpadLeft));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (Key)_configuration.LeftJoycon.DpadRight));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (Key)_configuration.LeftJoycon.ButtonMinus));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (Key)_configuration.LeftJoycon.ButtonL));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (Key)_configuration.LeftJoycon.ButtonZl));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (Key)_configuration.LeftJoycon.ButtonSr));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
// Finally right joycon
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (Key)_configuration.RightJoycon.ButtonX));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (Key)_configuration.RightJoycon.ButtonY));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (Key)_configuration.RightJoycon.ButtonPlus));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (Key)_configuration.RightJoycon.ButtonR));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr));
// Right JoyCon
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (Key)_configuration.RightJoycon.ButtonX));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (Key)_configuration.RightJoycon.ButtonY));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (Key)_configuration.RightJoycon.ButtonPlus));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (Key)_configuration.RightJoycon.ButtonR));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (Key)_configuration.RightJoycon.ButtonSr));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl));
#pragma warning restore IDE0055
}
}
public void SetTriggerThreshold(float triggerThreshold)
public void SetTriggerThreshold(float triggerThreshold) { }
public void Rumble(float lowFrequency, float highFrequency, uint durationMs) { }
public Vector3 GetMotionData(MotionInputId inputId) => Vector3.Zero;
private static float ConvertRawStickValue(short value)
{
// No operations
const float ConvertRate = 1.0f / (short.MaxValue + 0.5f);
return value * ConvertRate;
}
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
private static (short, short) GetStickValues(ref KeyboardStateSnapshot snapshot, JoyconConfigKeyboardStick<ConfigKey> stickConfig)
{
// No operations
short stickX = 0;
short stickY = 0;
if (snapshot.IsPressed((Key)stickConfig.StickUp))
{
stickY += 1;
}
if (snapshot.IsPressed((Key)stickConfig.StickDown))
{
stickY -= 1;
}
if (snapshot.IsPressed((Key)stickConfig.StickRight))
{
stickX += 1;
}
if (snapshot.IsPressed((Key)stickConfig.StickLeft))
{
stickX -= 1;
}
Vector2 stick = new(stickX, stickY);
stick = Vector2.Normalize(stick);
return ((short)(stick.X * short.MaxValue), (short)(stick.Y * short.MaxValue));
}
public Vector3 GetMotionData(MotionInputId inputId)
public void Clear()
{
// No operations
return Vector3.Zero;
_driver?.ResetKeys();
}
public void Dispose() { }
}
}

View file

@ -0,0 +1,107 @@
using Avalonia.Controls;
using Avalonia.Input;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Input;
using System;
using System.Collections.Generic;
using AvaKey = Avalonia.Input.Key;
using Key = Ryujinx.Input.Key;
namespace Ryujinx.Ava.Input
{
internal class AvaloniaKeyboardDriver : IGamepadDriver
{
private static readonly string[] _keyboardIdentifers = new string[1] { "0" };
private readonly Control _control;
private readonly HashSet<AvaKey> _pressedKeys;
public event EventHandler<KeyEventArgs> KeyPressed;
public event EventHandler<KeyEventArgs> KeyRelease;
public event EventHandler<string> TextInput;
public string DriverName => "AvaloniaKeyboardDriver";
public ReadOnlySpan<string> GamepadsIds => _keyboardIdentifers;
public AvaloniaKeyboardDriver(Control control)
{
_control = control;
_pressedKeys = new HashSet<AvaKey>();
_control.KeyDown += OnKeyPress;
_control.KeyUp += OnKeyRelease;
_control.TextInput += Control_TextInput;
}
private void Control_TextInput(object sender, TextInputEventArgs e)
{
TextInput?.Invoke(this, e.Text);
}
public event Action<string> OnGamepadConnected
{
add { }
remove { }
}
public event Action<string> OnGamepadDisconnected
{
add { }
remove { }
}
public IGamepad GetGamepad(string id)
{
if (!_keyboardIdentifers[0].Equals(id))
{
return null;
}
return new AvaloniaKeyboard(this, _keyboardIdentifers[0], LocaleManager.Instance[LocaleKeys.AllKeyboards]);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_control.KeyUp -= OnKeyPress;
_control.KeyDown -= OnKeyRelease;
}
}
protected void OnKeyPress(object sender, KeyEventArgs args)
{
_pressedKeys.Add(args.Key);
KeyPressed?.Invoke(this, args);
}
protected void OnKeyRelease(object sender, KeyEventArgs args)
{
_pressedKeys.Remove(args.Key);
KeyRelease?.Invoke(this, args);
}
internal bool IsPressed(Key key)
{
if (key == Key.Unbound || key == Key.Unknown)
{
return false;
}
AvaloniaKeyboardMappingHelper.TryGetAvaKey(key, out var nativeKey);
return _pressedKeys.Contains(nativeKey);
}
public void ResetKeys()
{
_pressedKeys.Clear();
}
public void Dispose()
{
Dispose(true);
}
}
}

View file

@ -0,0 +1,185 @@
using Ryujinx.Input;
using System;
using System.Collections.Generic;
using AvaKey = Avalonia.Input.Key;
namespace Ryujinx.Ava.Input
{
internal static class AvaloniaKeyboardMappingHelper
{
private static readonly AvaKey[] _keyMapping = {
// NOTE: Invalid
AvaKey.None,
AvaKey.LeftShift,
AvaKey.RightShift,
AvaKey.LeftCtrl,
AvaKey.RightCtrl,
AvaKey.LeftAlt,
AvaKey.RightAlt,
AvaKey.LWin,
AvaKey.RWin,
AvaKey.Apps,
AvaKey.F1,
AvaKey.F2,
AvaKey.F3,
AvaKey.F4,
AvaKey.F5,
AvaKey.F6,
AvaKey.F7,
AvaKey.F8,
AvaKey.F9,
AvaKey.F10,
AvaKey.F11,
AvaKey.F12,
AvaKey.F13,
AvaKey.F14,
AvaKey.F15,
AvaKey.F16,
AvaKey.F17,
AvaKey.F18,
AvaKey.F19,
AvaKey.F20,
AvaKey.F21,
AvaKey.F22,
AvaKey.F23,
AvaKey.F24,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.None,
AvaKey.Up,
AvaKey.Down,
AvaKey.Left,
AvaKey.Right,
AvaKey.Return,
AvaKey.Escape,
AvaKey.Space,
AvaKey.Tab,
AvaKey.Back,
AvaKey.Insert,
AvaKey.Delete,
AvaKey.PageUp,
AvaKey.PageDown,
AvaKey.Home,
AvaKey.End,
AvaKey.CapsLock,
AvaKey.Scroll,
AvaKey.Print,
AvaKey.Pause,
AvaKey.NumLock,
AvaKey.Clear,
AvaKey.NumPad0,
AvaKey.NumPad1,
AvaKey.NumPad2,
AvaKey.NumPad3,
AvaKey.NumPad4,
AvaKey.NumPad5,
AvaKey.NumPad6,
AvaKey.NumPad7,
AvaKey.NumPad8,
AvaKey.NumPad9,
AvaKey.Divide,
AvaKey.Multiply,
AvaKey.Subtract,
AvaKey.Add,
AvaKey.Decimal,
AvaKey.Enter,
AvaKey.A,
AvaKey.B,
AvaKey.C,
AvaKey.D,
AvaKey.E,
AvaKey.F,
AvaKey.G,
AvaKey.H,
AvaKey.I,
AvaKey.J,
AvaKey.K,
AvaKey.L,
AvaKey.M,
AvaKey.N,
AvaKey.O,
AvaKey.P,
AvaKey.Q,
AvaKey.R,
AvaKey.S,
AvaKey.T,
AvaKey.U,
AvaKey.V,
AvaKey.W,
AvaKey.X,
AvaKey.Y,
AvaKey.Z,
AvaKey.D0,
AvaKey.D1,
AvaKey.D2,
AvaKey.D3,
AvaKey.D4,
AvaKey.D5,
AvaKey.D6,
AvaKey.D7,
AvaKey.D8,
AvaKey.D9,
AvaKey.OemTilde,
AvaKey.OemTilde,AvaKey.OemMinus,
AvaKey.OemPlus,
AvaKey.OemOpenBrackets,
AvaKey.OemCloseBrackets,
AvaKey.OemSemicolon,
AvaKey.OemQuotes,
AvaKey.OemComma,
AvaKey.OemPeriod,
AvaKey.OemQuestion,
AvaKey.OemBackslash,
// NOTE: invalid
AvaKey.None,
};
private static readonly Dictionary<AvaKey, Key> _avaKeyMapping;
static AvaloniaKeyboardMappingHelper()
{
var inputKeys = Enum.GetValues<Key>();
// NOTE: Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array.
_avaKeyMapping = new Dictionary<AvaKey, Key>();
foreach (var key in inputKeys)
{
if (TryGetAvaKey(key, out var index))
{
_avaKeyMapping[index] = key;
}
}
}
public static bool TryGetAvaKey(Key key, out AvaKey avaKey)
{
avaKey = AvaKey.None;
bool keyExist = (int)key < _keyMapping.Length;
if (keyExist)
{
avaKey = _keyMapping[(int)key];
}
return keyExist;
}
public static Key ToInputKey(AvaKey key)
{
return _avaKeyMapping.GetValueOrDefault(key, Key.Unknown);
}
}
}

View file

@ -1,25 +1,23 @@
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Input;
using System;
using System.Drawing;
using System.Numerics;
namespace Ryujinx.Input.GTK3
namespace Ryujinx.Ava.Input
{
public class GTK3Mouse : IMouse
internal class AvaloniaMouse : IMouse
{
private GTK3MouseDriver _driver;
public GamepadFeaturesFlag Features => throw new NotImplementedException();
private AvaloniaMouseDriver _driver;
public string Id => "0";
public string Name => "GTKMouse";
public string Name => "AvaloniaMouse";
public bool IsConnected => true;
public GamepadFeaturesFlag Features => throw new NotImplementedException();
public bool[] Buttons => _driver.PressedButtons;
public GTK3Mouse(GTK3MouseDriver driver)
public AvaloniaMouse(AvaloniaMouseDriver driver)
{
_driver = driver;
}
@ -83,7 +81,6 @@ namespace Ryujinx.Input.GTK3
public void Dispose()
{
GC.SuppressFinalize(this);
_driver = null;
}
}

View file

@ -0,0 +1,159 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Ryujinx.Input;
using System;
using System.Numerics;
using MouseButton = Ryujinx.Input.MouseButton;
using Size = System.Drawing.Size;
namespace Ryujinx.Ava.Input
{
internal class AvaloniaMouseDriver : IGamepadDriver
{
private Control _widget;
private bool _isDisposed;
private Size _size;
private readonly TopLevel _window;
public bool[] PressedButtons { get; }
public Vector2 CurrentPosition { get; private set; }
public Vector2 Scroll { get; private set; }
public string DriverName => "AvaloniaMouseDriver";
public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
public AvaloniaMouseDriver(TopLevel window, Control parent)
{
_widget = parent;
_window = window;
_widget.PointerMoved += Parent_PointerMovedEvent;
_widget.PointerPressed += Parent_PointerPressedEvent;
_widget.PointerReleased += Parent_PointerReleasedEvent;
_widget.PointerWheelChanged += Parent_PointerWheelChanged;
_window.PointerMoved += Parent_PointerMovedEvent;
_window.PointerPressed += Parent_PointerPressedEvent;
_window.PointerReleased += Parent_PointerReleasedEvent;
_window.PointerWheelChanged += Parent_PointerWheelChanged;
PressedButtons = new bool[(int)MouseButton.Count];
_size = new Size((int)parent.Bounds.Width, (int)parent.Bounds.Height);
parent.GetObservable(Visual.BoundsProperty).Subscribe(Resized);
}
public event Action<string> OnGamepadConnected
{
add { }
remove { }
}
public event Action<string> OnGamepadDisconnected
{
add { }
remove { }
}
private void Resized(Rect rect)
{
_size = new Size((int)rect.Width, (int)rect.Height);
}
private void Parent_PointerWheelChanged(object o, PointerWheelEventArgs args)
{
Scroll = new Vector2((float)args.Delta.X, (float)args.Delta.Y);
}
private void Parent_PointerReleasedEvent(object o, PointerReleasedEventArgs args)
{
uint button = (uint)args.InitialPressMouseButton - 1;
if ((uint)PressedButtons.Length > button)
{
PressedButtons[button] = false;
}
}
private void Parent_PointerPressedEvent(object o, PointerPressedEventArgs args)
{
uint button = (uint)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind;
if ((uint)PressedButtons.Length > button)
{
PressedButtons[button] = true;
}
}
private void Parent_PointerMovedEvent(object o, PointerEventArgs args)
{
Point position = args.GetPosition(_widget);
CurrentPosition = new Vector2((float)position.X, (float)position.Y);
}
public void SetMousePressed(MouseButton button)
{
if ((uint)PressedButtons.Length > (uint)button)
{
PressedButtons[(uint)button] = true;
}
}
public void SetMouseReleased(MouseButton button)
{
if ((uint)PressedButtons.Length > (uint)button)
{
PressedButtons[(uint)button] = false;
}
}
public void SetPosition(double x, double y)
{
CurrentPosition = new Vector2((float)x, (float)y);
}
public bool IsButtonPressed(MouseButton button)
{
if ((uint)PressedButtons.Length > (uint)button)
{
return PressedButtons[(uint)button];
}
return false;
}
public Size GetClientSize()
{
return _size;
}
public IGamepad GetGamepad(string id)
{
return new AvaloniaMouse(this);
}
public void Dispose()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
_widget.PointerMoved -= Parent_PointerMovedEvent;
_widget.PointerPressed -= Parent_PointerPressedEvent;
_widget.PointerReleased -= Parent_PointerReleasedEvent;
_widget.PointerWheelChanged -= Parent_PointerWheelChanged;
_window.PointerMoved -= Parent_PointerMovedEvent;
_window.PointerPressed -= Parent_PointerPressedEvent;
_window.PointerReleased -= Parent_PointerReleasedEvent;
_window.PointerWheelChanged -= Parent_PointerWheelChanged;
_widget = null;
}
}
}

View file

@ -1,94 +0,0 @@
using Gdk;
using Gtk;
using System;
using System.Collections.Generic;
using GtkKey = Gdk.Key;
namespace Ryujinx.Input.GTK3
{
public class GTK3KeyboardDriver : IGamepadDriver
{
private readonly Widget _widget;
private readonly HashSet<GtkKey> _pressedKeys;
public GTK3KeyboardDriver(Widget widget)
{
_widget = widget;
_pressedKeys = new HashSet<GtkKey>();
_widget.KeyPressEvent += OnKeyPress;
_widget.KeyReleaseEvent += OnKeyRelease;
}
public string DriverName => "GTK3";
private static readonly string[] _keyboardIdentifers = new string[1] { "0" };
public ReadOnlySpan<string> GamepadsIds => _keyboardIdentifers;
public event Action<string> OnGamepadConnected
{
add { }
remove { }
}
public event Action<string> OnGamepadDisconnected
{
add { }
remove { }
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_widget.KeyPressEvent -= OnKeyPress;
_widget.KeyReleaseEvent -= OnKeyRelease;
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
[GLib.ConnectBefore]
protected void OnKeyPress(object sender, KeyPressEventArgs args)
{
GtkKey key = (GtkKey)Keyval.ToLower((uint)args.Event.Key);
_pressedKeys.Add(key);
}
[GLib.ConnectBefore]
protected void OnKeyRelease(object sender, KeyReleaseEventArgs args)
{
GtkKey key = (GtkKey)Keyval.ToLower((uint)args.Event.Key);
_pressedKeys.Remove(key);
}
internal bool IsPressed(Key key)
{
if (key == Key.Unbound || key == Key.Unknown)
{
return false;
}
GtkKey nativeKey = GTK3MappingHelper.ToGtkKey(key);
return _pressedKeys.Contains(nativeKey);
}
public IGamepad GetGamepad(string id)
{
if (!_keyboardIdentifers[0].Equals(id))
{
return null;
}
return new GTK3Keyboard(this, _keyboardIdentifers[0], "All keyboards");
}
}
}

View file

@ -1,178 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using GtkKey = Gdk.Key;
namespace Ryujinx.Input.GTK3
{
public static class GTK3MappingHelper
{
private static readonly GtkKey[] _keyMapping = new GtkKey[(int)Key.Count]
{
// NOTE: invalid
GtkKey.blank,
GtkKey.Shift_L,
GtkKey.Shift_R,
GtkKey.Control_L,
GtkKey.Control_R,
GtkKey.Alt_L,
GtkKey.Alt_R,
GtkKey.Super_L,
GtkKey.Super_R,
GtkKey.Menu,
GtkKey.F1,
GtkKey.F2,
GtkKey.F3,
GtkKey.F4,
GtkKey.F5,
GtkKey.F6,
GtkKey.F7,
GtkKey.F8,
GtkKey.F9,
GtkKey.F10,
GtkKey.F11,
GtkKey.F12,
GtkKey.F13,
GtkKey.F14,
GtkKey.F15,
GtkKey.F16,
GtkKey.F17,
GtkKey.F18,
GtkKey.F19,
GtkKey.F20,
GtkKey.F21,
GtkKey.F22,
GtkKey.F23,
GtkKey.F24,
GtkKey.F25,
GtkKey.F26,
GtkKey.F27,
GtkKey.F28,
GtkKey.F29,
GtkKey.F30,
GtkKey.F31,
GtkKey.F32,
GtkKey.F33,
GtkKey.F34,
GtkKey.F35,
GtkKey.Up,
GtkKey.Down,
GtkKey.Left,
GtkKey.Right,
GtkKey.Return,
GtkKey.Escape,
GtkKey.space,
GtkKey.Tab,
GtkKey.BackSpace,
GtkKey.Insert,
GtkKey.Delete,
GtkKey.Page_Up,
GtkKey.Page_Down,
GtkKey.Home,
GtkKey.End,
GtkKey.Caps_Lock,
GtkKey.Scroll_Lock,
GtkKey.Print,
GtkKey.Pause,
GtkKey.Num_Lock,
GtkKey.Clear,
GtkKey.KP_0,
GtkKey.KP_1,
GtkKey.KP_2,
GtkKey.KP_3,
GtkKey.KP_4,
GtkKey.KP_5,
GtkKey.KP_6,
GtkKey.KP_7,
GtkKey.KP_8,
GtkKey.KP_9,
GtkKey.KP_Divide,
GtkKey.KP_Multiply,
GtkKey.KP_Subtract,
GtkKey.KP_Add,
GtkKey.KP_Decimal,
GtkKey.KP_Enter,
GtkKey.a,
GtkKey.b,
GtkKey.c,
GtkKey.d,
GtkKey.e,
GtkKey.f,
GtkKey.g,
GtkKey.h,
GtkKey.i,
GtkKey.j,
GtkKey.k,
GtkKey.l,
GtkKey.m,
GtkKey.n,
GtkKey.o,
GtkKey.p,
GtkKey.q,
GtkKey.r,
GtkKey.s,
GtkKey.t,
GtkKey.u,
GtkKey.v,
GtkKey.w,
GtkKey.x,
GtkKey.y,
GtkKey.z,
GtkKey.Key_0,
GtkKey.Key_1,
GtkKey.Key_2,
GtkKey.Key_3,
GtkKey.Key_4,
GtkKey.Key_5,
GtkKey.Key_6,
GtkKey.Key_7,
GtkKey.Key_8,
GtkKey.Key_9,
GtkKey.grave,
GtkKey.grave,
GtkKey.minus,
GtkKey.plus,
GtkKey.bracketleft,
GtkKey.bracketright,
GtkKey.semicolon,
GtkKey.quoteright,
GtkKey.comma,
GtkKey.period,
GtkKey.slash,
GtkKey.backslash,
// NOTE: invalid
GtkKey.blank,
};
private static readonly Dictionary<GtkKey, Key> _gtkKeyMapping;
static GTK3MappingHelper()
{
var inputKeys = Enum.GetValues<Key>().SkipLast(1);
// GtkKey is not contiguous and quite large, so use a dictionary instead of an array.
_gtkKeyMapping = new Dictionary<GtkKey, Key>();
foreach (var key in inputKeys)
{
var index = ToGtkKey(key);
_gtkKeyMapping[index] = key;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static GtkKey ToGtkKey(Key key)
{
return _keyMapping[(int)key];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Key ToInputKey(GtkKey key)
{
return _gtkKeyMapping.GetValueOrDefault(key, Key.Unknown);
}
}
}

View file

@ -1,108 +0,0 @@
using Gdk;
using Gtk;
using System;
using System.Numerics;
using Size = System.Drawing.Size;
namespace Ryujinx.Input.GTK3
{
public class GTK3MouseDriver : IGamepadDriver
{
private Widget _widget;
private bool _isDisposed;
public bool[] PressedButtons { get; }
public Vector2 CurrentPosition { get; private set; }
public Vector2 Scroll { get; private set; }
public GTK3MouseDriver(Widget parent)
{
_widget = parent;
_widget.MotionNotifyEvent += Parent_MotionNotifyEvent;
_widget.ButtonPressEvent += Parent_ButtonPressEvent;
_widget.ButtonReleaseEvent += Parent_ButtonReleaseEvent;
_widget.ScrollEvent += Parent_ScrollEvent;
PressedButtons = new bool[(int)MouseButton.Count];
}
[GLib.ConnectBefore]
private void Parent_ScrollEvent(object o, ScrollEventArgs args)
{
Scroll = new Vector2((float)args.Event.X, (float)args.Event.Y);
}
[GLib.ConnectBefore]
private void Parent_ButtonReleaseEvent(object o, ButtonReleaseEventArgs args)
{
PressedButtons[args.Event.Button - 1] = false;
}
[GLib.ConnectBefore]
private void Parent_ButtonPressEvent(object o, ButtonPressEventArgs args)
{
PressedButtons[args.Event.Button - 1] = true;
}
[GLib.ConnectBefore]
private void Parent_MotionNotifyEvent(object o, MotionNotifyEventArgs args)
{
if (args.Event.Device.InputSource == InputSource.Mouse)
{
CurrentPosition = new Vector2((float)args.Event.X, (float)args.Event.Y);
}
}
public bool IsButtonPressed(MouseButton button)
{
return PressedButtons[(int)button];
}
public Size GetClientSize()
{
return new Size(_widget.AllocatedWidth, _widget.AllocatedHeight);
}
public string DriverName => "GTK3";
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 GTK3Mouse(this);
}
public void Dispose()
{
if (_isDisposed)
{
return;
}
GC.SuppressFinalize(this);
_isDisposed = true;
_widget.MotionNotifyEvent -= Parent_MotionNotifyEvent;
_widget.ButtonPressEvent -= Parent_ButtonPressEvent;
_widget.ButtonReleaseEvent -= Parent_ButtonReleaseEvent;
_widget = null;
}
}
}