#!/usr/bin/env python3 """ft-steam: Steam's menu and checks, through Steam's own UI (steamui.py). ft-steam menu open the SteamVR dashboard on Steam's menu, or close the dashboard if it's open (the Steam button's job, as a shortcut: the input relay's steam_menu) ft-steam check do Steam's UI calls that the above needs still exist (update-check.py) No pointer mode needed: it asks Steam to show its dashboard overlay (window.ShowVROverlay, what Steam itself calls) and to focus the Steam frame's left menu (MenuStore.OpenMainMenu, which in VR invokes the frame's focus_left_frame_menu_action). SteamClient.OpenVR.VROverlay says whether the dashboard is up and hides it. These are Steam's UI internals, not an API, so a Steam client update can rename them: `ft-steam check` says so. """ import os import sys sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) from steamui import SteamUnreachable, evaluate # noqa: E402 WINDOW = "SteamUIStore.WindowStore.VRGamepadUIMainWindowInstance" MENU = f"""(async () => {{ const vr = SteamClient.OpenVR.VROverlay; if (await vr.IsDashboardVisible()) {{ vr.HideDashboard(); return "closed"; }} const w = {WINDOW}; if (!w) throw new Error("Steam's VR dashboard window isn't open"); ShowVROverlay(w.GetVROverlayKey()); // The frame's menu takes focus only once the dashboard is up. for (let i = 0; i < 40 && !(await vr.IsDashboardVisible()); i++) await new Promise(r => setTimeout(r, 25)); w.MenuStore.OpenMainMenu(); return "opened"; }})()""" CHECK = f"""(() => {{ const missing = []; const vr = SteamClient.OpenVR && SteamClient.OpenVR.VROverlay; for (const f of ["IsDashboardVisible", "HideDashboard"]) if (!vr || typeof vr[f] !== "function") missing.push("SteamClient.OpenVR.VROverlay." + f); if (typeof window.ShowVROverlay !== "function") missing.push("ShowVROverlay"); const w = {WINDOW}; if (!w) missing.push("{WINDOW}"); else {{ if (typeof w.GetVROverlayKey !== "function") missing.push("GetVROverlayKey"); if (!w.MenuStore || typeof w.MenuStore.OpenMainMenu !== "function") missing.push("MenuStore.OpenMainMenu"); }} return missing; }})()""" def main(): cmd = sys.argv[1] if len(sys.argv) == 2 else "" if cmd not in ("menu", "check"): sys.exit(__doc__) try: result = evaluate(MENU if cmd == "menu" else CHECK) except SteamUnreachable as e: sys.exit(f"ft-steam: {e}") if cmd == "check": if result: sys.exit("Steam's UI lacks " + ", ".join(result)) print("ok") else: print(result) if __name__ == "__main__": main()