mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-06-05 03:49:17 +00:00
Added better support for the different keyboards.
This commit is contained in:
@@ -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": "",
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user