Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -440,16 +440,19 @@ VM_NAME="RDPWindows"
# - 'manual'
WAFLAVOR="docker"

# [DISPLAY SCALING FACTOR]
# [DISPLAY SCALING FACTORS]
# NOTES:
# - If an unsupported value is specified, a warning will be displayed.
# - If an unsupported value is specified, WinApps will use the closest supported value.
# DEFAULT VALUE: '100'
# - RDP_SCALE sets RemoteApp scaling. RDP_DESKTOP_SCALE sets scaling for 'winapps windows'.
# - Values outside 100-500 are set to the nearest limit. Non-integer scales stop the launch.
# - WinApps keeps the exact scale and rounds the device scale, used by MS Store (UWP) apps, to the nearest 100, 140 or 180.
# DEFAULT VALUES:
# - RDP_SCALE: '100'
# - RDP_DESKTOP_SCALE: 'inherit' (use RDP_SCALE)
# VALID VALUES:
# - '100'
# - '140'
# - '180'
# - Integers from '100' to '500'
# - 'inherit' for RDP_DESKTOP_SCALE
RDP_SCALE="100"
RDP_DESKTOP_SCALE="inherit"

# [MOUNTING REMOVABLE PATHS FOR FILES]
# NOTES:
Expand Down Expand Up @@ -571,7 +574,7 @@ HIDEF="on"
- If using a pre-existing Windows RDP server on your LAN, you must use `RDP_IP` to specify the location of the Windows server. You may also wish to configure a static IP address for this server.
- If running a Windows VM using `libvirt` with NAT enabled, leave `RDP_IP` commented out and WinApps will auto-detect the local IP address for the VM.
- For domain users, you can uncomment and change `RDP_DOMAIN`.
- On high-resolution (UHD) displays, you can set `RDP_SCALE` to the scale you would like to use (100, 140 or 180).
- On high-resolution (UHD) displays, set `RDP_SCALE` to a percentage from 100 to 500. Use `RDP_DESKTOP_SCALE` to set a different scale for `winapps windows`.
- To add additional flags to the FreeRDP call (e.g. `/prevent-session-lock 120`), uncomment and use the `RDP_FLAGS` configuration option.
- For multi-monitor setups, you can try adding `/multimon` to `RDP_FLAGS`. A FreeRDP bug may result in a black screen however, in which case you should revert this change.
- To enable non-English input and seamless language switching, you can try adding `/kbd:unicode` to `RDP_FLAGS`. This ensures client inputs are sent as Unicode sequences.
Expand Down
104 changes: 72 additions & 32 deletions bin/winapps
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ readonly EC_NO_IP=12
readonly EC_BAD_PORT=13
readonly EC_UNSUPPORTED_APP=14
readonly EC_INVALID_FLAVOR=15
readonly EC_INVALID_SCALE=16

