Created
September 10, 2017 22:06
-
-
Save ktsaou/ae8b715eb2fac2f31c7ed0eb79486eae to your computer and use it in GitHub Desktop.
autoscale X/Wayland applications based on current DPI settings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Run any X11/Wayland application like this:
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.