OriginSteamOverlayLauncher icon indicating copy to clipboard operation
OriginSteamOverlayLauncher copied to clipboard

Launching game in Big picture mode results in game window minimised.

Open gbdrbob opened this issue 9 months ago • 2 comments

I have encounteed an issue where launching a game via OSOL while Steam is in big picture mode results in the game being minimised to the task bar upon launch. Steps to reproduce:

STEPS

  • Install GOG version of Baldur's Gate 3 on host PC.
  • Launch BG3 once via GOG galaxy and select DX11 rendering in the Larian Launcher.
  • Set GOG Galaxy to skip the Larian Launcher by configuring a custom default executable with the --skip-launcher argument passed to LariLauncher.exe.
  • Install [OSOL] and add it to steam as a non-steam game.
  • Configure OSOL to call GOG galaxy with the required arguments to launch BG3 without any further user intervention (/command=runGame /gameId=1456460669)
  • Open steam in Big Picture mode and try to launch Baldur's Gate 3 via OSOL as configured above.

RESULTS Game is launched, but it is minimised to the task bar.

EXPECTED Game launches without further user intervention and game window is visible.

Notes: if I manually intervene to click the minimised game icon on the taskbar then the game resumes as expected

If I launch the game from standard desktop mode, then the above described bug does not occur, the game launches as expected. However this is inconvenient for living room use / gamepad control.

If I do not configure GOG Galaxy to call the Larian Launcher with the --skip-launcher parameter, so manual intervention is required in the form of clicking the "Play" button within the Larian Launcher to complete the launching of the game, then the bug does not occur.

This bug is very problematic when streaming via a Steam link, as it results in the GOG galaxy window being streamed to the client with no way to switch back to the minimised game window from within the streamed session.

I have also tested without OSOL, instead using a powershell script to launch GOG galaxy and auto close it after the game process exits and the exact same bug occurs. However it does not occur if the GOG galaxy launcher is directly added to steam without OSOL or my PS script.

I realise this is chaining a lot of different things together (OSOL or PS script -> GOG Galaxy -> LariLauncher.exe -> bg3_dx11.exe), a workaround is to not launch the game via OSOL and GOG galaxy but to add LariLauncher.exe to Steam instead, however that disables the GOG Galaxy achievement tracking, which I'd prefer to keep.

gbdrbob avatar Apr 27 '25 21:04 gbdrbob

Update to this - Using the example from here and some help from MS Copilot, I managed to write a powershell script that works around the issue by forcing the game window back into the foreground:

ShowBG3.ps1

# Requires PowerShell Version 5 or later

# Enumerate window show states
Enum ShowStates {
    Hide = 0
    Normal = 1
    Minimized = 2
    Maximized = 3
    ShowNoActivateRecentPosition = 4
    Show = 5
    MinimizeActivateNext = 6
    MinimizeNoActivate = 7
    ShowNoActivate = 8
    Restore = 9
    ShowDefault = 10
    ForceMinimize = 11
}

# Add necessary User32.dll functions for window manipulation
$windowApiCode = @"
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
"@

$WindowAPI = Add-Type -MemberDefinition $windowApiCode -Name User32WindowAPI -PassThru

# Function to determine whether Steam is in Big Picture mode
function Is-SteamInBigPictureMode {
    $steamWebHelperProcess = Get-Process -Name "steamwebhelper" -ErrorAction SilentlyContinue

    if ($steamWebHelperProcess) {
        $windowTitles = $steamWebHelperProcess | Select-Object -ExpandProperty MainWindowTitle
        return ($windowTitles -match "Big Picture")
    }

    return $false
}

