
O driver de vídeo no WSL (17/08/2024) não está enviando as informações do tamanho real do monitor para o Xrandr.
Isso é um problema para qualquer aplicação que possua uma GUI.
Você pode conferir uma ferramenta que fiz usando o conteúdo desse post no github: https://github.com/A-Ribeiro/wsl-hidpi-suggestion .
Contexto
Por esses dias estava programando uma ferramenta que utiliza o Xrandr para fazer uma query do tamanho do display para renderizar os componentes gráficos com a resolução correta.
O código nativo no windows e no linux funcionam corretamente.
No WSL tem essa questão.
Parece que o driver de vídeo no WSL não transfere a informação correta do tamanho dos monitores do sistema para as aplicações.
Por isso criei esses scripts que configuram a escala de DPI nas variáveis de ambiente do WSL no '~/.bashrc'.
Configuração
1) Entre no wsl e crie um arquivo com o nome '~/powershell_get_dim.ps1' e preencha com o conteúdo abaixo:
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class DCOps {
[DllImport("user32.dll")] public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")] public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")] public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public static int HORZSIZE = 4;
public static int VERTSIZE = 6;
public static int DESKTOPVERTRES = 117;
public static int DESKTOPHORZRES = 118;
}
"@
$hdc = [DCOps]::GetDC([IntPtr]::Zero)
if ($hdc -eq [IntPtr]::Zero){
echo "1,1,1,1"
exit
}
$w=[DCOps]::GetDeviceCaps($hdc, [DCOps]::DESKTOPHORZRES)
$h=[DCOps]::GetDeviceCaps($hdc, [DCOps]::DESKTOPVERTRES)
$wm=[DCOps]::GetDeviceCaps($hdc, [DCOps]::HORZSIZE)
$hm=[DCOps]::GetDeviceCaps($hdc, [DCOps]::VERTSIZE)
$rc=[DCOps]::ReleaseDC([IntPtr]::Zero, $hdc)
echo "$w,$h,$wm,$hm"
Esse script pega o monitor padrão do windows e retorna a resolução atual em pixels e em milímetros.
2) Agora crie um arquivo '~/_new_set_dpi_scale_from_win32.sh' com o conteúdo abaixo:
#!/bin/sh
f_dpi_scale() {
local dpi_scale powershell_script MainDisplayInfo dpi_100_percent
# the notation ${<item1>:-<item2>}
# is similar to <item1> or <item2>, if <item1> is not defined
dpi_scale="${GDK_DPI_SCALE:-${QT_SCALE_FACTOR:-${GTK_SCALE:-${GDK_SCALE:-}}}}"
if [[ -z "${dpi_scale:-}" ]] ; then
powershell_script=`cat ~/powershell_get_dim.ps1`
MainDisplayInfo=$("/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" "$powershell_script")
# set -f # avoid globbing (expansion of *).
# array=(${MainDisplayInfo//,/ })
# array=(`echo $MainDisplayInfo | sed 's/,/\n/g'`)
array=(`echo $MainDisplayInfo | tr ',' '\n'`)
w=${array[0]} # width in px
h=${array[1]} # height in px
wm=${array[2]} # width in mm
hm=${array[3]} # height in mm
dpi_100_percent=$(bc <<<"scale=6; $w / ($wm / 25.4)")
dpi_scale=$(bc <<<"scale=6; ($w * 25.4) / ($wm * 96) ")
export GDK_SCALE=${GDK_SCALE:-$dpi_scale}
export GDK_DPI_SCALE=${GDK_DPI_SCALE:-$dpi_scale}
export GTK_SCALE=${GTK_SCALE:-$dpi_scale}
# https://doc.qt.io/qt-5/highdpi.html
# export QT_AUTO_SCREEN_SCALE_FACTOR=${QT_AUTO_SCREEN_SCALE_FACTOR:-1}
# export QT_ENABLE_HIGHDPI_SCALING=${QT_ENABLE_HIGHDPI_SCALING:-1}
export QT_SCALE_FACTOR=${QT_SCALE_FACTOR:-$dpi_scale}
echo "DPI scale info:"
echo " - Main size"
echo " (px): ${w}x${h}"
echo " (mm): ${wm}x${hm}"
echo " (DPI-100%): ${dpi_100_percent} DPI"
echo " - Scale set to: $dpi_scale"
fi
}
# if dir runtime-dir exists, then ...
[ -d /mnt/wslg/runtime-dir ] && f_dpi_scale
Esse script basicamente executa nosso script em powershell e no final configura as variáveis no sistema: GDK_SCALE, GDK_DPI_SCALE, GTK_SCALE e QT_SCALE_FACTOR.
3) Por fim, abra o seu arquivo '~/.bashrc' e acrescente a seguinte linha de código:
# ... . ~/_new_set_dpi_scale_from_win32.sh
Pronto
Agora é só entrar no WSL e testar as aplicações de GUI.
Obs.: Essa configuração só tem efeito nas aplicações que utilizam alguma dessas variáveis de ambiente que acabamos de configurar.
Espero que tenham gostado do conteúdo.
abraços,
Alessandro Ribeiro
