Skip to content

Instantly share code, notes, and snippets.

@KokoseiJ
Last active February 19, 2022 06:44
Show Gist options
  • Save KokoseiJ/c23e325e24b77fd4ad7817ff81377938 to your computer and use it in GitHub Desktop.
Save KokoseiJ/c23e325e24b77fd4ad7817ff81377938 to your computer and use it in GitHub Desktop.
Simple Proton wrapper written in Pyrhon
#!/usr/bin/env python3
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
import os
import sys
import subprocess
def pton(path):
return path.rsplit("/", 1)[-1]
def execute(path):
if not os.path.exists(path):
messagebox.showerror(message=f"File `{path}` doesn't exist!")
return
name = pton(path)
args = proton_argv + [path]
proc = subprocess.Popen(args)
running_window = Toplevel(root)
running_window.title(f"Running {name}")
running_window.resizable(False, False)
wintextframe = ttk.Frame(running_window, padding=10)
wintextframe.grid(column=0, row=0)
winbuttonframe = ttk.Frame(running_window, padding=10)
winbuttonframe.grid(column=0, row=1)
ttk.Label(wintextframe, text=f"Running {name}...").grid(column=0, row=0)
ttk.Button(winbuttonframe, text="Kill", command=proc.kill).grid(column=0, row=0)
root.after(1000, check_proc, proc, running_window)
def check_proc(proc, running_window):
if not Toplevel.winfo_exists(running_window):
return
if proc.poll() is not None:
running_window.destroy()
return
root.after(1000, check_proc, proc, running_window)
def execute_modorganizer():
if mo2_path is None:
messagebox.showerror(message="Environment variable MO2_PATH is not set!\nIn order to use MO2, please install MO2 and set the environment variable to a correct folder.")
else:
execute(mo2_path)
def execute_game():
execute(exepath)
def execute_file():
filename = filedialog.askopenfilename()
if filename:
execute(filename)
def show_list(title, arr):
list_window = Toplevel(root)
list_window.title(title)
listvar = StringVar(value=arr)
listbox = Listbox(list_window, height=10, listvariable=listvar)
listbox.pack(fill="both", expand=True, side="left")
scroll = ttk.Scrollbar(list_window, orient=VERTICAL, command=listbox.yview)
scroll.pack(fill="y", side="right")
listbox.configure(yscrollcommand=scroll.set)
list_window.grid_columnconfigure(1, weight=1)
list_window.grid_rowconfigure(1, weight=1)
def mo2_xdgregister():
if not os.path.exists(mo2_path):
messagebox.showerror(message="Incorrect MO2_PATH!")
return
PATH = os.path.dirname(os.path.abspath(__file__))
nxmpath = os.path.join(PATH, "nxmhandler")
with open(nxmpath, "w") as f:
f.write(f"STEAM_COMPAT_DATA_PATH={os.environ.get('STEAM_COMPAT_DATA_PATH')} {' '.join(proton_argv[-2:])} {mo2_path.replace('ModOrganizer.exe', 'nxmhandler.exe')} \"$1\"")
subprocess.run(["chmod", "+x", nxmpath])
with open(os.path.expanduser("~/.local/share/applications/nxm.desktop"), "w") as f:
f.write(f"""\
[Desktop Entry]
Type=Application
Name=NXM Handler
Exec={nxmpath} %u
Terminal=false
MimeType=x-scheme-handler/nxm;
""")
subprocess.run(["xdg-mime", "default", "nxm.desktop", "x-scheme-handler/nxm"])
root = Tk()
root.title("Skyrim Wrapper")
root.resizable(False, False)
textframe = ttk.Frame(root, padding=10)
textframe.grid(column=0, row=0)
infoframe = ttk.Frame(root, padding=10)
infoframe.grid(column=0, row=1, sticky=S)
frame = ttk.Frame(root, padding=10)
frame.grid(column=0, row=2, sticky=S)
argv = sys.argv[1:]
proton_argv = argv[:-1]
proton_argv[-1] = "run"
exepath = argv[-1]
envstr = [f"{x}: {y}" for x, y in os.environ.items()]
mo2_path = os.environ.get("MO2_PATH")
ttk.Label(textframe, text=f"Executable: `{pton(exepath)}`").grid(column=0, row=0)
ttk.Button(infoframe, text="Show argv", command=lambda: show_list("Proton argv", argv)).grid(column=0, row=0)
ttk.Button(infoframe, text="Show environment variables", command=lambda: show_list("Environment Variables", envstr)).grid(column=1, row=0)
ttk.Button(frame, text="Open MO2", command=execute_modorganizer, padding=5).grid(column=0, row=0)
ttk.Button(frame, text="XDG Register (Browser integration)", command=mo2_xdgregister, padding=5).grid(column=0, row=1)
ttk.Button(frame, text="Boot Game (BYPASSES MO2!)", command=execute_game, padding=5).grid(column=0, row=2)
ttk.Button(frame, text="Run file", command=execute_file, padding=5).grid(column=0, row=3)
ttk.Button(frame, text="Quit", command=root.destroy, padding=5).grid(column=0, row=4)
root.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment