Fix settings keyboard input focus loss

This commit is contained in:
Babib3l
2026-03-21 22:45:19 +01:00
parent 9a5e4c06af
commit 7becde9d8e
3 changed files with 79 additions and 11 deletions

View File

@@ -15,6 +15,7 @@ namespace Ryujinx.Ava.Input
private readonly Control _control;
private readonly Dictionary<Key, int> _semanticPressedKeys;
private readonly Dictionary<ConfigPhysicalKey, int> _physicalPressedKeys;
private readonly Dictionary<Key, ConfigPhysicalKey> _observedPhysicalKeysBySemanticKey;
private readonly KeyboardInputMode _defaultMode;
public event EventHandler<KeyEventArgs> KeyPressed;
@@ -29,6 +30,7 @@ namespace Ryujinx.Ava.Input
_control = control;
_semanticPressedKeys = [];
_physicalPressedKeys = [];
_observedPhysicalKeysBySemanticKey = [];
_defaultMode = defaultMode;
_control.KeyDown += OnKeyPress;
@@ -192,17 +194,37 @@ namespace Ryujinx.Ava.Input
private void UpdateKeyStates(KeyEventArgs args, bool isPressed)
{
UpdateKeyState(_semanticPressedKeys, AvaloniaKeyboardMappingHelper.ToInputKey(args.PhysicalKey, args.Key), isPressed);
UpdateKeyState(_physicalPressedKeys, GetPhysicalInputKey(args), isPressed);
Key semanticKey = AvaloniaKeyboardMappingHelper.ToInputKey(args.Key);
Key resolvedSemanticKey = AvaloniaKeyboardMappingHelper.ToInputKey(args.PhysicalKey, args.Key);
ConfigPhysicalKey physicalKey = GetPhysicalInputKey(args, semanticKey);
UpdateKeyState(_semanticPressedKeys, resolvedSemanticKey, isPressed);
UpdateKeyState(_physicalPressedKeys, physicalKey, isPressed);
if (isPressed &&
semanticKey is not Key.Unknown and not Key.Unbound &&
physicalKey is not ConfigPhysicalKey.Unknown and not ConfigPhysicalKey.Unbound)
{
_observedPhysicalKeysBySemanticKey[semanticKey] = physicalKey;
}
}
private static ConfigPhysicalKey GetPhysicalInputKey(KeyEventArgs args)
private ConfigPhysicalKey GetPhysicalInputKey(KeyEventArgs args, Key semanticKey)
{
Key key = AvaloniaKeyboardMappingHelper.ToInputKey(args.PhysicalKey);
return key is >= Key.Unknown and < Key.Count
? (ConfigPhysicalKey)(int)key
: ConfigPhysicalKey.Unknown;
if (key is >= Key.Unknown and < Key.Count)
{
return (ConfigPhysicalKey)(int)key;
}
if (semanticKey is not Key.Unknown and not Key.Unbound &&
_observedPhysicalKeysBySemanticKey.TryGetValue(semanticKey, out ConfigPhysicalKey observedPhysicalKey))
{
return observedPhysicalKey;
}
return ConfigPhysicalKey.Unknown;
}
public void Dispose()

View File

@@ -43,6 +43,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private const string KeyboardString = "keyboard";
private const string ControllerString = "controller";
private readonly MainWindow _mainWindow;
private Control _keyboardDriverControl;
private PlayerIndex _playerId;
private PlayerIndex _playerIdChoose;
@@ -66,7 +67,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public IGamepadDriver AvaloniaKeyboardDriver { get; }
public IGamepadDriver AvaloniaKeyboardDriver { get; private set; }
public IGamepad SelectedGamepad
{
@@ -291,9 +292,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
_mainWindow = RyujinxApp.MainWindow;
AvaloniaKeyboardDriver keyboardDriver = new(owner, KeyboardInputMode.Physical);
keyboardDriver.KeyPressed += PhysicalKeyLabelHelper.ObserveKeyPress;
AvaloniaKeyboardDriver = keyboardDriver;
ReplaceKeyboardDriver(owner);
PhysicalKeyLabelHelper.LabelsChanged += OnPhysicalKeyLabelsChanged;
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
@@ -313,6 +312,16 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
_isChangeTrackingActive = true;
}
public void RetargetKeyboardDriver(Control owner)
{
if (!Program.PreviewerDetached)
{
return;
}
ReplaceKeyboardDriver(owner);
}
public InputViewModel()
{
PlayerIndexes = [];
@@ -1096,6 +1105,34 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
}
private void ReplaceKeyboardDriver(Control owner)
{
Control target = TopLevel.GetTopLevel(owner) as Control ?? owner;
if (ReferenceEquals(_keyboardDriverControl, target))
{
return;
}
if (AvaloniaKeyboardDriver is AvaloniaKeyboardDriver oldKeyboardDriver)
{
oldKeyboardDriver.KeyPressed -= PhysicalKeyLabelHelper.ObserveKeyPress;
oldKeyboardDriver.Dispose();
}
_keyboardDriverControl = target;
AvaloniaKeyboardDriver keyboardDriver = new(target, KeyboardInputMode.Physical);
keyboardDriver.KeyPressed += PhysicalKeyLabelHelper.ObserveKeyPress;
AvaloniaKeyboardDriver = keyboardDriver;
if (_isLoaded && Device > 0 && Device < Devices.Count && Devices[Device].Type == DeviceType.Keyboard)
{
SelectedGamepad?.Dispose();
LoadInputDriver();
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
@@ -1110,7 +1147,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
SelectedGamepad?.Dispose();
AvaloniaKeyboardDriver.Dispose();
AvaloniaKeyboardDriver?.Dispose();
}
}
}

View File

@@ -1,4 +1,5 @@
using Avalonia.Controls;
using Avalonia;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
@@ -20,6 +21,13 @@ namespace Ryujinx.Ava.UI.Views.Input
InitializeComponent();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
ViewModel?.RetargetKeyboardDriver(this);
}
public void SaveCurrentProfile()
{
ViewModel.Save();
@@ -30,6 +38,7 @@ namespace Ryujinx.Ava.UI.Views.Input
Dispose();
ViewModel = new InputViewModel(this, enableConfigGlobal); // Create new Input Page with global input configs
InitializeComponent();
ViewModel.RetargetKeyboardDriver(this);
}
private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)