--- Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp.orig	2026-05-08 14:11:02.262757499 -0400
+++ Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp	2026-05-05 15:36:35.232152395 -0400
@@ -149,7 +149,7 @@
 		FString SolutionDir = GetSolutionPath();
 		TArray<FString> Args;
 		Args.Add(MakePath(SolutionDir));
-		Args.Add(TEXT("-g ") + MakePath(FullPath) + FString::Printf(TEXT(":%d:%d"), LineNumber, ColumnNumber));
+		Args.Add(TEXT("-g ") + MakePath(FullPath + FString::Printf(TEXT(":%d:%d"), LineNumber, ColumnNumber)));
 		return Launch(Args);
 	}
 
--- Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp.orig	2026-05-08 14:11:02.370759731 -0400
+++ Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp	2026-05-05 15:36:35.232353795 -0400
@@ -557,7 +557,7 @@
 	ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
 	ISourceCodeAccessor& SourceCodeAccessor = SourceCodeAccessModule.GetAccessor();
 
-#if PLATFORM_WINDOWS
+#if PLATFORM_WINDOWS || PLATFORM_LINUX
 	FString SourceFileName;
 	uint32 SourceLineNumber = 1;
 	uint32 SourceColumnNumber = 0;
@@ -716,8 +716,8 @@
 	}
     
     UE_LOG(LogSelectionDetails, Warning, TEXT("NavigateToFunctionSource: Unable to look up symbol: %s in module:%s"), *FunctionSymbolName, *FunctionModuleName);
-    
-#endif	// PLATFORM_WINDOWS
+
+#endif	// PLATFORM_WINDOWS || PLATFORM_LINUX
 }
 
 
--- Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp.orig	2026-05-08 14:11:02.477761942 -0400
+++ Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp	2026-05-05 15:36:35.232635087 -0400
@@ -317,6 +317,9 @@
 		// Furthermore SDL hides the mouse which we prevent by setting SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE
 		SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // When relative mouse mode is active, don't hide cursor.
 
+		// Unreal does its own dynamic capturing, we don't need SDL to do it.
+		SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
+
 		// If we're rendering offscreen, use the "dummy" SDL video driver
 		if (FParse::Param(FCommandLine::Get(), TEXT("RenderOffScreen")) && !getenv("SDL_VIDEODRIVER"))
 		{
--- Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp.orig	2026-05-08 14:11:02.584764153 -0400
+++ Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp	2026-05-05 15:36:35.232750204 -0400
@@ -15,6 +15,7 @@
 #include "HAL/ExceptionHandling.h"
 #include "HAL/PlatformProcess.h"
 #include "HAL/PlatformTime.h"
+#include "Modules/ModuleManager.h"
 #include "AutoRTFM.h"
 
 #include <link.h>
@@ -1063,3 +1064,69 @@
 	}
 	ReportLock.Unlock();
 }
+
+bool FUnixPlatformStackWalk::GetFunctionDefinitionLocation(const FString& FunctionSymbolName, const FString& FunctionModuleName, FString& OutPathname, uint32& OutLineNumber, uint32& OutColumnNumber)
+{
+	// Find the .so path for this module.
+	FString ModulePath;
+	TArray<FModuleStatus> AllModules;
+	FModuleManager::Get().QueryModules(AllModules);
+	for (const FModuleStatus& Status : AllModules)
+	{
+		if (FPaths::GetBaseFilename(Status.FilePath) == FunctionModuleName)
+		{
+			ModulePath = Status.FilePath;
+			break;
+		}
+	}
+	if (ModulePath.IsEmpty())
+	{
+		return false;
+	}
+
+	// Debug symbols are in a separate .debug file alongside the .so.
+	FString DebugPath = FPaths::ChangeExtension(ModulePath, TEXT("debug"));
+	if (!FPaths::FileExists(DebugPath))
+	{
+		return false;
+	}
+
+	// Use lldb to look up the source file and line number.
+	// Run: lldb -b -o "image lookup -v -n ClassName::FuncName" <debug_file>
+	FString LldbParams = FString::Printf(TEXT("-b -o \"image lookup -v -n %s\" \"%s\""), *FunctionSymbolName, *DebugPath);
+	int32 ReturnCode = 0;
+	FString AllOutput;
+	FString Errors;
+	FPlatformProcess::ExecProcess(TEXT("/usr/bin/lldb"), *LldbParams, &ReturnCode, &AllOutput, &Errors);
+	if (ReturnCode != 0)
+	{
+		return false;
+	}
+
+	// Parse the LineEntry from lldb verbose output.
+	// Format: "LineEntry: [0x...-0x...): /path/to/file.cpp:132"
+	TArray<FString> Lines;
+	AllOutput.ParseIntoArrayLines(Lines);
+	for (const FString& Line : Lines)
+	{
+		FString Trimmed = Line.TrimStartAndEnd();
+		if (!Trimmed.StartsWith(TEXT("LineEntry:")))
+			continue;
+
+		int32 ParenIndex = Trimmed.Find(TEXT("): "));
+		if (ParenIndex == INDEX_NONE)
+			continue;
+		FString FileAndLine = Trimmed.Mid(ParenIndex + 3);
+
+		int32 ColonIndex;
+		if (!FileAndLine.FindLastChar(TCHAR(':'), ColonIndex))
+			continue;
+
+		OutPathname = FileAndLine.Left(ColonIndex);
+		OutLineNumber = FCString::Atoi(*FileAndLine.Mid(ColonIndex + 1));
+		OutColumnNumber = 0;
+		return true;
+	}
+
+	return false;
+}
--- Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h.orig	2026-05-08 14:11:02.692766385 -0400
+++ Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h	2026-05-05 15:36:35.232861435 -0400
@@ -24,6 +24,8 @@
 	static CORE_API void ThreadStackWalkAndDump(ANSICHAR* HumanReadableString, SIZE_T HumanReadableStringSize, int32 IgnoreCount, uint32 ThreadId);
 	static CORE_API int32 GetProcessModuleCount();
 	static CORE_API int32 GetProcessModuleSignatures(FStackWalkModuleInfo *ModuleSignatures, const int32 ModuleSignaturesSize);
