Skip to content

Keep fullscreen apps active in background on macOS >= 15#226

Open
Brawl345 wants to merge 2 commits into
PlayCover:masterfrom
Brawl345:feature/background-keepalive
Open

Keep fullscreen apps active in background on macOS >= 15#226
Brawl345 wants to merge 2 commits into
PlayCover:masterfrom
Brawl345:feature/background-keepalive

Conversation

@Brawl345

Copy link
Copy Markdown

Disclamer: This was vibeslopped made with Claue Fable 5 (before it was taken down luckily!), I just steered and verified it.

This fixes the "apps are paused in background when fullscreen and I swipe away" that was introduced in macOS 15 for Catalyst apps. It blocks certain calls and "plays" a silent audio-loop since apps that play audio are kept alive (for music players on iOS).

Few things to note:

  • This was done on macOS 27 beta but I see no reason why it shouldn't work on older versions, too
  • When you quit a game and relaunch it immediately it gets bugged and needs to be force-closed since it doesn't have enough time to quit itself cleanly. So you have to wait a few seconds until relaunching (5-10 seconds). Dunno if there is a better way. didEnterBackgroundNotification etc are blocked because games will pause themselves, too (in addition to the hard block introduced by macOS 15)
  • Tested it with Genshin, HSR and ZZZ
  • Having OBS open breaks this, don't really know why (maybe some conflict regarding the audio-fix?)
  • I also have a version where you have to enable this workaround per-game first if there is any interest (I also modded PlayCover but without this setting only PlayTools suffices)
  • My Swift skills are lacking and I'm not a fan of sending in AI-made PRs but I got the OK on Discord and this is something a lot of people have been asking for
  • I intentionally left in the (excessive) code comments from Claude so it can help you refactoring/cleaning it up if needed

Fixes PlayCover/PlayCover#1568

Since macOS 15, runningboardd suspends Catalyst apps as soon as their
scene becomes invisible (window on another Space, minimized, hidden),
freezing PlayCover games completely. Games also pause themselves
because the engine receives the standard background lifecycle events.

This commit does the following on macOS >= 15:

1. Plays an inaudible audio loop (AVAudioEngine, .playback +
   .mixWithOthers, output volume 0). Like on iOS, an app that is
   actively playing audio is exempt from suspension. Requires
   UIBackgroundModes: [audio] in the app's Info.plist.
2. Hides the background transition from the game: drops the
   willResignActive/didEnterBackground notifications and neuters the
   corresponding app/scene delegate callbacks, so engines such as
   Unity never pause their player loop.

Because the shutdown sequence replays exactly these suppressed events
(quitWhenClose does so explicitly, Cmd+Q via the system), all quit
paths are hooked through NSApplication.terminate to stand down the
suppression and the audio exemption first, so games can still save
their state and exit cleanly.

Verified with Genshin Impact, Honkai: Star Rail and ZZZ on macOS 27 Beta:
the game keeps running at full speed while its window is swiped away, and
quits cleanly via both the close button and Cmd+Q.

Fixes PlayCover/PlayCover#1568

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@TheMoonThatRises TheMoonThatRises self-requested a review June 19, 2026 16:46
Comment thread PlayTools/PlayCover.swift Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: macOS 15: Game paused if other full-screen apps is currently active

2 participants