Community Tutorial: Common UI Plugin - Keyboard Navigation

2 years have passed, is this method still valid? Thanks

I made a button that based on CommonBoundActionButton, and put it into my menu which is a CommonActivatableWidget, but when I push it onto the stack, the hovered and unhovered events did not work for keyboard. What do I need to do? Thanks!

Did you ever figure out the TODO? Its still not working and my focus is all over the place because Epic games cant make a good system…

2 Likes

This workaround still works like a charm, but there is another issue, when you navigate to the last button and press down arrow key, it goes to the first button, but somehow it doesn’t respond to confirm

Also tagging @Patterson in this:

But… when i hover one with the mouse and tap a keyboard key… i have two hovered buttons…

I found a guide somewhere suggesting making changes to UGameViewportClient, ie. NOT possible to really solve without C++. What I did was create a custom viewport client class (now I guess it should inherit from the Common UI viewport client instead) :

UCLASS()
class GF_UI_API UGF_GameViewportClientBase : public UGameViewportClient
{
	GENERATED_BODY()

public:
	void ShowMouseCursor();
	void HideMouseCursor();
	virtual EMouseCursor::Type GetCursor(FViewport* InViewport, int32 X, int32 Y) override;

private:
	bool mShowMouseCursor = true;
};

And implementation:

void UGF_GameViewportClientBase::ShowMouseCursor()
{
	mShowMouseCursor = true;
	FSlateApplication::Get().OnCursorSet(); // SlateApplication calls ::GetCursor() on this class.
}

void UGF_GameViewportClientBase::HideMouseCursor()
{
	mShowMouseCursor = false;
	FSlateApplication::Get().OnCursorSet(); // SlateApplication calls ::GetCursor() on this class.
}

EMouseCursor::Type UGF_GameViewportClientBase::GetCursor(FViewport* InViewport, int32 X, int32 Y)
{
	// Since this function is called whenever the mouse is _moved_, that would be a good time to start
	// showing the cursor again if it was hidden. The check is needed because ::HideMouseCursor
	// calls on the SlateApplication which forces this function to be called exactly once. And that
	// hides the cursor, until the user starts moving the mouse.
	if (!mShowMouseCursor)
	{
		mShowMouseCursor = true;
		return EMouseCursor::None;
	}
	return Super::GetCursor(InViewport, X, Y);
}

It’s probably not perfect, but it works. Only problem is that even when the cursor is hidden it has still hit-testing enabled. So it can be invisible and hover over a button, which means that the user will see two “active” buttons when using keyboard keys.

I’m still looking for a good solution to that second half of my problem. Any hints are appreciated! :slight_smile:

Hi there, have found out the solution? Thanks!

It’s ridiculous that there is no way to apply hover styles when button is focused without jiggling with two Button Style Blueprints. There is just no way to do that in C++ because all styles and functions that apply them are just private.

2 Likes