+
+	static CORE_API bool GetFunctionDefinitionLocation(const FString& FunctionSymbolName, const FString& FunctionModuleName, FString& OutPathname, uint32& OutLineNumber, uint32& OutColumnNumber);
 };
 
 typedef FUnixPlatformStackWalk FPlatformStackWalk;
--- Engine/Source/Runtime/ApplicationCore/Public/Linux/LinuxApplication.h.orig	2026-05-08 14:11:02.802768658 -0400
+++ Engine/Source/Runtime/ApplicationCore/Public/Linux/LinuxApplication.h	2026-05-08 14:09:14.778161399 -0400
@@ -265,6 +265,12 @@
 		/** The input device Id of the controller that can be used to find the matching ULocalPlayer */
 		FInputDeviceId DeviceId;
 
+		/** SDL gamepad type string (e.g. "ps4", "xboxone"), used as HardwareDeviceIdentifier in FInputDeviceScope */
+		FName GamepadType;
+
+		/** SDL gamepad name (human-readable device name), used as InputDeviceName in FInputDeviceScope */
+		FName GamepadName;
+
 		/** Store axis values from events here to be handled once per frame. */
 		TMap<FGamepadKeyNames::Type, float> AxisEvents;
 
--- Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxApplication.cpp.orig	2026-05-08 14:11:02.910770890 -0400
+++ Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxApplication.cpp	2026-05-08 14:09:14.778345206 -0400
@@ -13,6 +13,13 @@
 #include "IHapticDevice.h"
 #include "GenericPlatform/GenericPlatformInputDeviceMapper.h"
 
+namespace UE::LinuxInput
+{
+	static const FName InputClassName = TEXT("LinuxApplication");
+	static const FString KBMInputHardwareName = TEXT("KBM");
+	static const FString TouchInputHardwareName = TEXT("MobileTouch");
+}
+
 //
 // GameController thresholds
 //
@@ -320,6 +327,7 @@
 	{
 	case SDL_EVENT_KEY_DOWN:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::KBMInputHardwareName);
 			const SDL_KeyboardEvent &KeyEvent = Event.key;
 			SDL_Keycode KeySym = KeyEvent.key;
 			const uint32 CharCode = CharCodeFromSDLKeySym(KeySym);
@@ -342,6 +350,7 @@
 		break;
 	case SDL_EVENT_KEY_UP:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::KBMInputHardwareName);
 			const SDL_KeyboardEvent &KeyEvent = Event.key;
 			const SDL_Keycode KeySym = KeyEvent.key;
 			const uint32 CharCode = CharCodeFromSDLKeySym(KeySym);
@@ -352,6 +361,7 @@
 		break;
 	case SDL_EVENT_TEXT_INPUT:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::KBMInputHardwareName);
 			// Slate now gets all its text from here, I hope.
 			const bool bIsRepeated = false;  //Event.key.repeat != 0;
 			const FString TextStr(UTF8_TO_TCHAR(Event.text.text));
@@ -363,6 +373,7 @@
 		break;
 	case SDL_EVENT_MOUSE_MOTION:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::KBMInputHardwareName);
 			SDL_MouseMotionEvent motionEvent = Event.motion;
 			FLinuxCursor *LinuxCursor = (FLinuxCursor*)Cursor.Get();
 			LinuxCursor->InvalidateCaches();
@@ -406,6 +417,7 @@
 	case SDL_EVENT_MOUSE_BUTTON_DOWN:
 	case SDL_EVENT_MOUSE_BUTTON_UP:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::KBMInputHardwareName);
 			SDL_MouseButtonEvent buttonEvent = Event.button;
 
 			EMouseButtons::Type button;
@@ -484,6 +496,7 @@
 		break;
 	case SDL_EVENT_MOUSE_WHEEL:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::KBMInputHardwareName);
 			SDL_MouseWheelEvent *WheelEvent = &Event.wheel;
 			float Amount = (float)WheelEvent->y * fMouseWheelScrollAccel;
 
