Upgrade to unreal 5.7.4
This commit is contained in:
117
Docs/Getting-Gamepad-USB-Device-Name.md
Normal file
117
Docs/Getting-Gamepad-USB-Device-Name.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Getting the Gamepad USB Device Name
|
||||||
|
|
||||||
|
Unreal exposes `UInputDeviceSubsystem::GetMostRecentlyUsedHardwareDevice()`, which
|
||||||
|
returns an `FHardwareDeviceIdentifier`. In stock Unreal this is nearly useless: on
|
||||||
|
Windows it toggles between `"WindowsApplication"` (KBM) and `"XInputController"`
|
||||||
|
(any XInput pad); on Linux it returns nothing meaningful at all. It cannot
|
||||||
|
distinguish a DualSense from an Xbox pad.
|
||||||
|
|
||||||
|
The USB-reported device name (e.g. `"Sony Interactive Entertainment Wireless
|
||||||
|
Controller"`) is what we want to surface. This document describes the changes
|
||||||
|
required on each platform to put that name into `FHardwareDeviceIdentifier`.
|
||||||
|
|
||||||
|
## How `FHardwareDeviceIdentifier` Gets Populated
|
||||||
|
|
||||||
|
Input drivers wrap their `MessageHandler->OnControllerButton/Analog` calls in an
|
||||||
|
`FInputDeviceScope` (stack-allocated, thread-local stack of pointers). The scope
|
||||||
|
carries `InputDeviceName` (driver class) and `HardwareDeviceIdentifier` (physical
|
||||||
|
device string). When the input event reaches `UInputDeviceSubsystem`, those two
|
||||||
|
fields are copied into the `FHardwareDeviceIdentifier` record for that user.
|
||||||
|
|
||||||
|
So the fix on each platform is the same shape: **at device-connect time, cache
|
||||||
|
the USB device-name string; in the per-event scope, pass it as the
|
||||||
|
`HardwareDeviceIdentifier`.**
|
||||||
|
|
||||||
|
## Windows: Patch the GameInput Plugin
|
||||||
|
|
||||||
|
Location: `Engine/Plugins/Runtime/GameInput/Source/GameInputBase/`.
|
||||||
|
|
||||||
|
The Microsoft GameInput SDK already exposes the data we need on every device via
|
||||||
|
`GameInputDeviceInfo::displayName` (a `wchar_t*`). The plugin reads it for log
|
||||||
|
lines (`GameInputUtils.cpp:18-23`) but does not propagate it.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
|
||||||
|
1. **Cache at connect.** Add `FString CachedDisplayName` to
|
||||||
|
`FGameInputDeviceContainer`. In its constructor / device-info init path
|
||||||
|
(`GameInputDeviceContainer.cpp:44`, where `Info` is in scope), set:
|
||||||
|
```cpp
|
||||||
|
CachedDisplayName = FString(Info->displayName);
|
||||||
|
```
|
||||||
|
`TCHAR == wchar_t` on Windows, so the conversion is direct. Lifetime matches
|
||||||
|
the container — cleared automatically on disconnect.
|
||||||
|
|
||||||
|
2. **Make the container reachable from `FGameInputEventParams`.** The processor
|
||||||
|
already gets a `Device` pointer; add a `Container` pointer so
|
||||||
|
`GetHardwareDeviceIdentifierName` can read the cached string.
|
||||||
|
|
||||||
|
3. **Return it from `GetHardwareDeviceIdentifierName`**
|
||||||
|
(`GameInputDeviceProcessor.cpp:61`). After the existing
|
||||||
|
`bOverrideHardwareDeviceIdString` block, before the family-bucket switch:
|
||||||
|
```cpp
|
||||||
|
if (Params.Container && !Params.Container->CachedDisplayName.IsEmpty())
|
||||||
|
{
|
||||||
|
return Params.Container->CachedDisplayName;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The override path still wins (explicit dev intent); the family-bucket
|
||||||
|
fallback handles devices with empty `displayName`.
|
||||||
|
|
||||||
|
Total: ~10 lines plus the field. All inside `#if GAME_INPUT_SUPPORT`.
|
||||||
|
|
||||||
|
The user must enable the GameInput plugin and disable the default `XInputDevice`
|
||||||
|
plugin (otherwise both drivers will dispatch events for the same pad).
|
||||||
|
|
||||||
|
## Linux: Patch `LinuxApplication.cpp`
|
||||||
|
|
||||||
|
Location: `Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxApplication.cpp`.
|
||||||
|
|
||||||
|
SDL already provides the device name via `SDL_GameControllerName()`. The Linux
|
||||||
|
path calls it once for a log line in `AddGameController` (line 2175) and then
|
||||||
|
discards it. The Linux path also does not push an `FInputDeviceScope` at all
|
||||||
|
around its controller events — that's the second half of why
|
||||||
|
`GetMostRecentlyUsedHardwareDevice` is useless on Linux.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
|
||||||
|
1. **Store the name.** Add `FString DeviceName` to `SDLControllerState`. In
|
||||||
|
`AddGameController` (~line 2175), assign:
|
||||||
|
```cpp
|
||||||
|
ControllerState.DeviceName = UTF8_TO_TCHAR(SDL_GameControllerName(Controller));
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Wrap controller-event dispatch in a scope.** Around the
|
||||||
|
`MessageHandler->OnControllerButton*/OnControllerAnalog` block (starting
|
||||||
|
~line 518):
|
||||||
|
```cpp
|
||||||
|
FInputDeviceScope Scope(
|
||||||
|
nullptr,
|
||||||
|
FName("LinuxApplication"),
|
||||||
|
ControllerState.DeviceId.GetId(),
|
||||||
|
ControllerState.DeviceName);
|
||||||
|
// ... existing dispatch ...
|
||||||
|
```
|
||||||
|
Use `"LinuxApplication"` for `InputDeviceName` to mirror the Windows
|
||||||
|
convention.
|
||||||
|
|
||||||
|
Total: ~12 lines. No third-party dependencies, no engine plugins, no per-device
|
||||||
|
config tables.
|
||||||
|
|
||||||
|
## What This Does Not Solve
|
||||||
|
|
||||||
|
- **Stock XInput on Windows.** If we keep the default `XInputDevice` plugin,
|
||||||
|
events continue to come through `XInputInterface.cpp` with a fixed
|
||||||
|
`"XInputController"` identifier. XInput itself does not expose VID/PID or
|
||||||
|
device strings. Recovering the name there requires correlating the XInput
|
||||||
|
slot with a Raw Input HID via the `IG_xx` token in the Raw Input device path,
|
||||||
|
then calling `HidD_GetProductString` — a separate, more involved patch.
|
||||||
|
GameInput is the cleaner answer on Windows.
|
||||||
|
|
||||||
|
- **XInput-wrapped pads under GameInput.** A DualSense routed through Steam
|
||||||
|
Input or DS4Windows will surface as the wrapper's display name (e.g. ViGEm),
|
||||||
|
not as the underlying physical device. This is a property of the wrapper, not
|
||||||
|
fixable from our side.
|
||||||
|
|
||||||
|
- **`displayName` is not a stable identifier.** It is a human-readable name
|
||||||
|
whose exact text varies by OS version, driver, and USB descriptor. Use it for
|
||||||
|
prompt-set selection and logging. Do not use it as a save-game key.
|
||||||
@@ -43,35 +43,6 @@
|
|||||||
// If we're rendering offscreen, use the "dummy" SDL video driver
|
// If we're rendering offscreen, use the "dummy" SDL video driver
|
||||||
if (FParse::Param(FCommandLine::Get(), TEXT("RenderOffScreen")) && !getenv("SDL_VIDEODRIVER"))
|
if (FParse::Param(FCommandLine::Get(), TEXT("RenderOffScreen")) && !getenv("SDL_VIDEODRIVER"))
|
||||||
{
|
{
|
||||||
--- Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxWindow.cpp.orig 2026-04-12 22:58:34.538334467 -0400
|
|
||||||
+++ Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxWindow.cpp 2026-04-12 22:48:15.848291098 -0400
|
|
||||||
@@ -235,7 +235,26 @@
|
|
||||||
|
|
||||||
// The SDL window doesn't need to be reshaped.
|
|
||||||
// the size of the window you input is the sizeof the client.
|
|
||||||
+
|
|
||||||
+ // Under XWayland, non-override-redirect popup windows don't receive input
|
|
||||||
+ // events from the compositor. SDL already sets override_redirect for
|
|
||||||
+ // tooltips and popup menus, but other borderless child windows (like
|
|
||||||
+ // notification popups and dialogs) also need it. We temporarily enable
|
|
||||||
+ // the SDL hint to force override_redirect for these windows.
|
|
||||||
+ bool bForceOverrideRedirect = !Definition->HasOSWindowBorder
|
|
||||||
+ && InParent.IsValid()
|
|
||||||
+ && !(WindowStyle & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU));
|
|
||||||
+ if (bForceOverrideRedirect)
|
|
||||||
+ {
|
|
||||||
+ SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "1");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
HWnd = SDL_CreateWindow( TCHAR_TO_ANSI( *Definition->Title ), X, Y, ClientWidth, ClientHeight, WindowStyle );
|
|
||||||
+
|
|
||||||
+ if (bForceOverrideRedirect)
|
|
||||||
+ {
|
|
||||||
+ SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "0");
|
|
||||||
+ }
|
|
||||||
// produce a helpful message for common driver errors
|
|
||||||
if (HWnd == nullptr)
|
|
||||||
{
|
|
||||||
--- Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp.orig 2026-04-12 22:58:34.349328955 -0400
|
--- Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp.orig 2026-04-12 22:58:34.349328955 -0400
|
||||||
+++ Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp 2026-04-12 23:05:56.395187515 -0400
|
+++ Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp 2026-04-12 23:05:56.395187515 -0400
|
||||||
@@ -15,6 +15,7 @@
|
@@ -15,6 +15,7 @@
|
||||||
@@ -79,7 +50,7 @@
|
|||||||
#include "HAL/PlatformProcess.h"
|
#include "HAL/PlatformProcess.h"
|
||||||
#include "HAL/PlatformTime.h"
|
#include "HAL/PlatformTime.h"
|
||||||
+#include "Modules/ModuleManager.h"
|
+#include "Modules/ModuleManager.h"
|
||||||
#include "AutoRTFM/AutoRTFM.h"
|
#include "AutoRTFM.h"
|
||||||
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
@@ -1060,3 +1061,69 @@
|
@@ -1060,3 +1061,69 @@
|
||||||
|
|||||||
47
EnginePatches/Old-Patches.md
Normal file
47
EnginePatches/Old-Patches.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Old Patches
|
||||||
|
|
||||||
|
Patches that were once part of `EnginePatch` but are no longer needed.
|
||||||
|
Kept here for reference in case the underlying issue resurfaces.
|
||||||
|
|
||||||
|
## LinuxWindow.cpp — force override_redirect for borderless child windows
|
||||||
|
|
||||||
|
Removed when the engine was upgraded to UE 5.7, which uses SDL3. SDL3 has
|
||||||
|
better Wayland support, so this workaround is believed to be unnecessary.
|
||||||
|
The original purpose was to make Unreal play better with Wayland: under
|
||||||
|
XWayland, non-override-redirect popup windows don't receive input events
|
||||||
|
from the compositor. SDL already sets override_redirect for tooltips and
|
||||||
|
popup menus, but other borderless child windows (notification popups,
|
||||||
|
dialogs) also needed it, so we temporarily enabled
|
||||||
|
`SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT` around the `SDL_CreateWindow` call.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
--- Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxWindow.cpp.orig 2026-04-12 22:58:34.538334467 -0400
|
||||||
|
+++ Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxWindow.cpp 2026-04-12 22:48:15.848291098 -0400
|
||||||
|
@@ -235,7 +235,26 @@
|
||||||
|
|
||||||
|
// The SDL window doesn't need to be reshaped.
|
||||||
|
// the size of the window you input is the sizeof the client.
|
||||||
|
+
|
||||||
|
+ // Under XWayland, non-override-redirect popup windows don't receive input
|
||||||
|
+ // events from the compositor. SDL already sets override_redirect for
|
||||||
|
+ // tooltips and popup menus, but other borderless child windows (like
|
||||||
|
+ // notification popups and dialogs) also need it. We temporarily enable
|
||||||
|
+ // the SDL hint to force override_redirect for these windows.
|
||||||
|
+ bool bForceOverrideRedirect = !Definition->HasOSWindowBorder
|
||||||
|
+ && InParent.IsValid()
|
||||||
|
+ && !(WindowStyle & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU));
|
||||||
|
+ if (bForceOverrideRedirect)
|
||||||
|
+ {
|
||||||
|
+ SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "1");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
HWnd = SDL_CreateWindow( TCHAR_TO_ANSI( *Definition->Title ), X, Y, ClientWidth, ClientHeight, WindowStyle );
|
||||||
|
+
|
||||||
|
+ if (bForceOverrideRedirect)
|
||||||
|
+ {
|
||||||
|
+ SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "0");
|
||||||
|
+ }
|
||||||
|
// produce a helpful message for common driver errors
|
||||||
|
if (HWnd == nullptr)
|
||||||
|
{
|
||||||
|
```
|
||||||
BIN
UnrealEngine-5.5.4-release.zip
LFS
BIN
UnrealEngine-5.5.4-release.zip
LFS
Binary file not shown.
BIN
UnrealEngine-5.7.4-release.zip
LFS
Normal file
BIN
UnrealEngine-5.7.4-release.zip
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user