Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

set-x11vnc-resolution.sh (Source)

#/bin/sh
# File: set-x11vnc-resolution.sh
# Location: /mnt/public/Support/Programs/vnc/
# Author: bgstack15
# Startdate: 2024-08-15-5 13:09
# SPDX-License-Identifier: GPL-3.0-only
# Title: Resize x11vnc server in a vnc client window
# Purpose: Simplify resizing remmina vnc window
# History:
# Usage: run on client side
# Reference:
#    https://unix.stackexchange.com/questions/14159/how-do-i-find-the-window-dimensions-and-position-accurately-including-decoration/14170#14170
#    https://stackoverflow.com/questions/15816/changing-the-resolution-of-a-vnc-session-in-linux
#    https://stackoverflow.com/questions/2683279/how-to-detect-if-a-script-is-being-sourced
# Improve:
#    This does not handle any other wm than fluxbox, or client other than remmina
# Dependencies:
#    client: kerberos ticket for ssh to x11vnc server, xwininfo, xdotool,
#    server: /mnt/public/Support/Platforms/devuan/scripts/enable-remote-desktop.sh, xrandr, cvt, fbsetbg
# Documentation:
#    For consistent dpi across custom resolutions, use /etc/X11/Xresources/vnc-dpi contents `Xft.dpi: 96`
_get_geometry() {
   #_id="${_id:-"$( xdotool getactivewindow )"}"
   _id="${_id:-${1}}"
   test -z "${_id}" && return 1
   unset x y w h
      eval $( xwininfo -id "${_id}" | \
      sed -n -e "s/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p" \
         -e "s/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p" \
         -e "s/^ \+Width: \+\([0-9]\+\).*/w=\1/p" \
         -e "s/^ \+Height: \+\([0-9]\+\).*/h=\1/p" )
   #printf '%s\n' "${x} ${y} ${w} ${h}"
   # my fluxbox theme uses 35,47 offset to the first pixel of the x11 server in remmina
   # 38, 32
   # I think these numbers cannot get precise. 45 is fairly close and seems to avoid scrollbars.
   echo "_w=$(( w - 45 ))"
   echo "_h=$(( h - 45 ))"
}
_get_important_window() {
   # You might be tempted to let the user click a window, however, it would be painful to guarantee you can learn the correct target host. The titlebar might have the vncserver name, or not. We should just make vncserver required.
   # FUTUREIMPROVEMENT
   # I only use remmina but that might change.
   # return window id
   xwininfo -root -tree | awk "\$0 ~ /${vncserver}/ && /remmina/ && "'!'"/awk/ {print \$1}"
}
_connect_and_add_resolution() {
   # we know we always run x11vnc from script /mnt/public/Support/Platforms/devuan/enable-remote-desktop.sh
   # which uses env vars XAUTHORITY=/tmp/:0 DISPLAY=:0
   # but let us parse in case that ever changes.
   # this ssh depends on kerberos or other passwordless operation
   ssh "${vncserver}" /bin/sh ${VERBOSE:+-x} <<-EOF
   _i="\$( ps -e -o command:180 | grep -E '[x]11vnc' )"
   export XAUTHORITY="\$( echo "\${_i}" | xargs -n1 | awk '/-auth/{getline;print;}' )"
   export DISPLAY="\$( echo "\${_i}" | xargs -n1 | awk '/-display/{getline;print;}' )"
   #xrandr | awk "/${_w}x${_h}/" | grep -qE . && exit 0
   _connected="\$( xrandr | awk '/ connected/{print \$1}' )"
   export _newmode="\$( cvt "${_w}" "${_h}" | awk '{\$1="";print}' | tr -d '"' | tail -n1 )"
   export _newmodename="\$( echo "\${_newmode}" | awk '{print \$1}' )"
   xrandr --newmode \${_newmode} 2>&1 | grep -vE 'of failed request|Current serial number' | grep -e '.'
   xrandr --addmode "\${_connected}" \${_newmodename}
   xrandr -s \${_newmodename}
   # common wallpaper command for stackrpms
   fbsetbg -a /etc/wallpaper
EOF
   # thankfully the XAUTHORITY and DISPLAY lets us run fbsetbg, so we do not need this.
   # get user of root. thankfully we always use fluxbox.
   #_u="\$( ps -ef | awk '\$NF~/[f]luxbox/{print \$1}' )"
}
# BEGIN IF-DOT-SOURCED
sourced=0
if [ -n "$ZSH_VERSION" ]; then
  case $ZSH_EVAL_CONTEXT in *:file) sourced=1;; esac
elif [ -n "$KSH_VERSION" ]; then
  [ "$(cd -- "$(dirname -- "$0")" && pwd -P)/$(basename -- "$0")" != "$(cd -- "$(dirname -- "${.sh.file}")" && pwd -P)/$(basename -- "${.sh.file}")" ] && sourced=1
elif [ -n "$BASH_VERSION" ]; then
  (return 0 2>/dev/null) && sourced=1
else # All other shells: examine $0 for known shell binary filenames.
  # Detects `sh` and `dash`; add additional shell filenames as needed.
  case ${0##*/} in sh|-sh|dash|-dash) sourced=1;; esac
fi
# END IF-DOT-SOURCED
# MAIN
if test "${sourced}" = "0" ;
then
   vncserver="${vncserver:-${1}}"
   test -z "${vncserver}" && { echo "Fatal! Set vncserver to run ${0}. Aborted." 1>&2 ; return 1 ; }
   _id="$( _get_important_window )"
   eval $( _get_geometry "${_id}" )
   echo "working with w=${_w}, h=${_h}"
   _connect_and_add_resolution
fi