Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- { config, pkgs, lib, ... }:
- let
- homeDir = config.home.homeDirectory;
- in
- {
- # --- umu-run-game: run a Windows .exe with UMU/Proton ---
- home.file.".local/bin/umu-run-game" = {
- executable = true;
- text = ''
- #!/usr/bin/env bash
- GAME_DIR="$(dirname "$1")"
- GAME_NAME="$(basename "$GAME_DIR" | tr " " "-" | tr "[:upper:]" "[:lower:]")"
- export GAMEID=0
- export WINEPREFIX="$HOME/Games/umu/$GAME_NAME"
- mkdir -p "$WINEPREFIX"
- exec umu-run "$1"
- '';
- };
- # --- KDE right-click: "Run with UMU (Proton)" ---
- home.file.".local/share/kio/servicemenus/umu-run.desktop" = {
- executable = true;
- text = ''
- [Desktop Entry]
- Type=Service
- MimeType=application/x-ms-dos-executable;application/x-msdos-program;application/x-executable-wine;
- X-KDE-ServiceTypes=KonqPopupMenu/Plugin
- Actions=umu-run
- [Desktop Action umu-run]
- Name=Run with UMU (Proton)
- Icon=wine
- Exec=${homeDir}/.local/bin/umu-run-game %f
- '';
- };
- # --- Double-click .exe association ---
- xdg.desktopEntries.umu-run-game = {
- name = "UMU (Proton)";
- icon = "wine";
- exec = "${homeDir}/.local/bin/umu-run-game %f";
- mimeType = [
- "application/x-ms-dos-executable"
- "application/x-msdos-program"
- ];
- noDisplay = true;
- };
- # --- umu-lnk-parse: extract target .exe from Windows .lnk files ---
- home.file.".local/bin/umu-lnk-parse" = {
- executable = true;
- text = ''
- #!/usr/bin/env bash
- set -euo pipefail
- extract_exe_from_lnk() {
- local lnk="$1"
- local path
- path=$(${pkgs.exiftool}/bin/exiftool -s3 -LocalBasePath "$lnk" 2>/dev/null)
- if [[ -n "$path" ]] && echo "$path" | grep -qi '\.exe$'; then
- echo "$path"
- fi
- }
- TARGET="$1"
- if [[ -f "$TARGET" ]]; then
- extract_exe_from_lnk "$TARGET"
- exit $?
- fi
- # Directory mode: scan prefix for .lnk files
- shopt -s globstar nullglob
- declare -A FOUND
- declare -A FOUND_LNK
- for lnk in \
- "$TARGET"/drive_c/ProgramData/Microsoft/Windows/Start\ Menu/**/*.lnk \
- "$TARGET"/drive_c/users/*/AppData/Roaming/Microsoft/Windows/Start\ Menu/**/*.lnk \
- "$TARGET"/drive_c/users/*/Desktop/*.lnk; do
- exe_path=$(extract_exe_from_lnk "$lnk")
- [[ -z "$exe_path" ]] && continue
- name=$(basename "$lnk" .lnk)
- name_lower=$(echo "$name" | tr '[:upper:]' '[:lower:]')
- case "$name_lower" in
- *uninstall*|*remove*|*uninst*) continue ;;
- esac
- FOUND_LNK["$name"]="$lnk"
- FOUND["$name"]="$exe_path"
- done
- while IFS= read -r -d $'\0' name; do
- printf '%s\t%s\t%s\n' "$name" "''${FOUND[$name]}" "''${FOUND_LNK[$name]}"
- done < <(printf '%s\0' "''${!FOUND[@]}" | sort -z)
- '';
- };
- # --- umu-create-launcher: create a .desktop file for a Windows app ---
- home.file.".local/bin/umu-create-launcher" = {
- executable = true;
- text = ''
- #!/usr/bin/env bash
- set -euo pipefail
- NAME="$1"
- WIN_EXE="$2"
- PREFIX="$3"
- LNK_FILE="''${4:-}"
- SAFE_NAME=$(echo "$NAME" | tr ' ' '-' | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9_-]//g')
- DESKTOP_FILE="$HOME/.local/share/applications/umu-''${SAFE_NAME}.desktop"
- ICON_DIR="$HOME/.local/share/icons/umu"
- LAUNCHER_DIR="$HOME/.local/bin/umu-launchers"
- mkdir -p "$ICON_DIR" "$LAUNCHER_DIR"
- # Convert Windows path to Unix path inside prefix
- UNIX_REL=$(echo "$WIN_EXE" | sed 's|\\|/|g' | sed 's|^[A-Za-z]:/||')
- UNIX_EXE="$PREFIX/drive_c/$UNIX_REL"
- PREFIX_NAME=$(basename "$PREFIX")
- ICON_PATH="wine"
- # --- Icon extraction ---
- extract_icon() {
- local source="$1"
- local out="$ICON_DIR/''${SAFE_NAME}.png"
- local tmpdir
- tmpdir=$(mktemp -d /tmp/umu-ico-XXXXXX)
- if [[ "$source" == *.ico ]]; then
- if ${pkgs.icoutils}/bin/icotool -x -o "$tmpdir" "$source" 2>/dev/null; then
- BEST=$(ls -S "$tmpdir"/*.png 2>/dev/null | head -1 || true)
- if [[ -n "$BEST" ]] && [[ -f "$BEST" ]]; then
- mv "$BEST" "$out"
- rm -rf "$tmpdir"
- echo "$out"
- return 0
- fi
- fi
- elif [[ "$source" == *.exe ]]; then
- local tmpico="$tmpdir/extracted.ico"
- if ${pkgs.icoutils}/bin/wrestool -x -t 14 -o "$tmpico" "$source" 2>/dev/null && [[ -s "$tmpico" ]]; then
- if ${pkgs.icoutils}/bin/icotool -x -o "$tmpdir" "$tmpico" 2>/dev/null; then
- BEST=$(ls -S "$tmpdir"/*.png 2>/dev/null | head -1 || true)
- if [[ -n "$BEST" ]] && [[ -f "$BEST" ]]; then
- mv "$BEST" "$out"
- rm -rf "$tmpdir"
- echo "$out"
- return 0
- fi
- fi
- fi
- fi
- rm -rf "$tmpdir"
- return 1
- }
- # Strategy 1: .ico referenced in the .lnk
- if [[ -n "$LNK_FILE" ]] && [[ -f "$LNK_FILE" ]]; then
- ICO_WIN=$(${pkgs.exiftool}/bin/exiftool -s3 -IconFileName "$LNK_FILE" 2>/dev/null || true)
- if [[ -n "$ICO_WIN" ]]; then
- ICO_REL=$(echo "$ICO_WIN" | sed 's|\\|/|g' | sed 's|^[A-Za-z]:/||')
- ICO_UNIX="$PREFIX/drive_c/$ICO_REL"
- if [[ -f "$ICO_UNIX" ]]; then
- RESULT=$(extract_icon "$ICO_UNIX") && ICON_PATH="$RESULT"
- fi
- fi
- fi
- # Strategy 2: .ico next to the .exe
- if [[ "$ICON_PATH" == "wine" ]] && [[ -f "$UNIX_EXE" ]]; then
- EXE_DIR=$(dirname "$UNIX_EXE")
- ICO_FILE=$(find "$EXE_DIR" -maxdepth 1 -iname '*.ico' -print -quit 2>/dev/null || true)
- if [[ -n "$ICO_FILE" ]]; then
- RESULT=$(extract_icon "$ICO_FILE") && ICON_PATH="$RESULT"
- fi
- fi
- # Strategy 3: extract from .exe
- if [[ "$ICON_PATH" == "wine" ]] && [[ -f "$UNIX_EXE" ]]; then
- RESULT=$(extract_icon "$UNIX_EXE") && ICON_PATH="$RESULT"
- fi
- # Strategy 4: try GOG icon search
- if [[ "$ICON_PATH" == "wine" ]]; then
- SEARCH_NAME=$(echo "$NAME" | sed 's/[^a-zA-Z0-9 ]//g' | sed 's/ /+/g')
- DL_ICON="$ICON_DIR/''${SAFE_NAME}.png"
- GOG_ICON=$(${pkgs.curl}/bin/curl -sf -L \
- "https://api.gog.com/products?search=$SEARCH_NAME&limit=1" 2>/dev/null \
- | ${pkgs.jq}/bin/jq -r '.products[0].images.icon // empty' 2>/dev/null || true)
- if [[ -n "$GOG_ICON" ]]; then
- ${pkgs.curl}/bin/curl -sf -L -o "$DL_ICON" "https:$GOG_ICON" 2>/dev/null \
- && [[ -s "$DL_ICON" ]] && ICON_PATH="$DL_ICON"
- fi
- fi
- # --- Create a wrapper script ---
- LAUNCHER="$LAUNCHER_DIR/$SAFE_NAME"
- cat > "$LAUNCHER" <<'SCRIPT_HEAD'
- #!/usr/bin/env bash
- SCRIPT_HEAD
- cat >> "$LAUNCHER" <<SCRIPT_BODY
- export GAMEID=0
- export WINEPREFIX="$PREFIX"
- exec ${pkgs.umu-launcher}/bin/umu-run "$UNIX_EXE"
- SCRIPT_BODY
- sed -i 's/^ //' "$LAUNCHER"
- chmod +x "$LAUNCHER"
- # --- Create .desktop pointing to the wrapper ---
- cat > "$DESKTOP_FILE" <<DESKTOP
- [Desktop Entry]
- Type=Application
- Name=$NAME
- Comment=Windows app (UMU/Proton) — prefix: $PREFIX_NAME
- Exec=$LAUNCHER
- Icon=$ICON_PATH
- Terminal=false
- Categories=Game;
- Keywords=windows;wine;proton;umu;
- DESKTOP
- sed -i 's/^ //' "$DESKTOP_FILE"
- echo "$DESKTOP_FILE"
- '';
- };
- # --- umu-scan: scan prefix(es) for installed programs, create launchers ---
- home.file.".local/bin/umu-scan" = {
- executable = true;
- text = ''
- #!/usr/bin/env bash
- set -euo pipefail
- UMU_DIR="$HOME/Games/umu"
- if [[ ! -d "$UMU_DIR" ]]; then
- ${pkgs.kdePackages.kdialog}/bin/kdialog --sorry "No prefixes found in $UMU_DIR" --title "UMU Scan"
- exit 0
- fi
- # Use indexed arrays to avoid space/quoting issues
- NAMES=()
- EXES=()
- LNKS=()
- PREFIXES=()
- CHECKLIST_ARGS=()
- for PREFIX in "$UMU_DIR"/*/; do
- [[ -d "$PREFIX/drive_c" ]] || continue
- PREFIX_NAME=$(basename "$PREFIX")
- while IFS=$'\t' read -r name exe_path lnk_path; do
- [[ -z "$name" ]] && continue
- IDX=''${#NAMES[@]}
- NAMES+=("$name")
- EXES+=("$exe_path")
- LNKS+=("$lnk_path")
- PREFIXES+=("$PREFIX")
- CHECKLIST_ARGS+=("$IDX" "$name ($PREFIX_NAME)" "off")
- done < <("$HOME/.local/bin/umu-lnk-parse" "$PREFIX" 2>/dev/null || true)
- done
- if [[ ''${#NAMES[@]} -eq 0 ]]; then
- ${pkgs.kdePackages.kdialog}/bin/kdialog \
- --sorry "No installed programs found in any prefix." \
- --title "UMU Scan"
- exit 0
- fi
- SELECTED=$(${pkgs.kdePackages.kdialog}/bin/kdialog \
- --checklist "Select programs to create launchers for:" \
- "''${CHECKLIST_ARGS[@]}" \
- --title "UMU — Installed Programs" \
- --geometry 600x400) || exit 0
- COUNT=0
- for IDX in $SELECTED; do
- IDX=$(echo "$IDX" | tr -d '"')
- "$HOME/.local/bin/umu-create-launcher" \
- "''${NAMES[$IDX]}" "''${EXES[$IDX]}" "''${PREFIXES[$IDX]}" "''${LNKS[$IDX]}"
- COUNT=$((COUNT + 1))
- done
- ${pkgs.kdePackages.kdialog}/bin/kdialog \
- --passivepopup "Created $COUNT launcher(s). Check your app menu!" 5 \
- --title "UMU Scan Complete"
- '';
- };
- # --- umu-install: run a setup.exe, then scan for installed programs ---
- home.file.".local/bin/umu-install" = {
- executable = true;
- text = ''
- #!/usr/bin/env bash
- set -euo pipefail
- SETUP_EXE="$1"
- GAME_DIR="$(dirname "$SETUP_EXE")"
- GAME_NAME="$(basename "$GAME_DIR" | tr " " "-" | tr "[:upper:]" "[:lower:]")"
- GAME_NAME=$(${pkgs.kdePackages.kdialog}/bin/kdialog \
- --inputbox "Prefix name for this installation:" "$GAME_NAME" \
- --title "UMU Install") || exit 0
- export GAMEID=0
- export WINEPREFIX="$HOME/Games/umu/$GAME_NAME"
- mkdir -p "$WINEPREFIX"
- ${pkgs.kdePackages.kdialog}/bin/kdialog \
- --passivepopup "Starting installer in prefix: $GAME_NAME" 5 \
- --title "UMU Install" &
- umu-run "$SETUP_EXE"
- sleep 1
- NAMES=()
- EXES=()
- LNKS=()
- CHECKLIST_ARGS=()
- while IFS=$'\t' read -r name exe_path lnk_path; do
- [[ -z "$name" ]] && continue
- IDX=''${#NAMES[@]}
- NAMES+=("$name")
- EXES+=("$exe_path")
- LNKS+=("$lnk_path")
- CHECKLIST_ARGS+=("$IDX" "$name" "on")
- done < <("$HOME/.local/bin/umu-lnk-parse" "$WINEPREFIX" 2>/dev/null || true)
- if [[ ''${#NAMES[@]} -eq 0 ]]; then
- ${pkgs.kdePackages.kdialog}/bin/kdialog \
- --msgbox "Installation finished.\nNo shortcuts detected — browse:\n$WINEPREFIX/drive_c/" \
- --title "UMU Install"
- exit 0
- fi
- SELECTED=$(${pkgs.kdePackages.kdialog}/bin/kdialog \
- --checklist "Installation finished! Create launchers for:" \
- "''${CHECKLIST_ARGS[@]}" \
- --title "UMU — Create Launchers" \
- --geometry 500x350) || exit 0
- COUNT=0
- for IDX in $SELECTED; do
- IDX=$(echo "$IDX" | tr -d '"')
- "$HOME/.local/bin/umu-create-launcher" \
- "''${NAMES[$IDX]}" "''${EXES[$IDX]}" "$WINEPREFIX" "''${LNKS[$IDX]}"
- COUNT=$((COUNT + 1))
- done
- ${pkgs.kdePackages.kdialog}/bin/kdialog \
- --passivepopup "Created $COUNT launcher(s) — check your app menu!" 5 \
- --title "UMU Install Complete"
- '';
- };
- # --- KDE right-click: "Install with UMU (Proton)" ---
- home.file.".local/share/kio/servicemenus/umu-install.desktop" = {
- text = ''
- [Desktop Entry]
- Type=Service
- MimeType=application/x-ms-dos-executable;application/x-msdos-program;
- X-KDE-ServiceTypes=KonqPopupMenu/Plugin
- Actions=umu-install
- [Desktop Action umu-install]
- Name=Install with UMU (Proton)
- Icon=package-x-generic
- Exec=${homeDir}/.local/bin/umu-install %f
- '';
- };
- # --- Desktop entry for umu-scan (app menu) ---
- xdg.desktopEntries.umu-scan = {
- name = "UMU — Scan Installed Apps";
- comment = "Find installed Windows programs and create launchers";
- icon = "system-search";
- exec = "${homeDir}/.local/bin/umu-scan";
- terminal = false;
- categories = [ "Utility" ];
- };
- # --- Mime associations ---
- xdg.mimeApps = {
- enable = true;
- defaultApplications = {
- "application/x-ms-dos-executable" = "umu-run-game.desktop";
- "application/x-msdos-program" = "umu-run-game.desktop";
- };
- };
- }
Advertisement