diff --git a/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp b/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp index 5945102..b6c568f 100644 --- a/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp +++ b/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp @@ -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(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() diff --git a/Source/StevesUEHelpers/Public/StevesGameSubsystem.h b/Source/StevesUEHelpers/Public/StevesGameSubsystem.h index 30a28be..c3a0137 100644 --- a/Source/StevesUEHelpers/Public/StevesGameSubsystem.h +++ b/Source/StevesUEHelpers/Public/StevesGameSubsystem.h @@ -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