123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- #!/usr/bin/env zsh
- setopt rcquotes
- # eprintf <format> [args...]
- function eprintf {
- printf "${@}" >&2
- }
- # die <format> [args...]
- function die {
- eprintf '\e[91mfatal\e[m: '"${1}\n" "${(@)@:2}"
- exit 1
- }
- # print_help <argv[0]>
- function print_help {
- local exec_name="$(basename "${1}")"
- printf 'usage: %s [OPTIONS...] <GAME> [ARGS...]\n' "${exec_name}"
- printf 'Run a game inside an Xwayland session with a window manager. This\n'
- printf 'is very similar to gamescope, except that there is a window\n'
- printf 'involved. The default window manager is OpenBox.\n'
- printf '\n'
- printf ' -h Print this message, then exit.\n'
- printf ' -w Specify the window manager to use. This argument to this option will be\n'
- printf ' passed to "sh -c".\n'
- printf ' -r Specify the resolution of the Xwayland display. This should in the form\n'
- printf ' of ''WxH''. By default, the resolution of the currently focused output\n'
- printf ' will be used.\n'
- printf ' -d Specify the current desktop environment (or standalone Wayland\n'
- printf ' compositor). This is used if -r is not specified to find the resolution.\n'
- exit 0
- }
- # get_current_desktop
- function get_current_desktop {
- [[ -z "${XDG_CURRENT_DESKTOP}" ]] &&
- die 'set $XDG_CURRENT_DESKTOP or pass -d top specify desktop'
- eprintf 'Detected desktop: "%s"\n' "${XDG_CURRENT_DESKTOP}"
- printf '%s' "${XDG_CURRENT_DESKTOP}"
- }
- # get_default_resolution [desktop]
- function get_default_resolution {
- case "${1}" in
- 'river')
- local output="$(ristate -o |
- jq -r '.outputs | keys.[] as $names |
- {output: $names, focused: .[$names].focused} |
- select(.focused) | .output')"
- eprintf 'Detected output: %s\n' "${output}"
- local resolution="$(wlr-randr --json |
- jq -r --arg output "${output}" \
- '.[] | select(.name == $output).modes.[] |
- select(.current) | "\(.width)x\(.height)"')"
- ;;
- *)
- die 'unknown desktop session: "%s"' "${1}"
- ;;
- esac
- eprintf 'Detected resolution: %s\n' "${resolution}"
- printf '%s\n' "${resolution}"
- }
- while getopts ':hw:r:d:' OPTOPT; do
- case "${OPTOPT}" in
- 'h')
- print_help "${0}"
- ;;
- 'w')
- window_manager="${OPTARG}"
- ;;
- 'r')
- resolution="${OPTARG}"
- ;;
- 'd')
- current_desktop="${OPTARG}"
- ;;
- ':')
- die 'option requires an argument: %s' "${OPTARG}"
- ;;
- '?')
- die 'unknown option: %s' "${OPTARG}"
- ;;
- esac
- done
- (( "${OPTIND}" > ${#} )) && print_help "${0}"
- shift $(( "${OPTIND}" - 1))
- function {
- emulate -L zsh
- setopt errexit
- [[ -v window_manager ]] ||
- window_manager='openbox'
- [[ -v current_desktop ]] ||
- current_desktop="$(get_current_desktop 2>&3)"
- [[ -v resolution ]] ||
- resolution="$(get_default_resolution "${current_desktop}" 2>&3)"
- } 3>&2
- function on_sigchld {
- eprintf 'Xwayland or window manager died! Exiting...\n'
- kill %sh %Xwayland 2>/dev/null
- wait ${cat_pid}
- exit 1
- }
- trap on_sigchld CHLD
- coproc Xwayland -fullscreen -geometry "${resolution}" -displayfd 1
- local xwayland_display
- read <&p xwayland_display
- export DISPLAY=":${xwayland_display}"
- unset WAYLAND_DISPLAY
- eprintf 'Xwayland display: %s\n' "${DISPLAY}"
- cat <&p >&2
- let cat_pid="${!}"
- sh -c "exec -- ${window_manager}" &
- function {
- emulate -L sh
- eval "${@}"
- } "${@}"
- let child_error_code="${?}"
- if (( ${child_error_code} )); then
- printf 'Child exited with error code %d\n' "${child_error_code}"
- fi
- trap -
- kill %sh %Xwayland
- wait "${cat_pid}"
- eprintf 'Child died! Exiting...\n'
|