UE5.6 I discovered a malicious bug regarding the UI input method change (about OnInputMethodChanged event)

About you used OnInputMethodChanged to real-time change UI input change. You will find in this 5.6 upgrade that when you use the gamepad to input, the input mode will switch wildly between the mouse and the gamepad, and then your controller will completely fail.

This problem is mainly caused by the following code:

SlateApplication.cpp

bool FSlateApplication::OnMouseMove()
{
	if (!PlatformApplication->Cursor.IsValid())
    {
    	return false;
    }

    // If the left button is pressed we fake 
	if (IsFakingTouchEvents() && (GetPressedMouseButtons().Num() == 0 || GetPressedMouseButtons().Contains(EKeys::LeftMouseButton)))
	{
		// convert to touch event if we are faking it
		if (bIsFakingTouched)
		{
			return OnTouchMoved(PlatformApplication->Cursor->GetPosition(), 1.0f, 0, FSlateApplicationBase::SlateAppPrimaryPlatformUser, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice());
		}

		// Throw out the mouse move event if we're faking touch events but the mouse button isn't down.
		return false;
	}

	bool Result = true;
	const FVector2f CurrentCursorPosition = UE::Slate::CastToVector2f(PlatformApplication->Cursor->GetPosition());
	if (LastPlatformCursorPosition != CurrentCursorPosition)
	{
		// Force the cursor user index to use the platform cursor since we've been notified that the platform 
		// cursor position has changed. This is done intentionally after getting the positions in order to avoid
		// false positives.

		// NOTE: When we swap out the real OS cursor for the faux slate cursor ie. UsePlatformCursorForCursorUser(false)
		// we reset this event count to 0.  This occurs typically when a gamepad is being used and you don't want to manipulate the real
		// OS cursor, instead move around a fake cursor so that you can still do development stuff outside the game window.  Anyway,
		// when this occurs, in the future the OS will send you a long delayed mouse movement.  I'm not exactly sure what's triggering it,
		// it's not a movement from the application, I think it's something more subtle, like swapping true cursor visibility for using
		// a None cursor, it could also be some combination.
		// 
		// In any event, we track the number of events, and if we get more than 3, then we start trying to swap back to the OS cursor.
		// the 3 should give us any buffer needed for either a last frame mouse movement, or a weird condition like noted above.
		PlatformMouseMovementEvents++;

		if (PlatformMouseMovementEvents > 3)
		{
			UsePlatformCursorForCursorUser(true);
		}

		LastMouseMoveTime = GetCurrentTime();

		FPointerEvent MouseEvent(
			GetUserIndexForMouse(),
			CursorPointerIndex,
			CurrentCursorPosition,
			LastPlatformCursorPosition,
			PressedMouseButtons,
			EKeys::Invalid,
			0,
			PlatformApplication->GetModifierKeys()
			);

		Result = ProcessMouseMoveEvent( MouseEvent );
		LastPlatformCursorPosition = CurrentCursorPosition;
	}

	return Result;
}

The logic written above is so foolish. This code is so foolish that I am too lazy to look for its logical bugs. I choose to revert it back to version 5.5.3.

To prevent anyone from not downloading version 5.5.3, I have attached the following correct code:

bool FSlateApplication::OnMouseMove()
{
	// If the left button is pressed we fake 
	if (IsFakingTouchEvents() && (GetPressedMouseButtons().Num() == 0 || GetPressedMouseButtons().Contains(EKeys::LeftMouseButton)))
	{
		// convert to touch event if we are faking it
		if (bIsFakingTouched)
		{
			return OnTouchMoved(PlatformApplication->Cursor->GetPosition(), 1.0f, 0, FSlateApplicationBase::SlateAppPrimaryPlatformUser, IPlatformInputDeviceMapper::Get().GetDefaultInputDevice());
		}

		// Throw out the mouse move event if we're faking touch events but the mouse button isn't down.
		return false;
	}

	bool Result = true;
	const FVector2f CurrentCursorPosition = GetCursorPos();
	const FVector2f LastCursorPosition = GetLastCursorPos();

	// Force the cursor user index to use the platform cursor since we've been notified that the platform 
	// cursor position has changed. This is done intentionally after getting the positions in order to avoid
	// false positives.

	// NOTE: When we swap out the real OS cursor for the faux slate cursor ie. UsePlatformCursorForCursorUser(false)
	// we reset this event count to 0.  This occurs typically when a gamepad is being used and you don't want to manipulate the real
	// OS cursor, instead move around a fake cursor so that you can still do development stuff outside the game window.  Anyway,
	// when this occurs, in the future the OS will send you a long delayed mouse movement.  I'm not exactly sure what's triggering it,
	// it's not a movement from the application, I think it's something more subtle, like swapping true cursor visibility for using
	// a None cursor, it could also be some combination.
	// 
	// In any event, we track the number of events, and if we get more than 3, then we start trying to swap back to the OS cursor.
	// the 3 should give us any buffer needed for either a last frame mouse movement, or a weird condition like noted above.
	PlatformMouseMovementEvents++;

	if (PlatformMouseMovementEvents > 3)
	{
		UsePlatformCursorForCursorUser(true);
	}

	if (LastCursorPosition != CurrentCursorPosition)
	{
		LastMouseMoveTime = GetCurrentTime();

		FPointerEvent MouseEvent(
			GetUserIndexForMouse(),
			CursorPointerIndex,
			CurrentCursorPosition,
			LastCursorPosition,
			PressedMouseButtons,
			EKeys::Invalid,
			0,
			PlatformApplication->GetModifierKeys()
		);

		Result = ProcessMouseMoveEvent(MouseEvent);
	}

	return Result;
}

I am very skeptical about how the official wrote this code. it is obvious that it will cause serious input mode change problems.I spent two days troubleshooting the code I wrote. Finally, I discovered this error issue in the official update. I’m a little angry. I hope Unreal Engine can update more rigorously next time.