1

X11 多显示器配置:玩转 XRandR

 2 years ago
source link: https://harttle.land/2019/12/24/auto-xrandr.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

RandR(Resize and Rotate)协议是基于 X Window 系统的一个扩展,它可以直接操作显示器模式、刷新率,属于 DDX 组件。 xrandr 是官方的 RandR 配置工具,比老的 Xinerama 机制更容易测试和配置。 本文在没有桌面环境的情况下直接对底层软件进行配置,如果有安装某种 DE 可以在其控制面板中找到对应的配置。

xrandr

需要先安装 xorg-xrandr,无参数运行 xrandr 可以打印当前的 RandR 配置:

> xrandr
Screen 0: minimum 8 x 8, current 3840 x 2400, maximum 32767 x 32767
eDP1 connected primary 3840x2400+0+0 (normal left inverted right x axis y axis) 290mm x 180mm
   2560x1600     59.97*+
   ...
   640x360       59.84    59.32  
DP1 disconnected (normal left inverted right x axis y axis)
DP2 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
HDMI2 connected 2160x3840+3840+0 left (normal left inverted right x axis y axis) 480mm x 270mm
   1920x1080     60.00*+  50.00    59.94  
   1680x1050     59.88  
   ...
VIRTUAL1 disconnected (normal left inverted right x axis y axis)

添加 --verbose 参数可以打印更详细的信息,比如缩放(Transform 矩阵)、EDID 等。 其中 eDP1 是显示器名(output),下列出的是它支持的分辨率(mode)和刷新率(rate)。配置方式也很简单:

xrandr --output eDP1 --mode 1920x1080 --rate 60

HiDPI 和缩放

我的情况更加复杂,内置显示器(eDP1)是 Retina 屏幕,外置的(HDMI2)是普通的 1080p 屏幕。 这样两个屏幕需要设置不同的 DPI 才能让它们都能正常显示。 不论你在用 GNome、KDE、Wayland,还是像我这样的 i3wm,在 X11 下 HiDPI 有三处可以设置(而且都要设置):

  1. GUI 工具库的环境变量/配置文件。比如 GDK 或 QT 的缩放变量,这一组环境变量决定了你的 GUI 程序以怎样的级别缩放。
  2. 字体的 DPI。Xresource 是用户级别的 X11 配置,其中 Xft.dpi 决定了 X11 中的字体使用怎样的 DPI。
  3. RandR 的缩放。由于 GDK 只能整数缩放,需要借助 xrandr --scale 做任意缩放。

GDK 配置

GUI 工具库比较主流的是 GDK 和 QT,我们以 GDK 为例。 在你的 ~/.profile 中可以直接配置 GDK 软件的缩放。 要确保你的 登录 Shell 确实会执行这个 ~/.profile。

GDK_SCALE 只支持整数,也就是说只能放大两倍、三倍、四倍…… 而 Ritina 屏幕合适的缩放级别是 1.25-1.75 之间。 因此要先把它设置到一个 UI 看起来已经“很大”的值,后面再用 RandR 缩放回来。

# file: ~/.profile
export GDK_SCALE=2
export GDK_DPI_SCALE=0.5

其中 GDK_SCALE 会把字体也一并放大,字体就会模糊。 我们要用 GDK_DPI_SCALE 抵消对字体的缩放,后面再用 XResource 选择正确 DPI 的字体。

QT_SCALE_FACTOR 貌似不需要碰,看起来 QT 软件会跟随 Xft.dpi 的配置。如果你的 QT 软件(比如 Telegram)显示不正常可以尝试把它设为 1 或者 2。

字体的 DPI

XResource 机制提供了对字体和光标的单独配置, 只需要在 ~/.Xresources 中添加对应配置并确保它被 .xinitrc 或你的 Display Manager 执行到了。 这是我的 ~/.Xresources:

Xft.dpi: 270
Xcursor.size: 45

其中 Xft.dpi 用来配置 X11 选择的字体默认是 96,Xcursor.size 是光标大小。在 .xinitrc 中应用这个配置:

[ -f $HOME/.Xresources ] && xrdb -merge $HOME/.Xresources

测试时也可以 xrdb -merge 一下,新打开的软件就会生效。

XRandR

前面用 GDK_SCALE 把 GUI 软件放大了整数倍,这里需要用 XRandR 把它缩放回来。 xrandr 的 --scale 参数可以是任意小数,实现了连续可调的缩放级别:

xrandr --output eDP1 --scale 1.5x1.5

因为 xrandr 的 --dpi 参数是同时对所有显示器生效的,我们只能用 --scale 参数来分别设置每个显示器。 此外,我们还能让外接显示器旋转、放到内置显示器的右边:

xrandr --output HDMI2 --pos 3840x0 --rotate left --scale 2x2

GUI 配置和自动切换

用 xrandr 调节显示器适合放到脚本里面去执行,人工设置插入的显示器非常不方便,尤其是去会议室投影幻灯片的时候。 这时我们需要一个 GUI 版本的 XRandR:ARandR。 它可以通过鼠标拖拽来调节多个显示器,也可把调节后的结果保存为一个 .sh 文件用来下次直接跑。

此外我们还希望显示器插入/拔出的时候,识别到之前的保存好的配置直接应用。 最简单的方式是 从 AUR 安装 autorandr。 这是一个 python 封装过的 XRandR,提供了保存当前配置、加载某个配置、自动匹配并加载配置。

autorandr --save samsung-right-of-mac   # 三星在 Mac 右边
autorandr --save mac-only               # 没有任何外接
autorandr --load samsung-right-of-mac   # 插入显示器后应用这个配置
autorandr --change                      # 根据现在插入的显示器匹配加载配置

安装 autorandr 后它会启用一个 systemd 的 hook,在 drm 设备发生变化时调用 autorandr --change

Hacking

如果你在用 autorandr、arandr 时也遇到一些奇怪的问题, 可以像我一样写一个自定义的 autorandr。

保存/加载配置:https://gist.github.com/harttle/75b625a952ec48913dd019654a79cf75

监听内核事件:通过 udev rules 来在显示器插入/拔出时调用 autorandr.js --change 实现自动加载(传递哪些环境变量取决于你调用的软件会读哪些):

# file: /dev/udev/rules.d/80-randr.rules
KERNEL=="card0", SUBSYSTEM=="drm", ENV{HOME}="/home/harttle", ENV{XAUTHORITY}="/home/harttle/.Xauthority", ENV{DISPLAY}=":0", ENV{XDG_CONFIG_HOME}="/home/harttle/.config", RUN+="/home/harttle/bin/autorandr"

重启后生效,也可以通过 udevadm 让它立即生效:

udevadm control --reload

自定义需求:在插入外置显示器时,我还希望重新渲染一下桌面背景、跑一个新的 conky,或者发一个 libnotify 通知,下面是我的 /home/harttle/bin/autorandr。

#!/usr/bin/env bash
exec >> /home/harttle/log/autorandr.log 2>&1

/usr/bin/node --jitless /home/harttle/bin/autorandr.js --change
/home/harttle/bin/conky-update.sh
/home/harttle/bin/variety-update.sh

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2019/12/24/auto-xrandr.html。学识粗浅写作仓促,如有错误辛苦评论或 邮件 指出。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK