Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ktsaou
Created September 10, 2017 22:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ktsaou/ae8b715eb2fac2f31c7ed0eb79486eae to your computer and use it in GitHub Desktop.
Save ktsaou/ae8b715eb2fac2f31c7ed0eb79486eae to your computer and use it in GitHub Desktop.
autoscale X/Wayland applications based on current DPI settings
#!/usr/bin/env bash
program="${1}"
append=
# -----------------------------------------------------------------------------
# HiDPI decision
primary_found="no"
connected_displays=0
xdpi=1000
ydpi=1000
calc_dpi() {
local screen="${1}" role="${2// /}" wpx="${3}" hpx="${4}" wmm="${5}" hmm="${6}"
[ -z "${role}" ] && role="unknown"
x=$(( ((wpx * 10 / ((wmm * 10) / 254)) + 5) / 10 ))
y=$(( ((hpx * 10 / ((hmm * 10) / 254)) + 5) / 10 ))
connected_displays=$((connected_displays + 1))
if [ "${role}" = "primary" ]
then
xdpi=${x}
ydpi=${y}
primary_found="yes"
elif [ "${primary_found}" != "yes" ]
then
[ ${x} -lt ${xdpi} ] && xdpi=${x}
[ ${y} -lt ${ydpi} ] && ydpi=${y}
fi
echo >&2 "Screen: ${screen}, role ${role}, resolution ${wpx}x${hpx} px, dimensions ${wmm}x${hmm} mm, density ${x}x${y} dpi"
return 0
}
eval "$(xrandr |\
grep " connected " |\
sed "s|^\(.*\) connected\(.*\) \([0-9]\+\)\+x\([0-9]\+\).* \([0-9]\+\)mm x \([0-9]\+\)mm.*|calc_dpi '\1' '\2' '\3' '\4' '\5' '\6';|g" |\
grep ^calc_dpi
)"
echo >&2 "System minimum screen density ${xdpi}x${ydpi} dpi"
#find_min_dpi() {
# local t x y
# for t in $(xdpyinfo | grep "dots per inch" | sed "s|^.* \([0-9]\+x[0-9]\+\) .*$|\1|g")
# do
# x="${t/x*/}"
# y="${t/*x/}"
# echo >&2 "Found DPI: ${t}, parsed as ${x} x ${y}"
#
# [ -z "${x}" -o $((x + 0)) -eq 0 ] && x=96
# [ -z "${y}" -o $((y + 0)) -eq 0 ] && y=96
#
# [ ${x} -lt ${xdpi} ] && xdpi=${x}
# [ ${y} -lt ${ydpi} ] && ydpi=${y}
# done
#}
#find_min_dpi
#echo >&2 "Minimum screen DPI: ${xdpi} x ${ydpi}"
#
#connected_displays=$(xrandr | grep " connected" | wc -l)
#[ $((connected_displays)) -eq 0 ] && connected_displays=1
#echo >&2 "Connected displays: ${connected_displays}"
# decide if we need double scaling or not
HiDPI="yes"
[ ${xdpi} -le 168 -a ${ydpi} -le 168 ] && HiDPI="no"
# [ ${connected_displays} -gt 1 ] && HiDPI="yes"
# -----------------------------------------------------------------------------
# per application settings
if [ "${HiDPI}" = "yes" ]
then
DEFAULT_SCALE="2" # GTK/Qt applications - integer only
CHROME_SCALE="2.1" # google chrome/chromium settings
FIREFOX_SCALE="2.1" # firefox settings
FIREFOX_FONT="16" # in px
else
DEFAULT_SCALE="1" # GTK/Qt applications - integer only
CHROME_SCALE="1.3" # google chrome/chromium settings
FIREFOX_SCALE="1.3" # firefox settings
FIREFOX_FONT="14" # in px
fi
# -----------------------------------------------------------------------------
# helper functions
single_app_scale() {
local s="${1}"
export GDK_SCALE="${s}"
export CLUTTER_SCALE="${s}"
export QT_AUTO_SCREEN_SCALE_FACTOR="${s}"
}
firefox_change_setting() {
local setting="${1}" value="${2}"
for x in $(find ${HOME}/.mozilla/firefox -name prefs.js)
do
echo "firefox settings found: ${x}"
dir=$(dirname "${x}")
if [ ! -L "${dir}/lock" ]
then
if ! grep -q "^user_pref(\"${setting}\"," "${x}"
then
echo "Adding firefox setting ${settings} to ${value}"
echo "user_pref(\"${setting}\", \"${value}\");" >>"${x}"
fi
echo >&2 "changing firefox setting ${settings} to ${value}"
sed -i "s|^user_pref(\"${setting}\", \".*\");$|user_pref(\"${setting}\", \"${value}\");|g" "${x}"
else
echo >&2 "firefox is locked"
fi
done
}
firefox_set_ui_font_size() {
local size="${1}"
for x in $(find ${HOME}/.mozilla/firefox -name prefs.js)
do
echo "firefox settings found: ${x}"
dir=$(dirname "${x}")
if [ ! -L "${dir}/lock" ]
then
[ ! -d "${dir}/chrome" ] && mkdir -p "${dir}/chrome"
if [ ! -f "${dir}/chrome/userChrome.css" ]
then
echo >&2 "Adding file: ${dir}/chrome/userChrome.css"
cat >"${dir}/chrome/userChrome.css" <<EOF
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
* { font-size: ${size}px !important; }
EOF
fi
echo >&2 "changing firefox UI font size to ${size}px"
sed -i "s|^\* { font-size: .* \!important; }$|* { font-size: ${size}px !important; }|g" "${dir}/chrome/userChrome.css"
else
echo >&2 "firefox is locked"
fi
done
}
if [[ "${program}" =~ .*chrom.* ]]
then
append="--force-device-scale-factor=${CHROME_SCALE}"
elif [[ "${program}" =~ .*firefox.* ]]
then
firefox_change_setting "layout.css.devPixelsPerPx" "${FIREFOX_SCALE}"
firefox_set_ui_font_size "${FIREFOX_FONT}"
fi
logger -p info "AUTOSCALE: ${*} ${append}"
exec "${@}" ${append}
@ktsaou
Copy link
Author

ktsaou commented Sep 10, 2017

Run any X11/Wayland application like this:

/path/to/autoscaled.sh application [app params]

The script is to be used on 4K screens that have different DPIs. So, on the high density laptop screen you get 2.x scaling, while on a desktop screen you get 1.x scaling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment