mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-06-04 11:29:14 +00:00
Fix settings keyboard input focus loss
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user