As of UE 5.4, the Common UI button (UCommonButtonBase
) still doesn’t support direct focus settings. This is because UCommonButtonBase
is derived from UUserWidget
, which supports focusing, but doesn’t direct the focus to the underlying button itself automatically. However, you can still set the focus on the button by performing a “deep” focus on the Slate button. Here’s how you can achieve this:
/**
* Sets the focus on the button
* This function performs the "deep" focus on the Common UI button, which means that it will set the focus on the button itself
* This is useful since UCommonButtonBase is derived from UUserWidget, which doesn't support focus when setting it directly
*/
UFUNCTION(BlueprintCallable, Category = "mod.io|UI|Button", DisplayName = "Set Button Focus (Common UI)")
void SetCommonUIButtonFocus()
{
#if UE_VERSION_OLDER_THAN(5, 3, 0)
if (bIsFocusable)
#else
if (IsFocusable())
#endif
{
if (TSharedPtr<SButton> SlateButton = GetSlateButton())
{
if (SlateButton->SupportsKeyboardFocus())
{
FSlateApplication::Get().SetKeyboardFocus(SlateButton, EFocusCause::Mouse);
UE_LOG(LogTemp, Log, TEXT("Set focus on button '%s' (extended way)"), *GetName());
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Trying to set focus on button '%s' but the button does not support keyboard focus"), *GetName());
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Trying to set focus on button '%s' but the slate button could not be found"), *GetName());
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Trying to set focus on button '%s' but the button is not focusable"), *GetName());
}
}
/**
* Gets the Slate button widget
* The button is highly encapsulated and this function tries to scan the widget tree to find the button
* @return The Slate button widget if found, nullptr otherwise
*/
TSharedPtr<SButton> GetSlateButton() const
{
if (WidgetTree && WidgetTree->RootWidget)
{
if (UButton* InternalButton = Cast<UButton>(WidgetTree->RootWidget))
{
// UCommonButtonInternalBase::RebuildWidget() creates a SBox wrapper for the button
if (TSharedPtr<SBox> BoxButtonWrapper = StaticCastSharedPtr<SBox>(TSharedPtr<SWidget>(InternalButton->GetCachedWidget())))
{
if (BoxButtonWrapper->GetChildren() && BoxButtonWrapper->GetChildren()->Num() > 0)
{
if (TSharedPtr<SButton> InternalButtonSlate = StaticCastSharedPtr<SButton>(TSharedPtr<SWidget>(BoxButtonWrapper->GetChildren()->GetChildAt(0))))
{
return InternalButtonSlate;
}
}
}
// UButton::RebuildWidget() returns the button directly
else if (TSharedPtr<SButton> InternalButtonSlate = StaticCastSharedPtr<SButton>(InternalButton->GetCachedWidget()))
{
return InternalButtonSlate;
}
else
{
UE_LOG(LogTemp, Error, TEXT("Could not find the Slate button widget for button '%s'"), *GetName());
}
}
}
return nullptr;
}