Added better support for the different keyboards.

This commit is contained in:
Babib3l
2026-03-18 18:17:06 +01:00
parent 13c8b57063
commit ebd8cc4f4a
4 changed files with 231 additions and 17 deletions

View File

@@ -1608,7 +1608,7 @@
"el_GR": "", "el_GR": "",
"en_US": "`", "en_US": "`",
"es_ES": "º", "es_ES": "º",
"fr_FR": null, "fr_FR": "<",
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
@@ -1858,7 +1858,7 @@
"el_GR": "", "el_GR": "",
"en_US": "\\", "en_US": "\\",
"es_ES": "<", "es_ES": "<",
"fr_FR": "<", "fr_FR": "*",
"he_IL": "", "he_IL": "",
"it_IT": "<", "it_IT": "<",
"ja_JP": "", "ja_JP": "",

View File

@@ -4,7 +4,6 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Input; using Ryujinx.Input;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using AvaKey = Avalonia.Input.Key;
using Key = Ryujinx.Input.Key; using Key = Ryujinx.Input.Key;
namespace Ryujinx.Ava.Input namespace Ryujinx.Ava.Input
@@ -13,7 +12,7 @@ namespace Ryujinx.Ava.Input
{ {
private static readonly string[] _keyboardIdentifers = ["0"]; private static readonly string[] _keyboardIdentifers = ["0"];
private readonly Control _control; private readonly Control _control;
private readonly HashSet<AvaKey> _pressedKeys; private readonly Dictionary<Key, int> _pressedKeys;
public event EventHandler<KeyEventArgs> KeyPressed; public event EventHandler<KeyEventArgs> KeyPressed;
public event EventHandler<KeyEventArgs> KeyRelease; public event EventHandler<KeyEventArgs> KeyRelease;
@@ -65,21 +64,48 @@ namespace Ryujinx.Ava.Input
{ {
if (disposing) if (disposing)
{ {
_control.KeyUp -= OnKeyPress; _control.KeyDown -= OnKeyPress;
_control.KeyDown -= OnKeyRelease; _control.KeyUp -= OnKeyRelease;
} }
} }
protected void OnKeyPress(object sender, KeyEventArgs args) protected void OnKeyPress(object sender, KeyEventArgs args)
{ {
_pressedKeys.Add(args.Key); Key key = AvaloniaKeyboardMappingHelper.ToInputKey(args.PhysicalKey, args.Key);
if (key != Key.Unknown)
{
if (_pressedKeys.TryGetValue(key, out int count))
{
_pressedKeys[key] = count + 1;
}
else
{
_pressedKeys[key] = 1;
}
}
KeyPressed?.Invoke(this, args); KeyPressed?.Invoke(this, args);
} }
protected void OnKeyRelease(object sender, KeyEventArgs args) protected void OnKeyRelease(object sender, KeyEventArgs args)
{ {
_pressedKeys.Remove(args.Key); Key key = AvaloniaKeyboardMappingHelper.ToInputKey(args.PhysicalKey, args.Key);
if (key != Key.Unknown)
{
if (_pressedKeys.TryGetValue(key, out int count))
{
if (count <= 1)
{
_pressedKeys.Remove(key);
}
else
{
_pressedKeys[key] = count - 1;
}
}
}
KeyRelease?.Invoke(this, args); KeyRelease?.Invoke(this, args);
} }
@@ -91,9 +117,7 @@ namespace Ryujinx.Ava.Input
return false; return false;
} }
AvaloniaKeyboardMappingHelper.TryGetAvaKey(key, out AvaKey nativeKey); return _pressedKeys.ContainsKey(key);
return _pressedKeys.Contains(nativeKey);
} }
public void Clear() public void Clear()

View File

