The desktop uses the client's own game entries; a steam shim hands them to the app

The client already writes one menu entry per installed game (steam steam://rungameid/<id>, with
the game's icon); they were dead for want of a steam command, and r45 added a second entry per
game beside them. Now: steam on the desktop is a shim that hands off to bannerlator-steam-launch
(and is the client itself anywhere else), and bannerlator-desktop-games writes an entry only for
a game the client wrote none for.
This commit is contained in:
The412Banner committed 2026-09-22 10:48:26 -04:00
1 parent d0ca41d160
commit b28e91128f
5 files changed
+48 -11

No files matched your search

+6 -6
View File
@@ -188,12 +188,12 @@ assets internal. ⚠️ Built; not yet seen installing to a card.
### The client's games on the desktop
The desktop's menu lists every game the Steam client has installed (Games category, the game's
own artwork), and the home folder has **Steam Games** and **SD Games** links to their files. A
game entry - and the menu's **Steam** / **Steam Big Picture** entries - cannot run the client on
the desktop, where nothing can draw with Vulkan; they hand off to the app
(`bannerlator-steam-launch`), which ends the desktop session and starts a Steam session in its
place: the client's **desktop UI** under gamescope, and the game straight away when one was
The Steam client writes a menu entry for every game it installs (Games category, the game's
icon), and the home folder has **Steam Games** and **SD Games** links to their files. Those
entries run `steam steam://rungameid/…`; on this desktop `steam` is a shim, because the client
cannot run where nothing can draw with Vulkan. It - and the menu's **Steam** / **Steam Big
Picture** entries - hand off to the app (`bannerlator-steam-launch`), which ends the desktop
session and starts a Steam session in its place: the client's **desktop UI** under gamescope, and the game straight away when one was
chosen. Back opens the drawer as in any session; Stop session returns to the app. The list is
rebuilt at every desktop start. ⚠️ Built; not yet tried on a device.
@@ -36,6 +36,7 @@ object SessionFiles {
"usr/local/bin/bannerlator-netmanager" to "usr/local/bin/bannerlator-netmanager",
"usr/local/bin/bannerlator-steam-launch" to "usr/local/bin/bannerlator-steam-launch",
"usr/local/bin/bannerlator-desktop-games" to "usr/local/bin/bannerlator-desktop-games",
"usr/local/bin/bannerlator-steam-shim" to "usr/local/bin/bannerlator-steam-shim",
)
// The desktop's launcher and labwc defaults, only where the desktop package is installed:
// staging them into a runtime without it would make the desktop look present when it is not.
+2
View File
@@ -81,7 +81,9 @@ if [ ! -f /var/cache/fontconfig/.steamdeck-built ] && command -v fc-cache >/dev/
fi
# The menu's "Steam" / "Steam Big Picture" entries and one entry per installed game: all of them
# hand off to the app (bannerlator-steam-launch), since the client cannot draw on this desktop.
export BL_DESKTOP=1
ln -sf /usr/local/bin/bannerlator-steam-launch /usr/local/bin/steamdeck-steam 2>/dev/null
ln -sf /usr/local/bin/bannerlator-steam-shim /usr/local/bin/steam 2>/dev/null
python3 /usr/local/bin/bannerlator-desktop-games 2>&1 | sed 's/^/[games] /'
echo "== steamdeck-desktop: labwc ($WLR_RENDERER) on $WAYLAND_DISPLAY"
@@ -1,7 +1,8 @@
#!/usr/bin/python3
# The client's installed games, on the desktop: one menu entry per game (Games category), which
# starts it through bannerlator-steam-launch in Steam's desktop UI under gamescope, and two links
# in the home folder to the game files themselves. Run at every desktop start; stale entries go.
# The client's installed games, on the desktop. The client writes a menu entry per game itself
# (`steam steam://rungameid/<id>`, with the game's icon), which the desktop's `steam` shim hands to
# the app - so an entry of ours exists only for a game the client wrote none for. Plus two links in
# the home folder to the game files. Run at every desktop start; stale entries go.
#
# bannerlator-desktop-games [steam root]
import os
@@ -54,12 +55,32 @@ def icon_for(appid):
return "steam"
def client_entries():
"""App ids the client already wrote a menu entry for."""
found = set()
if not os.path.isdir(APPS_DIR):
return found
for entry in os.listdir(APPS_DIR):
if entry.startswith(PREFIX) or not entry.endswith(".desktop"):
continue
try:
with open(os.path.join(APPS_DIR, entry), encoding="utf-8", errors="replace") as f:
m = re.search(r"steam://rungameid/(\d+)", f.read())
except OSError:
continue
if m:
found.add(int(m.group(1)))
return found
def write_entries():
os.makedirs(APPS_DIR, exist_ok=True)
wanted = {}
theirs = client_entries()
for library, _ in LIBRARIES:
for appid, name in games(library):
wanted.setdefault(appid, name)
if appid not in theirs:
wanted.setdefault(appid, name)
for entry in os.listdir(APPS_DIR):
if entry.startswith(PREFIX) and entry.endswith(".desktop"):
appid = entry[len(PREFIX):-len(".desktop")]
@@ -102,7 +123,8 @@ def link_libraries():
def main():
wanted = write_entries()
link_libraries()
print("bannerlator-desktop-games: %d game(s) on the desktop menu" % len(wanted))
print("bannerlator-desktop-games: %d entr%s of ours, %d the client's" % (
len(wanted), "y" if len(wanted) == 1 else "ies", len(client_entries())))
if __name__ == "__main__":
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# `steam` on the desktop. The client writes a menu entry per installed game that runs
# `steam steam://rungameid/<id>`, and its own launchers say `steam`; neither can run the client
# here (no dma-buf on the desktop), so on the desktop this hands off to the app for a Steam session
# in the client's desktop UI under gamescope. Anywhere else it is the client itself.
set -u
if [ "${BL_DESKTOP:-}" = 1 ]; then
url=
for arg in "$@"; do case $arg in steam://*) url=$arg ;; esac; done
exec /usr/local/bin/bannerlator-steam-launch desktop ${url:+"$url"}
fi
exec "${HOME:-/root}/.local/share/Steam/steamrtarm64/steam" "$@"