Thanks for the hint,
the suggested solution
FReply FSceneViewport::AcquireFocusAndCapture(FIntPoint MousePosition, EFocusCause FocusCause)
{
// ...
// Mouse down should focus viewport for user input
// ReplyState.SetUserFocus(ViewportWidgetRef, FocusCause);
ReplyState.SetUserFocus(ViewportWidgetRef, FocusCause, true);
// ...
}
Solves the case of alt tabbing and returning to the PIE window.
For now I added code to FLevelViewportLayout to fix the input loss on minimizing and maximizing:
Added into LevelViewportLayout.h
/**
* Base class for level viewport layout configurations
* Handles maximizing and restoring well as visibility of specific viewports.
*/
class LEVELEDITOR_API FLevelViewportLayout : public FAssetEditorViewportLayout
{
...
struct FPL_CachedSlateUserData
{
public:
int32 UserIndex { INDEX_NONE };
TWeakPtr<SWidget> FocusWidget { nullptr };
TWeakPtr<SWidget> CapturedWidget { nullptr };
};
TArray<FPL_CachedSlateUserData> CachedSlateUserData { };
};
Added into LevelViewportLayout.h
void FLevelViewportLayout::MaximizeViewport( FName ViewportToMaximize, const bool bWantMaximize, const bool bWantImmersive, const bool bAllowAnimation )
{
...
bIsMaximized = bWantMaximize;
bIsImmersive = bWantImmersive;
// Start transition
bIsTransitioning = true;
//~ Start Changes
CachedSlateUserData.Reset();
FSlateApplication::Get().ForEachUser(
[&](FSlateUser& User)
{
FPL_CachedSlateUserData& CachedSlateUserDataEntry = CachedSlateUserData.Emplace_GetRef(FPL_CachedSlateUserData{ User.GetUserIndex() });
CachedSlateUserDataEntry.FocusWidget = User.GetFocusedWidget();
const FWeakWidgetPath& WeakCursorCapturePat = User.GetWeakCursorCapturePath();
CachedSlateUserDataEntry.CapturedWidget = WeakCursorCapturePat.IsValid() ? WeakCursorCapturePat.GetLastWidget() : nullptr;
});
//~ End Changes
...
}
Replaced LevelViewportLayout.h
// Update keyboard focus. Focus is usually lost when we re-parent the viewport widget.
{
// We first need to clear keyboard focus so that Slate doesn't assume that focus won't need to change
// simply because the viewport widget object is the same -- it has a new widget path!
FSlateApplication::Get().ClearKeyboardFocus( EFocusCause::SetDirectly );
// Set keyboard focus directly
MaximizedViewportEntity->SetKeyboardFocus();
}
with
// Update focus. Focus is usually lost when we re-parent the viewport widget.
{
// We first need to clear focus so that Slate doesn't assume that focus won't need to change
// simply because the viewport widget object is the same -- it has a new widget path!
FSlateApplication& SlateApp = FSlateApplication::Get();
SlateApp.ClearAllUserFocus( EFocusCause::SetDirectly );
FSlateApplication::Get().ForEachUser(
[&](FSlateUser& User)
{
FPL_CachedSlateUserData* CachedData = CachedSlateUserData.FindByPredicate(
[&User](const FPL_CachedSlateUserData& SlateUserData)
{
return SlateUserData.UserIndex == User.GetUserIndex();
});
if (CachedData)
{
if (CachedData->FocusWidget.IsValid())
{
User.SetFocus(CachedData->FocusWidget.Pin().ToSharedRef(), EFocusCause::SetDirectly);
}
if (CachedData->CapturedWidget.IsValid())
{
const TSharedRef<SWidget>& CapturedWidget = CachedData->CapturedWidget.Pin().ToSharedRef();
FWidgetPath PathToViewport;
if (FSlateWindowHelper::FindPathToWidget(FSlateApplication::Get().GetTopLevelWindows(),
CapturedWidget, PathToViewport, EVisibility::All))
{
User.SetCursorCaptor(CapturedWidget, PathToViewport);
}
}
}
}
);
}
this seems to work for now.