@@ -515,6 +528,7 @@
 
 			SDLControllerState &ControllerState = ControllerStates[caxisEvent.which];
 			FPlatformUserId UserId = IPlatformInputDeviceMapper::Get().GetUserForInputDevice(ControllerState.DeviceId);
+			FInputDeviceScope InputScope(nullptr, ControllerState.GamepadName, ControllerState.DeviceId.GetId(), ControllerState.GamepadType.ToString());
 
 			switch (caxisEvent.axis)
 			{
@@ -740,15 +754,17 @@
 
 			if (Button != FGamepadKeyNames::Invalid)
 			{
-				FPlatformUserId UserId = IPlatformInputDeviceMapper::Get().GetUserForInputDevice(ControllerStates[cbuttonEvent.which].DeviceId);
+				SDLControllerState& ButtonControllerState = ControllerStates[cbuttonEvent.which];
+				FPlatformUserId UserId = IPlatformInputDeviceMapper::Get().GetUserForInputDevice(ButtonControllerState.DeviceId);
+				FInputDeviceScope InputScope(nullptr, ButtonControllerState.GamepadName, ButtonControllerState.DeviceId.GetId(), ButtonControllerState.GamepadType.ToString());
 
 				if(cbuttonEvent.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN)
 				{
-					MessageHandler->OnControllerButtonPressed(Button, UserId, ControllerStates[cbuttonEvent.which].DeviceId, false);
+					MessageHandler->OnControllerButtonPressed(Button, UserId, ButtonControllerState.DeviceId, false);
 				}
 				else
 				{
-					MessageHandler->OnControllerButtonReleased(Button, UserId, ControllerStates[cbuttonEvent.which].DeviceId, false);
+					MessageHandler->OnControllerButtonReleased(Button, UserId, ButtonControllerState.DeviceId, false);
 				}
 			}
 		}
@@ -1018,6 +1034,7 @@
 
 	case SDL_EVENT_FINGER_DOWN:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::TouchInputHardwareName);
 			UE_LOG(LogLinuxWindow, Verbose, TEXT("Finger %llu is down at (%f, %f)"), Event.tfinger.fingerID, Event.tfinger.x, Event.tfinger.y);
 
 			// touch events can have no window associated with them, in that case ignore (with a warning)
@@ -1053,6 +1070,7 @@
 		break;
 	case SDL_EVENT_FINGER_UP:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::TouchInputHardwareName);
 			UE_LOG(LogLinuxWindow, Verbose, TEXT("Finger %llu is up at (%f, %f)"), Event.tfinger.fingerID, Event.tfinger.x, Event.tfinger.y);
 
 			// touch events can have no window associated with them, in that case ignore (with a warning)
@@ -1087,6 +1105,7 @@
 		break;
 	case SDL_EVENT_FINGER_MOTION:
 		{
+			FInputDeviceScope InputScope(nullptr, UE::LinuxInput::InputClassName, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice().GetId(), UE::LinuxInput::TouchInputHardwareName);
 			// touch events can have no window associated with them, in that case ignore (with a warning)
 			if (LIKELY(!bWindowlessEvent))
 			{
@@ -1196,6 +1215,7 @@
 	IPlatformInputDeviceMapper& Mapper = IPlatformInputDeviceMapper::Get();
 	for(auto ControllerIt = ControllerStates.CreateIterator(); ControllerIt; ++ControllerIt)
 	{
+		FInputDeviceScope InputScope(nullptr, ControllerIt.Value().GamepadName, ControllerIt.Value().DeviceId.GetId(), ControllerIt.Value().GamepadType.ToString());
 		for(auto Event = ControllerIt.Value().AxisEvents.CreateConstIterator(); Event; ++Event)
 		{
 			FPlatformUserId UserId = Mapper.GetUserForInputDevice(ControllerIt.Value().DeviceId);
@@ -2075,6 +2095,9 @@
 	UE_LOG(LogLinux, Verbose, TEXT("Adding controller %i '%s'"), FirstUnusedIndex, UTF8_TO_TCHAR(SDL_GetGamepadName(Controller)));
 	auto& ControllerState = ControllerStates.Add(Id);
 	ControllerState.Controller = Controller;
+	ControllerState.GamepadName = FName(UTF8_TO_TCHAR(SDL_GetGamepadName(Controller)));
+	const char* GamepadTypeStr = SDL_GetGamepadStringForType(SDL_GetGamepadType(Controller));
+	ControllerState.GamepadType = FName(GamepadTypeStr ? UTF8_TO_TCHAR(GamepadTypeStr) : TEXT("unknown"));
 
 	FPlatformUserId UserId = FPlatformUserId::CreateFromInternalId(FirstUnusedIndex);
 	DeviceMapper.RemapControllerIdToPlatformUserAndDevice(FirstUnusedIndex, UserId, ControllerState.DeviceId);
