How can I change focus to Slate and back?

Hey everyone,

I’m building a menu in Slate, which toggles after you’ve hit a keyboard key (as the game itself is not mouse cursor based).

So when I hit this key, I unpossess the pawn to stop it from getting input, I ask my HUD class to make slate widgets visible, the finally set “Show Mouse Cursor” to true on the PlayerController.

When I do that, the Slate layer is not focus. I have to click on my window once, they I can drag scrollbars and such. Put another way, the first click to a button fails, the next one succeed.

After focus has been given to slate, and the menu is hidden, no mouse input goes to the Controller, so again I have to click once.

Change my problem description after digging around more. Looks like the same issue as here: How to change focus between Slate-Menu and Game? - UI - Unreal Engine Forums

No exact answer yet, but the ShooterGame sample has an in-game menu that seems to work fine. I’ll look into that.

I have search a lot, still did not find how they do, I have add a basic button to there menu to see the hover effect, I have comment a lot of stuff and its still work… I start to believe this may be a property set somewhere, did you find something?

I’ve been commenting out code too. Even if the menu is stripped of useful widgets, the line that makes the cursor appear is:
GEngine->GameViewport->AddViewportWidgetContent(…) in ShooterIngameMenu.cpp. You can comment this line out and then cursor is no longer there.

They don’t use the ShowCursor property of the PlayerController at all for this. Epic team, any hints on this?

Hi Guys !

Just SOLVE this problem =), thanks to the ShooterGame !

So basically this is what you have to do :

Add this in your widget :

/** says that we can support keyboard focus */
virtual bool SupportsKeyboardFocus() const OVERRIDE{ return true; }

FReply SBLCUIWidget::OnKeyboardFocusReceived(const FGeometry& MyGeometry, const FKeyboardFocusEvent& InKeyboardFocusEvent)
{
	return FReply::Handled().ReleaseMouseCapture().CaptureJoystick(SharedThis( this ), true);
}

Then when you want to open the menu simply do that :

GEngine->GameViewport->AddViewportWidgetContent(SNew(SWeakWidget).PossiblyNullContent(MyUIWidget.ToSharedRef()));
FSlateApplication::Get().SetKeyboardFocus(MyUIWidget.ToSharedRef());

And to close it :

GEngine->GameViewport->RemoveAllViewportWidgets();
FSlateApplication::Get().SetFocusToGameViewport();

Hope this will help you because its been 3 days I am on this !!

Bests :wink:

Hey, I found the same solution :slight_smile:

SupportsKeyboardFocus() needs to return true if SetKeyboardFocus() is to work, because that method checks the predicate.

Then the mouse needs to be released otherwise will hide itself away as soon as you interact with Slate.

CaptureJoystick(SharedThis( this ), true) is not needed.

Alternatively, when calling SetKeyboardFocus(), also call ReleaseMouseCapture() on the SlateApplication object. This way there’s no need to override OnKeyboardFocusReceived.

Thanks Antares for all the help! I wish this behavior was documented, or that at least SetMouseFocus() would exist, as Keyboard focus and mouse cursor are not obviously linked together.

One addition: had to also override this to prevent the cursor from disappearing on left-clicks:

FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) OVERRIDE
{
	    //Set the keyboard focus 
	    return FReply::Handled().SetKeyboardFocus(SharedThis(this), EKeyboardFocusCause::SetDirectly);
}

Realy nice, I was searching for that, and thank you for the help ! I prefer to keep override of OnKeyboardFocusReceived because they do it in ShooterGame and it may be more clear (look for description of ReleaseMouseCapture they talk about doing this in reply)

Hope all of this will help other people and yes Keyboard focus mean keyboard to me and not mouse !

Hey,

For anyone arriving here after hours of failures and tears^^, OnKeyboardFocusReceived is deprecated since 4.6.

Here is some working code (currently 4.10):

.h
virtual bool SupportsKeyboardFocus() const override { return true; }
virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent) override;

--------------------------------------------------------------------------------------------
.cpp
FReply MyWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent)
{
	return FReply::Handled().ReleaseMouseCapture();
}

Cheers

Cedric