# Function to wait for a specific process
function Wait-ForTargetProcess {
    param (
        [string[]]$TargetProcessNames,
        [int]$TimeoutInSeconds = 120
    )
    Write-Host "Waiting for processes: $($TargetProcessNames -join ', ')..."
    $processWaitStartTime = Get-Date
    do {
        $targetProcess = Get-Process | Where-Object { $_.ProcessName -match ($TargetProcessNames -join "|") } | Select-Object -First 1
        if ((Get-Date) -gt $processWaitStartTime.AddSeconds($TimeoutInSeconds)) {
            Write-Host "Timeout reached while waiting for the target process."
            return $null
        }
        Start-Sleep -Seconds 1
    } while (-not $targetProcess)
    return $targetProcess
}

# Function to get the handle of the foreground window
function Get-ForegroundWindowHandle {
    return $WindowAPI::GetForegroundWindow()
}

# Function to manage window state
function Set-WindowState {
    param (
        [IntPtr]$WindowHandle,
        [ShowStates]$State
    )

    # Set a retry mechanism
    $maxRetries = 30
    $retryDelay = 1  # seconds
    $retryCount = 0
    $success = $false

    Write-Host "Attempting to set window state to $State for handle $WindowHandle..."

    do {
        # Try to update the window state
        $showWindowSuccess = $WindowAPI::ShowWindowAsync($WindowHandle, [int]$State)
        $setForegroundSuccess = $WindowAPI::SetForegroundWindow($WindowHandle)

        # Check if both API calls succeeded
        if ($showWindowSuccess -and $setForegroundSuccess) {
            Write-Host "Successfully set window state to $State."
            $success = $true
            break
        } else {
            Write-Host "Failed to set window state. Retrying... ($retryCount/$maxRetries)"
            Start-Sleep -Seconds $retryDelay
            $retryCount++
        }
    } while ($retryCount -lt $maxRetries)

    # Final check
    if (-not $success) {
        Write-Host "Error: Unable to set window state after $maxRetries retries."
    }
}

# Function to monitor foreground window state
function Monitor-ForegroundWindow {
    param (
        [IntPtr]$WindowHandle,
        [int]$DurationSeconds = 10
    )
    $startTime = Get-Date
    Write-Host "Monitoring the target window state for $DurationSeconds seconds..."
    while ((Get-Date) -lt $startTime.AddSeconds($DurationSeconds)) {
        $ForegroundWindowHandle = Get-ForegroundWindowHandle
        if ($ForegroundWindowHandle -ne $WindowHandle) {
            Write-Host "Game window $WindowHandle is not in the foreground. Current foreground window: $ForegroundWindowHandle"
            # Restore the window state and bring it to the foreground
            Set-WindowState -WindowHandle $WindowHandle -State ([ShowStates]::Restore)
        } else {
            Write-Host "Game window $WindowHandle remains in the foreground."
        }
        Start-Sleep -Seconds 1
    }
}

# Main launcher function
function Show-Game {
    param (
        [string[]]$TargetProcessNames,
        [int]$TimeoutInSeconds = 120
    )

    Write-Host "Waiting for target process..."
    $targetProcess = Wait-ForTargetProcess -TargetProcessNames $TargetProcessNames -TimeoutInSeconds $TimeoutInSeconds

    if ($targetProcess) {
        Write-Host "Checking if Steam is in Big Picture mode..."
        if (Is-SteamInBigPictureMode) {
            Write-Host "Steam is in Big Picture mode. Monitoring to ensure game window remains in foreground..."
            Monitor-ForegroundWindow -WindowHandle $targetProcess.MainWindowHandle -DurationSeconds 10
        } else {
            Write-Host "Steam is not in Big Picture mode. Proceeding without game window monitoring..."
        }
    } else {
        Write-Host "Error: Target process not found or timeout reached." -ForegroundColor Red
    }
}

# Execute the main function
Show-Game -TargetProcessNames @("bg3", "bg3_dx11") -TimeoutInSeconds 120

I call the script from OSOL via the PreLaunchExec options in the ini file:

PreLaunchExecPath=C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
PreLaunchExecArgs=-WindowStyle hidden -noprofile -executionpolicy bypass -file C:\Scripts\ShowBG3.ps1

Edit: refactored script

gbdrbob avatar Apr 27 '25 23:04 gbdrbob