Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05942fb44a | ||
|
|
d41da6356d |
+140
-13
@@ -4071,9 +4071,50 @@ except Exception:
|
|||||||
ls "$_SANG_EMU_DIR" 2>/dev/null
|
ls "$_SANG_EMU_DIR" 2>/dev/null
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
_SANG_EXE="/home/retro/Applications/$(basename "$_SANG_HOST_FILE")"
|
_SANG_REAL_EXE="/home/retro/Applications/$(basename "$_SANG_HOST_FILE")"
|
||||||
[ -z "$_SANG_NAME" ] && _SANG_NAME=$(basename "$_SANG_HOST_FILE" | sed -E 's/\.(AppImage|sh|x86_64)$//I')
|
[ -z "$_SANG_NAME" ] && _SANG_NAME=$(basename "$_SANG_HOST_FILE" | sed -E 's/\.(AppImage|sh|x86_64)$//I')
|
||||||
|
|
||||||
|
# Route the actual launch through a small fullscreen-forcing wrapper
|
||||||
|
# instead of pointing Steam's Exe directly at the AppImage. Why: a
|
||||||
|
# non-Steam game launched from Steam is a SECOND top-level window in
|
||||||
|
# Wolf's single-app Steam Sway session (RUN_SWAY=true on the 'steam'
|
||||||
|
# CATALOG entry) — Sway's own kiosk config only auto-fullscreens the
|
||||||
|
# ONE window it expects (Steam's own), so anything launched from
|
||||||
|
# inside Steam opens at whatever default size it requests instead,
|
||||||
|
# which reads as roughly half the screen against a full
|
||||||
|
# Moonlight-resolution display. Reported live against ES-DE/Dolphin
|
||||||
|
# added this way. NOT yet confirmed live that swaymsg actually
|
||||||
|
# reaches Sway from inside this exact container/session — if it
|
||||||
|
# doesn't, the wrapper's fullscreen loop just fails silently
|
||||||
|
# (2>/dev/null below) and the app launches exactly as it did before
|
||||||
|
# this existed, so this is safe to try without risking the launch
|
||||||
|
# itself. Regenerated on every call (cheap, stateless — nothing to
|
||||||
|
# lose by overwriting it) so a fix to the wrapper reaches every
|
||||||
|
# existing shortcut the next time it's (re-)added, not just new ones.
|
||||||
|
_SANG_WRAP="$_SANG_EMU_DIR/steam-fullscreen-wrap"
|
||||||
|
cat > "$_SANG_WRAP" << 'WRAPEOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# steam-fullscreen-wrap <real-binary> [args...]
|
||||||
|
# Launches the real target, then repeatedly asks Sway to fullscreen whatever
|
||||||
|
# currently has input focus for a few seconds after launch — the newly
|
||||||
|
# launched window is expected to grab focus once it maps, same as any
|
||||||
|
# ordinary X11/Wayland client. 'fullscreen enable' (not 'toggle') is
|
||||||
|
# idempotent, so repeating it while the window is already fullscreen is a
|
||||||
|
# harmless no-op rather than flipping it back off.
|
||||||
|
REAL_BIN="$1"; shift
|
||||||
|
"$REAL_BIN" "$@" &
|
||||||
|
PID=$!
|
||||||
|
(
|
||||||
|
for _i in $(seq 1 20); do
|
||||||
|
sleep 0.5
|
||||||
|
swaymsg fullscreen enable 2>/dev/null
|
||||||
|
done
|
||||||
|
) &
|
||||||
|
wait "$PID"
|
||||||
|
WRAPEOF
|
||||||
|
chmod +x "$_SANG_WRAP"
|
||||||
|
_SANG_EXE="/home/retro/Applications/steam-fullscreen-wrap"
|
||||||
|
|
||||||
STEAM_HOME=$(_steam_home)
|
STEAM_HOME=$(_steam_home)
|
||||||
if [ -z "$STEAM_HOME" ]; then
|
if [ -z "$STEAM_HOME" ]; then
|
||||||
echo "No Steam home found yet under ${WOLF_STATE_DIR:-/etc/wolf}."
|
echo "No Steam home found yet under ${WOLF_STATE_DIR:-/etc/wolf}."
|
||||||
@@ -4100,10 +4141,10 @@ except Exception:
|
|||||||
sleep 3
|
sleep 3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo python3 - "$_SANG_VDF" "$_SANG_EXE" "$_SANG_NAME" "/home/retro/Applications" << 'VDFPY'
|
sudo python3 - "$_SANG_VDF" "$_SANG_EXE" "$_SANG_NAME" "/home/retro/Applications" "$_SANG_REAL_EXE" << 'VDFPY'
|
||||||
import sys, struct, os, zlib
|
import sys, struct, os, zlib
|
||||||
|
|
||||||
path, exe_path, app_name, start_dir = sys.argv[1:5]
|
path, exe_path, app_name, start_dir, real_exe = sys.argv[1:6]
|
||||||
|
|
||||||
TYPE_MAP, TYPE_STR, TYPE_INT, TYPE_END = 0x00, 0x01, 0x02, 0x08
|
TYPE_MAP, TYPE_STR, TYPE_INT, TYPE_END = 0x00, 0x01, 0x02, 0x08
|
||||||
|
|
||||||
@@ -4167,13 +4208,30 @@ if shortcuts_entry is None:
|
|||||||
|
|
||||||
entries_list = shortcuts_entry[2]
|
entries_list = shortcuts_entry[2]
|
||||||
|
|
||||||
|
# exe_path now points at the shared steam-fullscreen-wrap script (same Exe
|
||||||
|
# for every emulator added this way), with the real per-emulator target
|
||||||
|
# carried in LaunchOptions instead — so matching (for both idempotent
|
||||||
|
# re-adds and appid uniqueness) has to key on the (exe, LaunchOptions) PAIR,
|
||||||
|
# not exe alone, or adding a second emulator would silently overwrite the
|
||||||
|
# first one's shortcut entry. Also cleans up a legacy entry from before this
|
||||||
|
# wrapper existed, where Exe pointed directly at this same real binary with
|
||||||
|
# no LaunchOptions at all — re-adding an emulator added under the old
|
||||||
|
# scheme replaces that stale direct-launch entry instead of leaving a
|
||||||
|
# duplicate tile behind.
|
||||||
quoted_exe = f'"{exe_path}"'
|
quoted_exe = f'"{exe_path}"'
|
||||||
entries_list[:] = [e for e in entries_list if get_field(e[2], 'exe') != quoted_exe]
|
quoted_launch = f'"{real_exe}"'
|
||||||
|
entries_list[:] = [
|
||||||
|
e for e in entries_list
|
||||||
|
if not (
|
||||||
|
(get_field(e[2], 'exe') == quoted_exe and get_field(e[2], 'LaunchOptions') == quoted_launch)
|
||||||
|
or get_field(e[2], 'exe') == quoted_launch
|
||||||
|
)
|
||||||
|
]
|
||||||
for idx, e in enumerate(entries_list):
|
for idx, e in enumerate(entries_list):
|
||||||
e[0] = str(idx)
|
e[0] = str(idx)
|
||||||
|
|
||||||
new_index = str(len(entries_list))
|
new_index = str(len(entries_list))
|
||||||
crc_input = (exe_path + app_name).encode('utf-8')
|
crc_input = (exe_path + real_exe + app_name).encode('utf-8')
|
||||||
appid = (zlib.crc32(crc_input) | 0x80000000) & 0xFFFFFFFF
|
appid = (zlib.crc32(crc_input) | 0x80000000) & 0xFFFFFFFF
|
||||||
appid_signed = appid - 0x100000000 if appid >= 0x80000000 else appid
|
appid_signed = appid - 0x100000000 if appid >= 0x80000000 else appid
|
||||||
|
|
||||||
@@ -4184,7 +4242,7 @@ new_entry_fields = [
|
|||||||
['StartDir', TYPE_STR, f'"{start_dir}"'],
|
['StartDir', TYPE_STR, f'"{start_dir}"'],
|
||||||
['icon', TYPE_STR, ''],
|
['icon', TYPE_STR, ''],
|
||||||
['ShortcutPath', TYPE_STR, ''],
|
['ShortcutPath', TYPE_STR, ''],
|
||||||
['LaunchOptions', TYPE_STR, ''],
|
['LaunchOptions', TYPE_STR, quoted_launch],
|
||||||
['IsHidden', TYPE_INT, 0],
|
['IsHidden', TYPE_INT, 0],
|
||||||
['AllowDesktopConfig', TYPE_INT, 1],
|
['AllowDesktopConfig', TYPE_INT, 1],
|
||||||
['AllowOverlay', TYPE_INT, 1],
|
['AllowOverlay', TYPE_INT, 1],
|
||||||
@@ -4200,12 +4258,12 @@ entries_list.append([new_index, TYPE_MAP, new_entry_fields])
|
|||||||
|
|
||||||
with open(path, 'wb') as f:
|
with open(path, 'wb') as f:
|
||||||
f.write(serialize_map(root))
|
f.write(serialize_map(root))
|
||||||
print(f"Wrote shortcuts.vdf: {app_name} -> {exe_path} (appid {appid_signed})")
|
print(f"Wrote shortcuts.vdf: {app_name} -> {real_exe} (via {exe_path}, appid {appid_signed})")
|
||||||
VDFPY
|
VDFPY
|
||||||
sudo chown 1000:1000 "$_SANG_VDF"
|
sudo chown 1000:1000 "$_SANG_VDF"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Added '$_SANG_NAME' -> $_SANG_EXE to Steam's shortcuts.vdf."
|
echo "Added '$_SANG_NAME' -> $_SANG_REAL_EXE (via the fullscreen wrapper) to Steam's shortcuts.vdf."
|
||||||
echo "Open Steam in Moonlight (it will restart since it was stopped above) —"
|
echo "Open Steam in Moonlight (it will restart since it was stopped above) —"
|
||||||
echo "the new tile appears in your Library (may need the Library view, not just Home)."
|
echo "the new tile appears in your Library (may need the Library view, not just Home)."
|
||||||
echo "First launch: right-click it -> Properties -> Compatibility, and confirm"
|
echo "First launch: right-click it -> Properties -> Compatibility, and confirm"
|
||||||
@@ -4701,7 +4759,26 @@ CATALOG = {
|
|||||||
# (see below) — without it, an emulator AppImage (Cemu, etc.)
|
# (see below) — without it, an emulator AppImage (Cemu, etc.)
|
||||||
# added as a non-Steam game (./manage.sh steam-add-nonsteam-game)
|
# added as a non-Steam game (./manage.sh steam-add-nonsteam-game)
|
||||||
# has no file to actually point Exe at from inside this container.
|
# has no file to actually point Exe at from inside this container.
|
||||||
f'{games}/emulators:/home/retro/Applications:rw'],
|
f'{games}/emulators:/home/retro/Applications:rw',
|
||||||
|
# Same roms/saves/bios/retro-home/retroarch mounts as esde/
|
||||||
|
# retroarch below — without these, a standalone ES-DE or
|
||||||
|
# RetroArch AppImage added here as a non-Steam game (same
|
||||||
|
# mechanism as Cemu above) would see none of the ROMs, cores,
|
||||||
|
# save states, BIOS files, or ES-DE's own settings/custom
|
||||||
|
# systems (TI-99, Wii U AntiMicroX command) that the esde/
|
||||||
|
# retroarch containers already have — it'd start from a
|
||||||
|
# completely empty config instead of reusing what's already
|
||||||
|
# set up. Every path here is the exact same host directory
|
||||||
|
# those two containers mount, just also visible from Steam.
|
||||||
|
f'{games}/roms:/ROMs:rw',
|
||||||
|
f'{games}/saves:/mnt/games/saves:rw',
|
||||||
|
f'{games}/media:/media:rw',
|
||||||
|
f'{games}/bios:/home/retro/bioses:rw',
|
||||||
|
f'{games}/retro-home:/home/retro/.config:rw',
|
||||||
|
f'{games}/retro-home-data:/home/retro/.local/share:rw',
|
||||||
|
f'{games}/retroarch:/home/retro/.config/retroarch:rw',
|
||||||
|
f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw',
|
||||||
|
f'{games}/esde-settings:/home/retro/ES-DE/settings:rw'],
|
||||||
env=['PROTON_LOG=1', 'RUN_SWAY=true',
|
env=['PROTON_LOG=1', 'RUN_SWAY=true',
|
||||||
'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*'],
|
'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*'],
|
||||||
cap_add=['SYS_ADMIN', 'SYS_NICE', 'SYS_PTRACE', 'NET_RAW', 'MKNOD', 'NET_ADMIN'],
|
cap_add=['SYS_ADMIN', 'SYS_NICE', 'SYS_PTRACE', 'NET_RAW', 'MKNOD', 'NET_ADMIN'],
|
||||||
@@ -5295,10 +5372,60 @@ controllers per player slot even when the physical controllers are
|
|||||||
identical models (the same case \`./manage.sh controllers\` exists to work
|
identical models (the same case \`./manage.sh controllers\` exists to work
|
||||||
around for ES-DE). Add Cemu here, then in Steam's own Big Picture
|
around for ES-DE). Add Cemu here, then in Steam's own Big Picture
|
||||||
Controller Settings you can see and assign each detected controller
|
Controller Settings you can see and assign each detected controller
|
||||||
individually. This hasn't been confirmed live yet against Wolf's
|
individually.
|
||||||
container-created virtual controllers specifically (real hardware behaves
|
|
||||||
this way; whether Steam Input sees Wolf's virtual joypads the same way is
|
**Controller doesn't respond at all once added to Steam?** Confirmed live:
|
||||||
still to be tested) — worth trying before assuming it works.
|
this is Steam Input, not the emulator — by default Steam applies its own
|
||||||
|
controller configuration to *every* shortcut, Steam or non-Steam alike,
|
||||||
|
and a freshly-added non-Steam game with no configuration picked yet can
|
||||||
|
end up with no usable mapping at all rather than passing raw input
|
||||||
|
through. Fix from Steam's own Big Picture UI: select the shortcut → the
|
||||||
|
controller icon / **Manage Game** → **Controller Options**, and either
|
||||||
|
pick a **Gamepad** template (closest to "pass it through as a normal
|
||||||
|
joystick", needed for ES-DE/RetroArch's own native SDL input handling to
|
||||||
|
see it at all) or turn **Steam Input** off for that one shortcut entirely
|
||||||
|
if you don't need the per-device assignment this section is about in the
|
||||||
|
first place. This is a one-time, per-shortcut setting Steam remembers —
|
||||||
|
not something this installer can preconfigure from the command line, since
|
||||||
|
it's stored in Steam's own (separate, Steam Cloud-synced) controller
|
||||||
|
config rather than \`shortcuts.vdf\`.
|
||||||
|
|
||||||
|
**Opens at roughly half the screen instead of fullscreen?** Also confirmed
|
||||||
|
live, and now worked around automatically as of the version of this repo
|
||||||
|
that added the point below — \`steam-add-nonsteam-game\`/
|
||||||
|
\`steam-setup-frontends\` route the launch through a small wrapper
|
||||||
|
(\`emulators/steam-fullscreen-wrap\`) instead of pointing Steam's \`Exe\`
|
||||||
|
directly at the AppImage. The underlying cause: a non-Steam game launched
|
||||||
|
from Steam is a *second* top-level window inside Wolf's single-app Steam
|
||||||
|
Sway session, and Sway's own kiosk config only auto-fullscreens the ONE
|
||||||
|
window it expects (Steam's own) — anything launched from inside Steam
|
||||||
|
opens at whatever default size it requests instead. The wrapper launches
|
||||||
|
the real binary, then repeatedly asks Sway to fullscreen whatever currently
|
||||||
|
has focus for a few seconds after launch (idempotent — harmless if it's
|
||||||
|
already fullscreen). **This has not been confirmed live against a real
|
||||||
|
Wolf Steam session yet** — if \`swaymsg\` isn't reachable from inside that
|
||||||
|
exact container, the wrapper's fullscreen loop just fails silently and the
|
||||||
|
window opens at its old default size, same as before this existed; it's
|
||||||
|
safe to try either way since the underlying launch itself is unaffected.
|
||||||
|
Re-run \`steam-add-nonsteam-game\`/\`steam-setup-frontends\` for anything
|
||||||
|
already added before this existed — it replaces the old direct-launch
|
||||||
|
shortcut with the wrapped one automatically, no duplicate tile left behind.
|
||||||
|
|
||||||
|
**An added emulator's tile appears in Steam but crashes on launch instead
|
||||||
|
of opening at all** (as opposed to the half-screen case above, where it
|
||||||
|
does open): that's a different problem — something about the AppImage
|
||||||
|
itself failing to run inside the Steam container specifically, since the
|
||||||
|
same binary launching fine through the \`esde\`/\`desktop\` Wolf apps rules out
|
||||||
|
the AppImage being broken outright. Worth checking before assuming it's
|
||||||
|
unfixable:
|
||||||
|
\`\`\`bash
|
||||||
|
CONTAINER=\$(docker ps --format '{{.Names}}' | grep -i WolfSteam | head -1)
|
||||||
|
docker exec "\$CONTAINER" /home/retro/Applications/<the-appimage-file> ; echo "exit: \$?"
|
||||||
|
\`\`\`
|
||||||
|
Run directly like this (no wrapper, no Steam involved) the real error
|
||||||
|
usually prints straight to the terminal — a missing shared library, a
|
||||||
|
FUSE/AppImage mount failure (\`dlopen(): error loading libfuse.so.2\`),
|
||||||
|
or similar. That output is what actually narrows down the fix.
|
||||||
|
|
||||||
## Running ES-DE and/or RetroArch through Steam instead of their own Wolf apps
|
## Running ES-DE and/or RetroArch through Steam instead of their own Wolf apps
|
||||||
The same Steam Input reasoning above applies beyond just Cemu: ES-DE and
|
The same Steam Input reasoning above applies beyond just Cemu: ES-DE and
|
||||||
|
|||||||
Reference in New Issue
Block a user