136 lines
3.9 KiB
Bash
Executable File
136 lines
3.9 KiB
Bash
Executable File
#!/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'
|