Improve the checking for game in foreground

Instead of checking every imput event, check every 0.5s. Also expose the foregrounded boolean, and raise an event so other code can use this.
This commit is contained in:
Steve Streeting 2021-04-29 12:28:27 +01:00
parent a466ce6a71
commit 510423abfe
2 changed files with 44 additions and 13 deletions

View File

@ -15,7 +15,8 @@ void UStevesGameSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
CreateInputDetector();
InitTheme();
InitTheme();
InitForegroundCheck();
}
void UStevesGameSubsystem::Deinitialize()
@ -51,6 +52,30 @@ void UStevesGameSubsystem::InitTheme()
DefaultUiTheme = LoadObject<UUiTheme>(nullptr, *DefaultUiThemePath, nullptr);
}
void UStevesGameSubsystem::InitForegroundCheck()
{
// Check foreground status every 0.5 seconds
GetWorld()->GetTimerManager().SetTimer(ForegroundCheckHandle, this, &UStevesGameSubsystem::CheckForeground, 0.5);
}
void UStevesGameSubsystem::CheckForeground()
{
bool bNewForeground = bIsForeground;
if (IsValid(GEngine) && IsValid(GEngine->GameViewport) && GEngine->GameViewport->Viewport)
bNewForeground = GEngine->GameViewport->Viewport->IsForegroundWindow();
if (bNewForeground != bIsForeground)
{
bIsForeground = bNewForeground;
InputDetector->bIgnoreEvents = !bIsForeground;
OnWindowForegroundChanged.Broadcast(bIsForeground);
}
}
void UStevesGameSubsystem::OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode)
{
// We can't check this during Initialize because it's too early
@ -221,16 +246,7 @@ void UStevesGameSubsystem::SetBrushFromAtlas(FSlateBrush* Brush, TScriptInterfac
bool UStevesGameSubsystem::FInputModeDetector::ShouldProcessInputEvents() const
{
if (!bProcessEventsInBackground)
{
if (IsValid(GEngine) && IsValid(GEngine->GameViewport) && GEngine->GameViewport->Viewport)
return GEngine->GameViewport->Viewport->IsForegroundWindow();
// If we're not supposed to process in the background but there's no viewport, don't process
return false;
}
return true;
return !bIgnoreEvents;
}
UStevesGameSubsystem::FInputModeDetector::FInputModeDetector()

View File

@ -12,6 +12,7 @@
#include "StevesGameSubsystem.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWindowForegroundChanged, bool, bFocussed);
UCLASS(Config=Game)
class STEVESUEHELPERS_API UStevesGameSubsystem : public UGameInstanceSubsystem
@ -68,8 +69,8 @@ protected:
bool ShouldProcessInputEvents() const;
public:
/// Whether this detector should process events when the application is in the background
bool bProcessEventsInBackground = false;
/// Whether this detector should ignore events (e.g. because the application is in the background)
bool bIgnoreEvents = false;
// Single delegate caller, owner should propagate if they want (this isn't a UObject)
FInternalInputModeChanged OnInputModeChanged;
@ -100,12 +101,20 @@ protected:
FFocusSystem FocusSystem;
bool bCheckedViewportClient = false;
FTimerHandle ForegroundCheckHandle;
UPROPERTY(BlueprintReadOnly)
bool bIsForeground = true;
UPROPERTY(BlueprintReadWrite)
UUiTheme* DefaultUiTheme;
void CreateInputDetector();
void DestroyInputDetector();
void InitTheme();
void InitForegroundCheck();
void CheckForeground();
// Called by detector
void OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode);
@ -118,6 +127,10 @@ public:
UPROPERTY(BlueprintAssignable)
FOnInputModeChanged OnInputModeChanged;
/// Event raised when the game window's foreground status changes
UPROPERTY(BlueprintAssignable)
FOnWindowForegroundChanged OnWindowForegroundChanged;
UFUNCTION(BlueprintCallable)
EInputMode GetLastInputModeUsed(int PlayerIndex = 0) const { return InputDetector->GetLastInputMode(PlayerIndex); }
@ -134,6 +147,8 @@ public:
/// Get the global focus system
FFocusSystem* GetFocusSystem();
/// Return whether the game is currently in the foreground
bool IsForeground() const { return bIsForeground; }
/**
* @brief Get an input button / key / axis image as a sprite based on any combination of action / axis binding or manual key