mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-06-04 11:29:14 +00:00
Fallback to keyboard on controller disconnect
This commit is contained in:
@@ -36,6 +36,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
private List<InputConfig> _inputConfig;
|
private List<InputConfig> _inputConfig;
|
||||||
|
private List<InputConfig> _requestedInputConfig;
|
||||||
private bool _enableKeyboard;
|
private bool _enableKeyboard;
|
||||||
private bool _enableMouse;
|
private bool _enableMouse;
|
||||||
private Switch _device;
|
private Switch _device;
|
||||||
@@ -52,6 +53,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
_gamepadDriver = gamepadDriver;
|
_gamepadDriver = gamepadDriver;
|
||||||
_mouseDriver = mouseDriver;
|
_mouseDriver = mouseDriver;
|
||||||
_inputConfig = [];
|
_inputConfig = [];
|
||||||
|
_requestedInputConfig = [];
|
||||||
|
|
||||||
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
@@ -89,14 +91,14 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
ReloadConfiguration(_requestedInputConfig, _enableKeyboard, _enableMouse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadConnected(string id)
|
private void HandleOnGamepadConnected(string id)
|
||||||
{
|
{
|
||||||
// Force input reload
|
// Force input reload
|
||||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
ReloadConfiguration(_requestedInputConfig, _enableKeyboard, _enableMouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -127,11 +129,13 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
_requestedInputConfig = inputConfig?.ToList() ?? [];
|
||||||
|
|
||||||
NpadController[] oldControllers = _controllers.ToArray();
|
NpadController[] oldControllers = _controllers.ToArray();
|
||||||
|
|
||||||
List<InputConfig> validInputs = [];
|
List<InputConfig> validInputs = [];
|
||||||
|
|
||||||
foreach (InputConfig inputConfigEntry in inputConfig)
|
foreach (InputConfig inputConfigEntry in _requestedInputConfig)
|
||||||
{
|
{
|
||||||
NpadController controller;
|
NpadController controller;
|
||||||
int index = (int)inputConfigEntry.PlayerIndex;
|
int index = (int)inputConfigEntry.PlayerIndex;
|
||||||
@@ -147,7 +151,17 @@ namespace Ryujinx.Input.HLE
|
|||||||
controller = new(_cemuHookClient);
|
controller = new(_cemuHookClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
|
InputConfig activeConfig = inputConfigEntry;
|
||||||
|
bool isValid = DriverConfigurationUpdate(ref controller, activeConfig);
|
||||||
|
|
||||||
|
if (!isValid &&
|
||||||
|
enableKeyboard &&
|
||||||
|
inputConfigEntry is StandardControllerInputConfig &&
|
||||||
|
TryGetKeyboardFallback(inputConfigEntry, out StandardKeyboardInputConfig fallbackConfig))
|
||||||
|
{
|
||||||
|
activeConfig = fallbackConfig;
|
||||||
|
isValid = DriverConfigurationUpdate(ref controller, activeConfig);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
@@ -157,7 +171,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_controllers[index] = controller;
|
_controllers[index] = controller;
|
||||||
validInputs.Add(inputConfigEntry);
|
validInputs.Add(activeConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +183,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
oldControllers[i] = null;
|
oldControllers[i] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_inputConfig = inputConfig;
|
_inputConfig = validInputs;
|
||||||
_enableKeyboard = enableKeyboard;
|
_enableKeyboard = enableKeyboard;
|
||||||
_enableMouse = enableMouse;
|
_enableMouse = enableMouse;
|
||||||
|
|
||||||
@@ -177,6 +191,79 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetKeyboardFallback(InputConfig inputConfig, out StandardKeyboardInputConfig fallbackConfig)
|
||||||
|
{
|
||||||
|
fallbackConfig = null;
|
||||||
|
|
||||||
|
ReadOnlySpan<string> keyboardIds = _keyboardDriver.GamepadsIds;
|
||||||
|
|
||||||
|
if (keyboardIds.IsEmpty)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string keyboardId = keyboardIds[0];
|
||||||
|
|
||||||
|
using IGamepad keyboard = _keyboardDriver.GetGamepad(keyboardId);
|
||||||
|
|
||||||
|
if (keyboard == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fallbackConfig = new StandardKeyboardInputConfig
|
||||||
|
{
|
||||||
|
Version = InputConfig.CurrentVersion,
|
||||||
|
Backend = InputBackendType.WindowKeyboard,
|
||||||
|
Id = keyboardId,
|
||||||
|
Name = keyboard.Name,
|
||||||
|
PlayerIndex = inputConfig.PlayerIndex,
|
||||||
|
ControllerType = inputConfig.ControllerType,
|
||||||
|
LeftJoycon = new LeftJoyconCommonConfig<PhysicalKey>
|
||||||
|
{
|
||||||
|
DpadUp = PhysicalKey.Up,
|
||||||
|
DpadDown = PhysicalKey.Down,
|
||||||
|
DpadLeft = PhysicalKey.Left,
|
||||||
|
DpadRight = PhysicalKey.Right,
|
||||||
|
ButtonMinus = PhysicalKey.Minus,
|
||||||
|
ButtonL = PhysicalKey.E,
|
||||||
|
ButtonZl = PhysicalKey.Q,
|
||||||
|
ButtonSl = PhysicalKey.Unbound,
|
||||||
|
ButtonSr = PhysicalKey.Unbound,
|
||||||
|
},
|
||||||
|
LeftJoyconStick = new JoyconConfigKeyboardStick<PhysicalKey>
|
||||||
|
{
|
||||||
|
StickUp = PhysicalKey.W,
|
||||||
|
StickDown = PhysicalKey.S,
|
||||||
|
StickLeft = PhysicalKey.A,
|
||||||
|
StickRight = PhysicalKey.D,
|
||||||
|
StickButton = PhysicalKey.F,
|
||||||
|
},
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<PhysicalKey>
|
||||||
|
{
|
||||||
|
ButtonA = PhysicalKey.Z,
|
||||||
|
ButtonB = PhysicalKey.X,
|
||||||
|
ButtonX = PhysicalKey.C,
|
||||||
|
ButtonY = PhysicalKey.V,
|
||||||
|
ButtonPlus = PhysicalKey.Plus,
|
||||||
|
ButtonR = PhysicalKey.U,
|
||||||
|
ButtonZr = PhysicalKey.O,
|
||||||
|
ButtonSl = PhysicalKey.Unbound,
|
||||||
|
ButtonSr = PhysicalKey.Unbound,
|
||||||
|
},
|
||||||
|
RightJoyconStick = new JoyconConfigKeyboardStick<PhysicalKey>
|
||||||
|
{
|
||||||
|
StickUp = PhysicalKey.I,
|
||||||
|
StickDown = PhysicalKey.K,
|
||||||
|
StickLeft = PhysicalKey.J,
|
||||||
|
StickRight = PhysicalKey.L,
|
||||||
|
StickButton = PhysicalKey.H,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void UnblockInputUpdates()
|
public void UnblockInputUpdates()
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
@@ -334,7 +421,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal InputConfig GetPlayerInputConfigByIndex(int index)
|
public InputConfig GetPlayerInputConfigByIndex(int index)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -348,15 +348,19 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
private void LoadConfiguration(InputConfig inputConfig = null)
|
private void LoadConfiguration(InputConfig inputConfig = null)
|
||||||
{
|
{
|
||||||
|
InputConfig persistedConfig;
|
||||||
|
|
||||||
if (UseGlobalConfig && Program.UseExtraConfig)
|
if (UseGlobalConfig && Program.UseExtraConfig)
|
||||||
{
|
{
|
||||||
Config = inputConfig ?? ConfigurationState.InstanceExtra.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
|
persistedConfig = ConfigurationState.InstanceExtra.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Config = inputConfig ?? ConfigurationState.Instance.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
|
persistedConfig = ConfigurationState.Instance.Hid.InputConfig.Value.FirstOrDefault(inputConfig => inputConfig.PlayerIndex == _playerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Config = inputConfig ?? GetDisplayedInputConfig(persistedConfig);
|
||||||
|
|
||||||
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
||||||
{
|
{
|
||||||
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig), VisualStick);
|
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig), VisualStick);
|
||||||
@@ -368,6 +372,18 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InputConfig GetDisplayedInputConfig(InputConfig persistedConfig)
|
||||||
|
{
|
||||||
|
if (persistedConfig is not StandardControllerInputConfig)
|
||||||
|
{
|
||||||
|
return persistedConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputConfig activeConfig = _mainWindow?.ViewModel.AppHost?.NpadManager?.GetPlayerInputConfigByIndex((int)_playerId);
|
||||||
|
|
||||||
|
return activeConfig is StandardKeyboardInputConfig ? activeConfig : persistedConfig;
|
||||||
|
}
|
||||||
|
|
||||||
private void FindPairedDeviceInConfigFile()
|
private void FindPairedDeviceInConfigFile()
|
||||||
{
|
{
|
||||||
// This function allows you to output a message about the device configuration found in the file
|
// This function allows you to output a message about the device configuration found in the file
|
||||||
@@ -475,11 +491,24 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
{
|
{
|
||||||
_isChangeTrackingActive = false; // Disable configuration change tracking
|
_isChangeTrackingActive = false; // Disable configuration change tracking
|
||||||
|
|
||||||
|
bool shouldApplyKeyboardFallback = Config is StandardControllerInputConfig controllerConfig && controllerConfig.Id == id;
|
||||||
|
|
||||||
LoadDevices();
|
LoadDevices();
|
||||||
|
|
||||||
IsModified = true;
|
if (shouldApplyKeyboardFallback)
|
||||||
RevertChanges();
|
{
|
||||||
FindPairedDeviceInConfigFile();
|
LoadConfiguration();
|
||||||
|
LoadDevice();
|
||||||
|
NotificationIsVisible = false;
|
||||||
|
IsModified = false;
|
||||||
|
NotifyChanges();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsModified = true;
|
||||||
|
RevertChanges();
|
||||||
|
FindPairedDeviceInConfigFile();
|
||||||
|
}
|
||||||
|
|
||||||
_isChangeTrackingActive = true; // Enable configuration change tracking
|
_isChangeTrackingActive = true; // Enable configuration change tracking
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user