From 4ed7a9d2d50c7842769bd74c8a19bdb80e9eec38 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 17:54:47 +0000 Subject: [PATCH] Force ES-DE's "Run in background" off durably; mount ~/ES-DE/settings Fixes a real, confirmed-live, cross-system bug: with ES-DE's "Run in background (while game is launched)" enabled, ES-DE keeps listening to every controller even after a game/emulator takes focus - a second controller's input can reach ES-DE's own menu and launch a completely different game underneath whatever's already running. ES-DE's own USERGUIDE.md names this exact failure mode. ES-DE's compiled default for this setting is already off (confirmed against its real Settings.cpp), but nothing in this repo asserted that durably, and ~/ES-DE (settings, gamelists, scraped media, logs) had no mount onto the game drive at all - confirmed against ES-DE's own source (getAppDataDirectory() is a plain $HOME/ES-DE) and GOW's own es-de startup script. Wolf normally reuses the same app container across sessions rather than recreating it each time (confirmed against Wolf's docker.cpp - it only removes the container on exit if WOLF_STOP_CONTAINER_ON_EXIT=TRUE, which this repo never sets), so this mostly didn't bite day to day, but it meant the setting - and everything else under ~/ES-DE - wasn't safe across an actual reinstall the way roms/saves/BIOS already are. Mounts esde-settings/ onto ~/ES-DE/settings specifically (additive, doesn't touch the existing custom_systems mount) and writes a surgical, idempotent RunInBackground=false into es_settings.xml on every install - never a full rewrite, since that file is the user's own complete settings state. Verified the write logic against fresh-file, existing- file-with-other-settings, and flip-an-existing-true-to-false cases, plus idempotent re-runs. Gamelists/scraped-media durability under ~/ES-DE is a related, noted gap - not fixed here. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01VLX1yYKJExGSXmgUhxKQG6 --- services/wolf.sh | 115 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/services/wolf.sh b/services/wolf.sh index 130792b..6d0d9f4 100644 --- a/services/wolf.sh +++ b/services/wolf.sh @@ -325,6 +325,7 @@ EOF echo " and Wii U (Cemu) in ES-DE via a second, opt-in 'Alternative emulators' command" echo " - Expose Wolf's REST API socket to the host (WOLF_SOCKET_PATH + /var/run/wolf mount)" echo " so './manage.sh controllers' can force distinct pad types per controller slot" + echo " - Force ES-DE's 'Run in background' off durably (mounts + writes esde-settings/es_settings.xml)" return 0 fi @@ -1391,6 +1392,49 @@ PS2XMLPY log_success "PS2: added PCEE2 as the default RetroArch core (custom_systems/es_systems.xml) — ES-DE's" log_info "own build doesn't ship it yet (added upstream in the not-yet-released 3.5.0)" + # ── ES-DE: force "Run in background" off ──────────────────────────────── + # ES-DE's own compiled default for this IS already off (confirmed against + # its real Settings.cpp: mBoolMap["RunInBackground"] = {false, false}) — + # this write exists purely so that default stays durable and explicit + # rather than relying on it never having been toggled. Real, confirmed + # cause of a genuine bug otherwise: with it on, ES-DE keeps running and + # listening to every controller even after a game/emulator has launched + # and taken visual focus — a second controller's input can still reach + # ES-DE's own menu in the background and launch (and start playing audio + # for) a completely different game while the first one is still up + # front. ES-DE's own USERGUIDE.md explicitly names this failure mode + # ("make sure that the setting Run in background... is disabled"). + # Confirmed live: this affects any system, not just Cemu. + # + # es_settings.xml is the user's OWN full settings state (theme, scraper + # prefs, everything) — unlike es_systems.xml this is never a full + # rewrite, only a surgical strip-and-reappend of this one entry, + # same idempotent pattern as everywhere else in this file. Written as a + # plain top-level element with no wrapper, matching what + # ES-DE's own Settings::saveFile() actually produces today (confirmed + # against its source — the "wrap everything in " format is + # loader-side forward-compatibility for a future ES-DE release, not + # what gets written now); either format loads fine either way. + mkdir -p "$GAME_STORAGE_DIR/esde-settings" + _ESDE_SETTINGS="$GAME_STORAGE_DIR/esde-settings/es_settings.xml" + backup_if_exists "$_ESDE_SETTINGS" + python3 - "$_ESDE_SETTINGS" << 'ESDESETTINGSPY' +import re, sys +path = sys.argv[1] +try: + with open(path) as f: + content = f.read() +except FileNotFoundError: + content = '' +content = re.sub(r'[ \t]*[ \t]*\n?', '', content) +line = ' \n' +content = (content.rstrip('\n') + '\n' + line) if content.strip() else line +with open(path, 'w') as f: + f.write(content) +ESDESETTINGSPY + chown "$ACTUAL_USER:$ACTUAL_USER" "$_ESDE_SETTINGS" + log_success "ES-DE: 'Run in background (while game is launched)' forced off (esde-settings/es_settings.xml)" + # ── App selection ───────────────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" @@ -1941,7 +1985,23 @@ CATALOG = { f'{games}/retroarch:/home/retro/.config/retroarch:rw', f'{games}/emulators:/mnt/games/emulators:rw', f'{games}/emulators:/home/retro/Applications:rw', - f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw'], + f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw', + # ~/ES-DE (settings, gamelists, downloaded_media, logs) has + # NO mount at all otherwise (confirmed against ES-DE's own + # source and GOW's es-de startup.sh: getAppDataDirectory() + # is a plain $HOME/ES-DE, no XDG redirect) — Wolf normally + # reuses the same app container across sessions rather than + # recreating it each time (confirmed against Wolf's own + # docker.cpp: it only removes the container on session end + # if WOLF_STOP_CONTAINER_ON_EXIT=TRUE, which this repo never + # sets), so this doesn't get wiped every reconnect — but it + # IS lost on any real reinstall/container recreate, unlike + # everything else here which lives on the game drive. Only + # mounting settings/ specifically (not the whole ~/ES-DE + # tree) keeps this additive and non-breaking alongside the + # existing custom_systems mount above — gamelists/scraped + # media durability is a separate, not-yet-done improvement. + f'{games}/esde-settings:/home/retro/ES-DE/settings:rw'], env=ESDE_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host', ulimits=[], privileged=False, devices=['/dev/uinput:/dev/uinput'], @@ -3670,7 +3730,23 @@ CATALOG = { f'{games}/retroarch:/home/retro/.config/retroarch:rw', f'{games}/emulators:/mnt/games/emulators:rw', f'{games}/emulators:/home/retro/Applications:rw', - f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw'], + f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw', + # ~/ES-DE (settings, gamelists, downloaded_media, logs) has + # NO mount at all otherwise (confirmed against ES-DE's own + # source and GOW's es-de startup.sh: getAppDataDirectory() + # is a plain $HOME/ES-DE, no XDG redirect) — Wolf normally + # reuses the same app container across sessions rather than + # recreating it each time (confirmed against Wolf's own + # docker.cpp: it only removes the container on session end + # if WOLF_STOP_CONTAINER_ON_EXIT=TRUE, which this repo never + # sets), so this doesn't get wiped every reconnect — but it + # IS lost on any real reinstall/container recreate, unlike + # everything else here which lives on the game drive. Only + # mounting settings/ specifically (not the whole ~/ES-DE + # tree) keeps this additive and non-breaking alongside the + # existing custom_systems mount above — gamelists/scraped + # media durability is a separate, not-yet-done improvement. + f'{games}/esde-settings:/home/retro/ES-DE/settings:rw'], env=ESDE_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host', ulimits=[], privileged=False, devices=['/dev/uinput:/dev/uinput'], @@ -4255,6 +4331,41 @@ regardless of which type it's sharing a GUID with. This is a reasoned workaround, not one confirmed working live — if it doesn't pan out, that's useful to know. +## ES-DE launches a second game while one is already running +**Symptom** (confirmed live, not Cemu-specific — happens on any system): +a second controller's input reaches ES-DE's own menu in the background +and launches an entirely different game — you'll hear/see it start +playing underneath whatever already has focus. + +**Cause:** ES-DE's own **"Run in background (while game is launched)"** +setting. When it's on, ES-DE keeps running and listening to every +controller even after something else has launched and taken visual +focus — ES-DE's own USERGUIDE.md names this exact failure mode directly. +ES-DE's compiled default for this is already off, but nothing durably +enforced that in this setup before now, so it's easy for it to have +gotten toggled on at some point and stick that way. + +**This installer now forces it off automatically** (\`esde-settings/es_settings.xml\`, +written fresh on every install/reinstall) — no menu digging required. If +you're on an install from before this existed, re-run \`sudo ./setup.sh wolf\` +to pick it up, or set it by hand: **Main Menu → Other Settings → Run in +background (while game is launched) → off**. + +**Why this needed its own mount, not just a one-time write:** \`~/ES-DE\` +(settings, gamelists, scraped artwork, logs) had no bind mount onto the +game drive at all before this — confirmed against ES-DE's own source +(\`getAppDataDirectory()\` is a plain \`$HOME/ES-DE\`, no XDG redirect) and +GOW's own \`es-de\` startup script. In normal day-to-day use this mostly +didn't matter, since Wolf reuses the same app container across sessions +rather than recreating it each time (confirmed against Wolf's own +\`docker.cpp\`: the container is only removed on session end if +\`WOLF_STOP_CONTAINER_ON_EXIT=TRUE\`, which this repo never sets) — but it +meant this setting, and everything else under \`~/ES-DE\`, wasn't safe +across an actual reinstall or container recreate the way roms/saves/BIOS +already are. Only \`settings/\` is mounted now (\`esde-settings/\`, additive, +doesn't touch the existing \`custom_systems\` mount) — gamelists and +scraped media durability is a related gap, not yet fixed. + ## EA games (Battlefront II 2017, etc.) EA titles require GE-Proton and the EA App to be installed inside the Wine prefix. The EA App handles authentication — without it, the game launches