sonic2kk / steamtinkerlaunch

Linux wrapper tool for use with the Steam client for custom launch options and 3rd party programs
GNU General Public License v3.0
2.05k stars 70 forks source link

GameScope: Use `-wA1` in getGameScopeArg to avoid overlap when switches and flags start with the same letter #1027

Closed sonic2kk closed 5 months ago

sonic2kk commented 5 months ago

Overview

This PR fixes getGameScopeArg by making sure when we match a flag, we match using -w, so that switches and flags starting with the same letter or having a similar pattern are not matched incorrectly, i.e. make sure -r and --rt are matched separately. This also includes cases where the switch might appear in another word, for example --enable-hdr might match -h.

Problem

We use setGameScopeVars to parse the GAMESCOPE_ARGS string. This will pull out a 1/0 for checkbox values if the flag exists (e.g. return 1 to enable the fullscreen checkbox if -f is present in the string). It can also be used to pull out values for flags that have parameters, such as 2 in --fsr-sharpness 2.

However, there was an oversight. When greping, in one place for getting the width/height, we use -wA1 to get the value, but in getGameScopeArg which mirrors a lot of that logic, we don't use -w. The -w ensures we match whole words, i.e. make sure -r and --rt are not treated as the same! This oversight led to us potentially matching, for example, the Realtime Scheduling checkbox switch --rt as having an argument when really it should control a checkbox, because grep assumes that it's the same as -r which is a flag for the focused game framerate limit!

If --rt was at the end of the string, when trying to get the value for -r, it meant it would think -- was its value if --rt was enabled. The GAMESCOPE_ARGS are not being parsed correctly!

Solution

The solution seems to work as simply as just using -w in grep -wA1. This will need more testing though!

The following debug code should demonstrate the impact of this change:

function getGameScopeArg {
    ARGS="$1"  # e.g. "$GAMESCOPE_ARGS"
    UNESCAPED_FLAG="$2"
    FLAG="${2//-/\\-}"  # e.g. "--hdr-enabled" becomes "\-\-hdr\-enabled"
    VAR="$3"  # e.g. "$GSHDR"
    TRUEVAL="$4"  # e.g. "1" (on UI)
    DEFVAL="$5"  # e.g. "0" (on UI)
    ARGTYPE="${6,,}"  # e.g. "chk", "cb", etc (matches Yad widget types mostly)

    # Set values for undefined arguments
    if [ -z "$VAR" ]; then
        if grep -qw "$FLAG" <<< "$ARGS"; then
            if [[ $ARGTYPE =~ "cb" ]] || [[ $ARGTYPE =~ "num" ]]; then
                # Get the value given to the argument as the enabled/selected value, e.g. get '2' from '-U 2' if we passed '-U'
                tr ' ' '\n' <<< "$ARGS" | grep -A1 "$FLAG" | tail -n1
            elif [[ $ARGTYPE =~ "path" ]] || [[ $ARGTYPE =~ "txt" ]]; then
                # Get value given to arguments with two dashes, like `--`
                echo "$ARGS" | sed 's:--:\n--:g' | grep -A1 "$FLAG" | sed "s:${UNESCAPED_FLAG}::g;s:-:\n-:g" | head -n1 | xargs
            else
                echo "$TRUEVAL"
            fi
        else
            echo "$DEFVAL"
        fi
    fi
}

GAMESCOPE_ARGS="-w 1920 -h 1080 -W 3840 -H 2160 -r 144 -f -e --force-grab-cursor --rt --"
getGameScopeArg "$GAMESCOPE_ARGS" "--rt" "$GSRT" "1" "0"
getGameScopeArg "$GAMESCOPE_ARGS" "-r" "$GSFLR" "" "$UL" "cb"

Before this PR:

After this PR:

sonic2kk commented 5 months ago

This seems safe to merge. Just needs ShellCheck + version bump.