Problems with Input Injection
Describe the bug
- Multiple calls to
InputInjector.TryCreate()cause the app to crash. InitializeGamepadInjection()always causes an app to crash if called after a call toUninitializeGamepadInjection()on the sameInputInjectorinstance.
Similar problems have been reported for mouse injection.
if an InputInjector is created and used a second time no mouse input is simulated (without failure).
Steps to reproduce the bug
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Gaming.Input;
using Windows.UI.Input.Preview.Injection;
namespace PC_Win
{
internal class GamepadInjector
{
private InjectedInputGamepadInfo gamepadState;
private readonly InputInjector injector;
private bool isConnected;
public GamepadInjector()
{
injector = InputInjector.TryCreate();
gamepadState = new InjectedInputGamepadInfo();
isConnected = false;
}
public void ConnectGamepad()
{
if (!isConnected)
{
try
{
injector.InitializeGamepadInjection();
isConnected = true;
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
public void DisconnectGamepad()
{
if (isConnected)
{
try
{
injector.UninitializeGamepadInjection();
isConnected = false;
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
public void Update(InjectedInputGamepadInfo state)
{
gamepadState = state;
}
public void PressButton(GamepadButtons button)
{
gamepadState.Buttons |= button;
}
public void ReleaseButton(GamepadButtons button)
{
gamepadState.Buttons &= ~button;
}
public void Inject()
{
if (isConnected)
{
injector.InjectGamepadInput(gamepadState);
}
}
~GamepadInjector()
{
DisconnectGamepad();
}
}
}
Make an object of this class and call the functions as described. The above is part of a WinUI3 app.
The same app rewritten in C++ using Cpp/WinRT (with Qt6 for GUI) has the same problems.
And the same happened in Rust with the windows-rs crate. See comment.
This clearly points towards a problem in the library.
Expected behavior
The InputInjector.InitializeGamepadInjection() docs say:
Calling this method is analogous to connecting a physical gamepad, which also triggers a GamepadAdded event.
A physical gamepad is assigned a persistent unique ID (see NonRoamableId) that does not change when the device is connected and disconnected. Similarly, a virtual gamepad created with InitializeGamepadInjection is also assigned a unique ID that persists across calls to UninitializeGamepadInjection and InitializeGamepadInjection for the same InputInjector instance.
A virtual reconnect should behave adequately then.
Creating and initializing multiple InputInjector instances should work without crashing. It is equivalent to connecting multiple devices in reality.
Screenshots
No response
NuGet package version
None
Windows version
Windows 11 (22H2): Build 22621
Additional context
No response
You may use this website (not mine) to test the Gamepad Input.
It works. (At least till the apps crash)
The debugger (gdb) tells me the problem lies in
SyntheticController_UnregisterReportCallback of XboxgipSynthetic in xboxgipsynthetic.dll
Full stack trace:
xboxgipsynthetic.dll!XboxgipSynthetic!SyntheticController_UnregisterReportCallback (Unknown Source:0)
xboxgipsynthetic.dll!XboxgipSynthetic!SyntheticController_UnregisterReportCallback (Unknown Source:0)
xboxgipsynthetic.dll!XboxgipSynthetic!SyntheticController_UnregisterReportCallback (Unknown Source:0)
xboxgipsynthetic.dll!XboxgipSynthetic!SyntheticController_UnregisterReportCallback (Unknown Source:0)
kernel32.dll!KERNEL32!BaseThreadInitThunk (Unknown Source:0)
ntdll.dll!ntdll!RtlUserThreadStart (Unknown Source:0)
[Unknown/Just-In-Time compiled code] (Unknown Source:0)
The program segfaults soon after.
Do let me know if this helps or if this is a false positive.
Note: This is C++, not C#. The code is almost a direct translation of the reproducible example above.
XboxgipSynthetic.dll - Is the source-code for this library available anywhere?
I would like to fix it if possible.
@michael-hawker @bpulliam
Help this guy out please :) Would love to have his app working! It's a great open source alternative for some pretty shitty commercial software.