[UE5.1.1, Bug report] FAnalogCursor::HandleKeyDownEvent assumes mouse button was used.

The FAnalogCursor simulates mouse behavior for devices such as a gamepad. Some keys are hardcoded here or platform specific, but eventually when it simulates a “click” event it passes on the left mouse button to FSlateApplication::ProcessMouseButtonDownEvent.

The problem with this is that any other input preprocessor now receives “HandleMouseButtonDownEvent”, incorrectly detecting a mouse device where we were using a gamepad for a click event. It doesn’t seem to break anything but if you just want to detect which input device is currently in use through an input preprocessor then this doesn’t make it easier.

bool FAnalogCursor::HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& InKeyEvent)
{
	if (IsRelevantInput(InKeyEvent))
	{
		FKey Key = InKeyEvent.GetKey();
		// Consume the sticks input so it doesn't effect other things
		if (Key == EKeys::Gamepad_LeftStick_Right ||
			Key == EKeys::Gamepad_LeftStick_Left ||
			Key == EKeys::Gamepad_LeftStick_Up ||
			Key == EKeys::Gamepad_LeftStick_Down)
		{
			return true;
		}

		// Bottom face button is a click
		if (Key == EKeys::Virtual_Accept)
		{
			if (!InKeyEvent.IsRepeat())
			{
				if (TSharedPtr<FSlateUser> SlateUser = SlateApp.GetUser(InKeyEvent))
				{
					const bool bIsPrimaryUser = FSlateApplication::CursorUserIndex == SlateUser->GetUserIndex();
					FPointerEvent MouseEvent(
						SlateUser->GetUserIndex(),
						FSlateApplication::CursorPointerIndex,
						SlateUser->GetCursorPosition(),
						SlateUser->GetPreviousCursorPosition(),
						bIsPrimaryUser ? SlateApp.GetPressedMouseButtons() : TSet<FKey>(),
						EKeys::LeftMouseButton,
						0,
						bIsPrimaryUser ? SlateApp.GetModifierKeys() : FModifierKeysState()
					);

					TSharedPtr<FGenericWindow> GenWindow;
					return SlateApp.ProcessMouseButtonDownEvent(GenWindow, MouseEvent);
				}
			}

			return true;
		}
	}

	return false;
}

Just tested what would happen if you override this method entirely and pass on a gamepad button (face bottom) used for slates “accept” navigation key into the MouseEvent. Instead of clicking a widget it focuses a widget, with “mouse” as focus reason. What to think of this…

1 Like