# PATHS
readonly APPDATA_PATH="${HOME}/.local/share/winapps"
Expand Down Expand Up @@ -51,6 +52,10 @@ RDP_FLAGS=""
FREERDP_COMMAND=""
REMOVABLE_MEDIA=""
RDP_SCALE=100
RDP_DEVICE_SCALE=100
# Scale for 'winapps windows'; 'inherit' uses RDP_SCALE.
RDP_DESKTOP_SCALE="inherit"
RDP_DESKTOP_DEVICE_SCALE=100
AUTOPAUSE="off"
AUTOPAUSE_TIME="300"
DEBUG="true"
Expand Down Expand Up @@ -215,6 +220,8 @@ function waEarlyDispatch() {
function waThrowExit() {
# Declare variables.
local ERR_CODE="$1"
local INVALID_SCALE_KEY="${2:-RDP_SCALE}"
local INVALID_SCALE_VALUE="${3-$RDP_SCALE}"

# Throw error.
case "$ERR_CODE" in
Expand Down Expand Up @@ -282,6 +289,11 @@ Please run:
dprint "ERROR: INVALID FLAVOR. EXITING."
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --app-icon="$APP_ICON_PATH" --urgency="low" "WinApps" "Invalid WinApps flavor.\nPlease ensure 'docker', 'podman' or 'libvirt' are specified as the flavor in the WinApps configuration file."
;;
"$EC_INVALID_SCALE")
dprint "ERROR: ${INVALID_SCALE_KEY} MUST BE AN INTEGER. EXITING."
printf "ERROR: %s must be an integer; received '%s'.\n" "$INVALID_SCALE_KEY" "$INVALID_SCALE_VALUE" >&2
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --app-icon="$APP_ICON_PATH" --urgency="low" "WinApps" "Invalid ${INVALID_SCALE_KEY} value '${INVALID_SCALE_VALUE}'.\nPlease specify an integer value."
;;
esac

# Terminate the script.
Expand Down Expand Up @@ -329,37 +341,61 @@ function waHelp() {
}

# Name: 'waFixScale'
# Role: Since FreeRDP only supports '/scale' values of 100, 140 or 180, find the closest supported argument to the user's configuration.
# Role: Validate the scales and choose the nearest device scales.
function waFixScale() {
# Define variables.
local OLD_SCALE=100
local VALID_SCALE_1=100
local VALID_SCALE_2=140
local VALID_SCALE_3=180

# Check for an unsupported value.
if [ "$RDP_SCALE" != "$VALID_SCALE_1" ] && [ "$RDP_SCALE" != "$VALID_SCALE_2" ] && [ "$RDP_SCALE" != "$VALID_SCALE_3" ]; then
# Save the unsupported scale.
OLD_SCALE="$RDP_SCALE"

# Calculate the absolute differences.
local DIFF_1=$(( RDP_SCALE > VALID_SCALE_1 ? RDP_SCALE - VALID_SCALE_1 : VALID_SCALE_1 - RDP_SCALE ))
local DIFF_2=$(( RDP_SCALE > VALID_SCALE_2 ? RDP_SCALE - VALID_SCALE_2 : VALID_SCALE_2 - RDP_SCALE ))
local DIFF_3=$(( RDP_SCALE > VALID_SCALE_3 ? RDP_SCALE - VALID_SCALE_3 : VALID_SCALE_3 - RDP_SCALE ))

# Set the final scale to the valid scale value with the smallest absolute difference.
if (( DIFF_1 <= DIFF_2 && DIFF_1 <= DIFF_3 )); then
RDP_SCALE="$VALID_SCALE_1"
elif (( DIFF_2 <= DIFF_1 && DIFF_2 <= DIFF_3 )); then
RDP_SCALE="$VALID_SCALE_2"
local SCALE_KEY=""
local DEVICE_SCALE_KEY=""
local RAW_SCALE=""
local SCALE_DIGITS=""
local SCALE_VALUE=0
local DEVICE_SCALE=0

for SCALE_KEY in RDP_SCALE RDP_DESKTOP_SCALE; do
RAW_SCALE="${!SCALE_KEY}"
if [ "$SCALE_KEY" = "RDP_SCALE" ]; then
DEVICE_SCALE_KEY="RDP_DEVICE_SCALE"
else
RDP_SCALE="$VALID_SCALE_3"
DEVICE_SCALE_KEY="RDP_DESKTOP_DEVICE_SCALE"
if [ "$RAW_SCALE" = "inherit" ]; then
RAW_SCALE="$RDP_SCALE"
fi
fi

# Print feedback.
dprint "WARNING: Unsupported RDP_SCALE value '${OLD_SCALE}'. Defaulting to '${RDP_SCALE}'."
notify-send --expire-time=4000 --icon="dialog-warning" --app-name="WinApps" --app-icon="$APP_ICON_PATH" --urgency="low" "WinApps" "Unsupported RDP_SCALE value '${OLD_SCALE}'.\nDefaulting to '${RDP_SCALE}'."
fi
if [[ ! "$RAW_SCALE" =~ ^[+-]?[0-9]+$ ]]; then
waThrowExit "$EC_INVALID_SCALE" "$SCALE_KEY" "$RAW_SCALE"
fi

SCALE_DIGITS="${RAW_SCALE#[+-]}"
while [[ "$SCALE_DIGITS" == 0* ]] && [ "$SCALE_DIGITS" != "0" ]; do
SCALE_DIGITS="${SCALE_DIGITS#0}"
done

# Bound the value before arithmetic to avoid integer overflow.
if [[ "$RAW_SCALE" == -* ]]; then
SCALE_VALUE=0
elif (( ${#SCALE_DIGITS} > 3 )); then
SCALE_VALUE=501
else
SCALE_VALUE=$(( 10#$SCALE_DIGITS ))
fi

if (( SCALE_VALUE < 100 )); then
SCALE_VALUE=100
dprint "WARNING: ${SCALE_KEY} value '${RAW_SCALE}' is below 100. Clamping desktop scale to '${SCALE_VALUE}'."
elif (( SCALE_VALUE > 500 )); then
SCALE_VALUE=500
dprint "WARNING: ${SCALE_KEY} value '${RAW_SCALE}' is above 500. Clamping desktop scale to '${SCALE_VALUE}'."
fi

DEVICE_SCALE=$(( SCALE_VALUE <= 120 ? 100 : SCALE_VALUE <= 160 ? 140 : 180 ))
printf -v "$SCALE_KEY" '%s' "$SCALE_VALUE"
printf -v "$DEVICE_SCALE_KEY" '%s' "$DEVICE_SCALE"
if [ "$DEVICE_SCALE" != "$SCALE_VALUE" ]; then
dprint "NOTICE: Approximating the device scale for ${SCALE_KEY} from '${SCALE_VALUE}' to '${DEVICE_SCALE}'; desktop scale remains '${SCALE_VALUE}'."
fi
done

return 0
}

# Name: 'waLoadConfig'
Expand All @@ -375,7 +411,7 @@ function waLoadConfig() {

RDP_PORT="${RDP_PORT:-3389}"

# Update $RDP_SCALE.
# Resolve RemoteApp and full-desktop scale settings.
waFixScale
# Update when $REMOVABLE_MEDIA is null
waFixRemovableMedia
Expand Down Expand Up @@ -826,7 +862,8 @@ function waRunCommand() {
/d:"$RDP_DOMAIN" \
/u:"$RDP_USER" \
${RDP_PASSWORD_ARG:+"$RDP_PASSWORD_ARG"} \
/scale:"$RDP_SCALE" \
/scale-desktop:"$RDP_DESKTOP_SCALE" \
/scale-device:"$RDP_DESKTOP_DEVICE_SCALE" \
+auto-reconnect \
+dynamic-resolution \
/wm-class:"Microsoft Windows" \
Expand All @@ -844,7 +881,8 @@ function waRunCommand() {
/d:"$RDP_DOMAIN" \
/u:"$RDP_USER" \
${RDP_PASSWORD_ARG:+"$RDP_PASSWORD_ARG"} \
/scale:"$RDP_SCALE" \
/scale-desktop:"$RDP_SCALE" \
/scale-device:"$RDP_DEVICE_SCALE" \
+auto-reconnect \
/app:program:"$2",hidef:"$HIDEF" \
/v:"$RDP_IP":"$RDP_PORT" &>/dev/null &
Expand Down Expand Up @@ -878,7 +916,8 @@ function waRunCommand() {
/d:"$RDP_DOMAIN" \
/u:"$RDP_USER" \
${RDP_PASSWORD_ARG:+"$RDP_PASSWORD_ARG"} \
/scale:"$RDP_SCALE" \
/scale-desktop:"$RDP_SCALE" \
/scale-device:"$RDP_DEVICE_SCALE" \
+auto-reconnect \
/wm-class:"$FULL_NAME" \
/app:program:"$WIN_EXECUTABLE",hidef:"$HIDEF",icon:"$ICON",name:"$FULL_NAME" \
Expand All @@ -901,7 +940,8 @@ function waRunCommand() {
/d:"$RDP_DOMAIN" \
/u:"$RDP_USER" \
${RDP_PASSWORD_ARG:+"$RDP_PASSWORD_ARG"} \
/scale:"$RDP_SCALE" \
/scale-desktop:"$RDP_SCALE" \
/scale-device:"$RDP_DEVICE_SCALE" \
+auto-reconnect \
/drive:media,"$REMOVABLE_MEDIA" \
/wm-class:"$FULL_NAME" \
Expand Down
97 changes: 65 additions & 32 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ readonly EC_BAD_PORT="13" # Windows is unreachable via RDP_PORT.
readonly EC_RDP_FAIL="14" # FreeRDP failed to establish a connection with Windows.
readonly EC_APPQUERY_FAIL="15" # Failed to query Windows for installed applications.
readonly EC_INVALID_FLAVOR="16" # Backend specified is not 'libvirt', 'docker' or 'podman'.
readonly EC_INVALID_SCALE="17" # A display scale setting is invalid.

# PATHS
# 'BIN'
Expand Down Expand Up @@ -93,6 +94,10 @@ RDP_IP="" # Imported variable.
VM_NAME="RDPWindows" # Name of the Windows VM (FOR 'libvirt' ONLY).
WAFLAVOR="docker" # Imported variable.
RDP_SCALE=100 # Imported variable.
RDP_DEVICE_SCALE=100 # Derived from RDP_SCALE.
# Scale for 'winapps windows'; 'inherit' uses RDP_SCALE.
RDP_DESKTOP_SCALE="inherit"
RDP_DESKTOP_DEVICE_SCALE=100
RDP_FLAGS="" # Imported variable.
DEBUG="true" # Imported variable.
FREERDP_COMMAND="" # Imported variable.
Expand Down Expand Up @@ -501,36 +506,62 @@ function waCheckExistingInstall() {


# Name: 'waFixScale'
# Role: Since FreeRDP only supports '/scale' values of 100, 140 or 180, find the closest supported argument to the user's configuration.
# Role: Validate the scales and choose the nearest device scales.
function waFixScale() {
# Define variables.
local OLD_SCALE=100
local VALID_SCALE_1=100
local VALID_SCALE_2=140
local VALID_SCALE_3=180

# Check for an unsupported value.
if [ "$RDP_SCALE" != "$VALID_SCALE_1" ] && [ "$RDP_SCALE" != "$VALID_SCALE_2" ] && [ "$RDP_SCALE" != "$VALID_SCALE_3" ]; then
# Save the unsupported scale.
OLD_SCALE="$RDP_SCALE"

# Calculate the absolute differences.
local DIFF_1=$(( RDP_SCALE > VALID_SCALE_1 ? RDP_SCALE - VALID_SCALE_1 : VALID_SCALE_1 - RDP_SCALE ))
local DIFF_2=$(( RDP_SCALE > VALID_SCALE_2 ? RDP_SCALE - VALID_SCALE_2 : VALID_SCALE_2 - RDP_SCALE ))
local DIFF_3=$(( RDP_SCALE > VALID_SCALE_3 ? RDP_SCALE - VALID_SCALE_3 : VALID_SCALE_3 - RDP_SCALE ))

# Set the final scale to the valid scale value with the smallest absolute difference.
if (( DIFF_1 <= DIFF_2 && DIFF_1 <= DIFF_3 )); then
RDP_SCALE="$VALID_SCALE_1"
elif (( DIFF_2 <= DIFF_1 && DIFF_2 <= DIFF_3 )); then
RDP_SCALE="$VALID_SCALE_2"
local SCALE_KEY=""
local DEVICE_SCALE_KEY=""
local RAW_SCALE=""
local SCALE_DIGITS=""
local SCALE_VALUE=0
local DEVICE_SCALE=0

for SCALE_KEY in RDP_SCALE RDP_DESKTOP_SCALE; do
RAW_SCALE="${!SCALE_KEY}"
if [ "$SCALE_KEY" = "RDP_SCALE" ]; then
DEVICE_SCALE_KEY="RDP_DEVICE_SCALE"
else
RDP_SCALE="$VALID_SCALE_3"
DEVICE_SCALE_KEY="RDP_DESKTOP_DEVICE_SCALE"
if [ "$RAW_SCALE" = "inherit" ]; then
RAW_SCALE="$RDP_SCALE"
fi
fi

# Print feedback.
echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} Unsupported RDP_SCALE value '${OLD_SCALE}' detected. Defaulting to '${RDP_SCALE}'."
fi
if [[ ! "$RAW_SCALE" =~ ^[+-]?[0-9]+$ ]]; then
echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}${SCALE_KEY} must be an integer; received '${RAW_SCALE}'.${CLEAR_TEXT}"
return "$EC_INVALID_SCALE"
fi

SCALE_DIGITS="${RAW_SCALE#[+-]}"
while [[ "$SCALE_DIGITS" == 0* ]] && [ "$SCALE_DIGITS" != "0" ]; do
SCALE_DIGITS="${SCALE_DIGITS#0}"
done

# Bound the value before arithmetic to avoid integer overflow.
if [[ "$RAW_SCALE" == -* ]]; then
SCALE_VALUE=0
elif (( ${#SCALE_DIGITS} > 3 )); then
SCALE_VALUE=501
else
SCALE_VALUE=$(( 10#$SCALE_DIGITS ))
fi

if (( SCALE_VALUE < 100 )); then
SCALE_VALUE=100
echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} ${SCALE_KEY} value '${RAW_SCALE}' is below 100. Clamping desktop scale to '${SCALE_VALUE}'.${CLEAR_TEXT}"
elif (( SCALE_VALUE > 500 )); then
SCALE_VALUE=500
echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} ${SCALE_KEY} value '${RAW_SCALE}' is above 500. Clamping desktop scale to '${SCALE_VALUE}'.${CLEAR_TEXT}"
fi

DEVICE_SCALE=$(( SCALE_VALUE <= 120 ? 100 : SCALE_VALUE <= 160 ? 140 : 180 ))
printf -v "$SCALE_KEY" '%s' "$SCALE_VALUE"
printf -v "$DEVICE_SCALE_KEY" '%s' "$DEVICE_SCALE"
if [ "$DEVICE_SCALE" != "$SCALE_VALUE" ]; then
echo -e "${INFO_TEXT}Approximating the device scale for ${SCALE_KEY} from '${SCALE_VALUE}' to '${DEVICE_SCALE}'; desktop scale remains '${SCALE_VALUE}'.${CLEAR_TEXT}"
fi
done

return 0
}

# Name: 'waLoadConfig'
Expand Down Expand Up @@ -1213,7 +1244,8 @@ function waCheckRDPAccess() {
/d:"$RDP_DOMAIN" \
/u:"$RDP_USER" \
${RDP_PASSWORD_ARG:+"$RDP_PASSWORD_ARG"} \
/scale:"$RDP_SCALE" \
/scale-desktop:"$RDP_SCALE" \
/scale-device:"$RDP_DEVICE_SCALE" \
+auto-reconnect \
+home-drive \
/app:program:"C:\Windows\System32\cmd.exe",cmd:"/C type NUL > $TEST_PATH_WIN && tsdiscon" \
Expand Down Expand Up @@ -1346,7 +1378,8 @@ function waFindInstalled() {
/d:"$RDP_DOMAIN" \
/u:"$RDP_USER" \
${RDP_PASSWORD_ARG:+"$RDP_PASSWORD_ARG"} \
/scale:"$RDP_SCALE" \
/scale-desktop:"$RDP_SCALE" \
/scale-device:"$RDP_DEVICE_SCALE" \
+auto-reconnect \
+home-drive \
/app:program:"C:\Windows\System32\cmd.exe",cmd:"/C $BATCH_SCRIPT_PATH_WIN" \
Expand Down Expand Up @@ -1780,8 +1813,8 @@ function waInstall() {
# Check for missing dependencies.
waCheckInstallDependencies

# Update $RDP_SCALE.
waFixScale
# Resolve RemoteApp and full-desktop scale settings.
waFixScale || return "$?"

# Append additional FreeRDP flags if required.
if [[ -n $RDP_FLAGS ]]; then
Expand Down Expand Up @@ -1977,8 +2010,8 @@ function waAddApps() {
# Check for missing dependencies.
waCheckInstallDependencies

# Update $RDP_SCALE.
waFixScale
# Resolve RemoteApp and full-desktop scale settings.
waFixScale || return "$?"

# Append additional FreeRDP flags if required.
if [[ -n $RDP_FLAGS ]]; then
Expand Down
Loading