@@ -2,6 +2,7 @@ using Ryujinx.Input;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using AvaKey = Avalonia.Input.Key; using AvaKey = Avalonia.Input.Key;
using AvaPhysicalKey = Avalonia.Input.PhysicalKey;
namespace Ryujinx.Ava.Input namespace Ryujinx.Ava.Input
{ {
@@ -132,7 +133,8 @@ namespace Ryujinx.Ava.Input
AvaKey.D8, AvaKey.D8,
AvaKey.D9, AvaKey.D9,
AvaKey.OemTilde, AvaKey.OemTilde,
AvaKey.OemTilde,AvaKey.OemMinus, AvaKey.Oem102,
AvaKey.OemMinus,
AvaKey.OemPlus, AvaKey.OemPlus,
AvaKey.OemOpenBrackets, AvaKey.OemOpenBrackets,
AvaKey.OemCloseBrackets, AvaKey.OemCloseBrackets,
@@ -147,7 +149,149 @@ namespace Ryujinx.Ava.Input
AvaKey.None AvaKey.None
]; ];
private static readonly AvaPhysicalKey[] _physicalKeyMapping =
[
// NOTE: Invalid
AvaPhysicalKey.None,
AvaPhysicalKey.ShiftLeft,
AvaPhysicalKey.ShiftRight,
AvaPhysicalKey.ControlLeft,
AvaPhysicalKey.ControlRight,
AvaPhysicalKey.AltLeft,
AvaPhysicalKey.AltRight,
AvaPhysicalKey.MetaLeft,
AvaPhysicalKey.MetaRight,
AvaPhysicalKey.ContextMenu,
AvaPhysicalKey.F1,
AvaPhysicalKey.F2,
AvaPhysicalKey.F3,
AvaPhysicalKey.F4,
AvaPhysicalKey.F5,
AvaPhysicalKey.F6,
AvaPhysicalKey.F7,
AvaPhysicalKey.F8,
AvaPhysicalKey.F9,
AvaPhysicalKey.F10,
AvaPhysicalKey.F11,
AvaPhysicalKey.F12,
AvaPhysicalKey.F13,
AvaPhysicalKey.F14,
AvaPhysicalKey.F15,
AvaPhysicalKey.F16,
AvaPhysicalKey.F17,
AvaPhysicalKey.F18,
AvaPhysicalKey.F19,
AvaPhysicalKey.F20,
AvaPhysicalKey.F21,
AvaPhysicalKey.F22,
AvaPhysicalKey.F23,
AvaPhysicalKey.F24,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.None,
AvaPhysicalKey.ArrowUp,
AvaPhysicalKey.ArrowDown,
AvaPhysicalKey.ArrowLeft,
AvaPhysicalKey.ArrowRight,
AvaPhysicalKey.Enter,
AvaPhysicalKey.Escape,
AvaPhysicalKey.Space,
AvaPhysicalKey.Tab,
AvaPhysicalKey.Backspace,
AvaPhysicalKey.Insert,
AvaPhysicalKey.Delete,
AvaPhysicalKey.PageUp,
AvaPhysicalKey.PageDown,
AvaPhysicalKey.Home,
AvaPhysicalKey.End,
AvaPhysicalKey.CapsLock,
AvaPhysicalKey.ScrollLock,
AvaPhysicalKey.PrintScreen,
AvaPhysicalKey.Pause,
AvaPhysicalKey.NumLock,
AvaPhysicalKey.NumPadClear,
AvaPhysicalKey.NumPad0,
AvaPhysicalKey.NumPad1,
AvaPhysicalKey.NumPad2,
AvaPhysicalKey.NumPad3,
AvaPhysicalKey.NumPad4,
AvaPhysicalKey.NumPad5,
AvaPhysicalKey.NumPad6,
AvaPhysicalKey.NumPad7,
AvaPhysicalKey.NumPad8,
AvaPhysicalKey.NumPad9,
AvaPhysicalKey.NumPadDivide,
AvaPhysicalKey.NumPadMultiply,
AvaPhysicalKey.NumPadSubtract,
AvaPhysicalKey.NumPadAdd,
AvaPhysicalKey.NumPadDecimal,
AvaPhysicalKey.NumPadEnter,
AvaPhysicalKey.A,
AvaPhysicalKey.B,
AvaPhysicalKey.C,
AvaPhysicalKey.D,
AvaPhysicalKey.E,
AvaPhysicalKey.F,
AvaPhysicalKey.G,
AvaPhysicalKey.H,
AvaPhysicalKey.I,
AvaPhysicalKey.J,
AvaPhysicalKey.K,
AvaPhysicalKey.L,
AvaPhysicalKey.M,
AvaPhysicalKey.N,
AvaPhysicalKey.O,
AvaPhysicalKey.P,
AvaPhysicalKey.Q,
AvaPhysicalKey.R,
AvaPhysicalKey.S,
AvaPhysicalKey.T,
AvaPhysicalKey.U,
AvaPhysicalKey.V,
AvaPhysicalKey.W,
AvaPhysicalKey.X,
AvaPhysicalKey.Y,
AvaPhysicalKey.Z,
AvaPhysicalKey.Digit0,
AvaPhysicalKey.Digit1,
AvaPhysicalKey.Digit2,
AvaPhysicalKey.Digit3,
AvaPhysicalKey.Digit4,
AvaPhysicalKey.Digit5,
AvaPhysicalKey.Digit6,
AvaPhysicalKey.Digit7,
AvaPhysicalKey.Digit8,
AvaPhysicalKey.Digit9,
AvaPhysicalKey.Backquote,
AvaPhysicalKey.IntlBackslash,
AvaPhysicalKey.Minus,
AvaPhysicalKey.Equal,
AvaPhysicalKey.BracketLeft,
AvaPhysicalKey.BracketRight,
AvaPhysicalKey.Semicolon,
AvaPhysicalKey.Quote,
AvaPhysicalKey.Comma,
AvaPhysicalKey.Period,
AvaPhysicalKey.Slash,
AvaPhysicalKey.Backslash,
// NOTE: invalid
AvaPhysicalKey.None
];
private static readonly Dictionary<AvaKey, Key> _avaKeyMapping; private static readonly Dictionary<AvaKey, Key> _avaKeyMapping;
private static readonly Dictionary<AvaPhysicalKey, Key> _avaPhysicalKeyMapping;
static AvaloniaKeyboardMappingHelper() static AvaloniaKeyboardMappingHelper()
{ {
@@ -155,21 +299,42 @@ namespace Ryujinx.Ava.Input
// NOTE: Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array. // NOTE: Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array.
_avaKeyMapping = new Dictionary<AvaKey, Key>(); _avaKeyMapping = new Dictionary<AvaKey, Key>();
_avaPhysicalKeyMapping = new Dictionary<AvaPhysicalKey, Key>();
foreach (Key key in inputKeys) foreach (Key key in inputKeys)
{ {
if (TryGetAvaKey(key, out AvaKey index)) if (TryGetAvaKey(key, out AvaKey avaKey))
{ {
_avaKeyMapping[index] = key; _avaKeyMapping[avaKey] = key;
}
if (TryGetAvaPhysicalKey(key, out AvaPhysicalKey avaPhysicalKey))
{
_avaPhysicalKeyMapping[avaPhysicalKey] = key;
} }
} }
// Alias additional Avalonia key values to improve non-US layout support.
_avaKeyMapping[AvaKey.Oem1] = Key.Semicolon;
_avaKeyMapping[AvaKey.Oem2] = Key.Slash;
_avaKeyMapping[AvaKey.Oem3] = Key.Tilde;
_avaKeyMapping[AvaKey.Oem4] = Key.BracketLeft;
_avaKeyMapping[AvaKey.Oem5] = Key.BackSlash;
_avaKeyMapping[AvaKey.Oem6] = Key.BracketRight;
_avaKeyMapping[AvaKey.Oem7] = Key.Quote;
_avaKeyMapping[AvaKey.OemBackslash] = Key.Grave;
_avaKeyMapping[AvaKey.Oem102] = Key.Grave;
// Common alternates for non-US/JIS physical keys.
_avaPhysicalKeyMapping[AvaPhysicalKey.IntlRo] = Key.BackSlash;
_avaPhysicalKeyMapping[AvaPhysicalKey.IntlYen] = Key.BackSlash;
} }
public static bool TryGetAvaKey(Key key, out AvaKey avaKey) public static bool TryGetAvaKey(Key key, out AvaKey avaKey)
{ {
avaKey = AvaKey.None; avaKey = AvaKey.None;
bool keyExist = (int)key < _keyMapping.Length; bool keyExist = key < Key.Count && (int)key < _keyMapping.Length;
if (keyExist) if (keyExist)
{ {
avaKey = _keyMapping[(int)key]; avaKey = _keyMapping[(int)key];
@@ -178,9 +343,34 @@ namespace Ryujinx.Ava.Input
return keyExist; return keyExist;
} }
public static bool TryGetAvaPhysicalKey(Key key, out AvaPhysicalKey avaPhysicalKey)
{
avaPhysicalKey = AvaPhysicalKey.None;
bool keyExist = key < Key.Count && (int)key < _physicalKeyMapping.Length;
if (keyExist)
{
avaPhysicalKey = _physicalKeyMapping[(int)key];
}
return keyExist;
}
public static Key ToInputKey(AvaKey key) public static Key ToInputKey(AvaKey key)
{ {
return _avaKeyMapping.GetValueOrDefault(key, Key.Unknown); return _avaKeyMapping.GetValueOrDefault(key, Key.Unknown);
} }
public static Key ToInputKey(AvaPhysicalKey key)
{
return _avaPhysicalKeyMapping.GetValueOrDefault(key, Key.Unknown);
}
public static Key ToInputKey(AvaPhysicalKey physicalKey, AvaKey key)
{
Key inputKey = ToInputKey(key);
return inputKey != Key.Unknown ? inputKey : ToInputKey(physicalKey);
}
} }
} }

View File

@@ -65,7 +65,7 @@ namespace Ryujinx.Ava.UI.Applet
private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, KeyEventArgs e) private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, KeyEventArgs e)
{ {
HidKey key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key); HidKey key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.PhysicalKey, e.Key);
if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true)) if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
{ {
@@ -85,7 +85,7 @@ namespace Ryujinx.Ava.UI.Applet
private void AvaloniaDynamicTextInputHandler_KeyPressed(object sender, KeyEventArgs e) private void AvaloniaDynamicTextInputHandler_KeyPressed(object sender, KeyEventArgs e)
{ {
HidKey key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key); HidKey key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.PhysicalKey, e.Key);
if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true)) if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
{ {