xrandr – 多屏幕不同DPI配置踩坑记

Linux平台上的多屏幕支持一直不像Windows和Mac那么友好。近日在配置多屏幕不同DPI,实现不同比例缩放时碰到了麻烦。本博记录一下解决的思路和解决方案,供日后参考。虽说并不完美,但不影响使用。

环境信息

系统环境:
Ubuntu 18.04 LTS (未启用Wayland)
X.Org X Server 1.19.6
Gnome 3.28.2

计算机型号:华为MateBook 13 2018
显示设备:
屏幕1:内置显示器 (奇美CMN8201面板)13寸 分辨率:2160×1440 DPI 200
屏幕2:飞利浦246E 23寸 分辨率:1920×1080 DPI 96
笔记本居左,外置显示器居右。

# xrandr信息
# 内置显示器为eDP-1,外置显示器为DP-1
Screen 0: minimum 320 x 200, current 4080 x 1440, maximum 8192 x 8192
eDP-1 connected primary 2160x1440+0+0 (normal left inverted right x axis y axis) 275mm x 183mm
   2160x1440     60.00*+
(下略)

DP-1 connected 1920x1080+2160+0 (normal left inverted right x axis y axis) 521mm x 293mm
   1920x1080     60.00*+  50.00    59.94  
(下略)

两屏幕均使用核显输出。在添加第二显示器之前,gnome使用1.25缩放比例,系统全局使用100%缩放比例。添加第二显示器后,由于内置显示器的高DPI,外置显示器的内容均被放大两倍,浏览网页还能将就,但在写程序时候需要来回调整字体,很不方便。

xrandr 配置思路

xrandr官方wiki:https://wiki.archlinux.org/index.php/Xrandr
HiDPI官方wiki:https://wiki.archlinux.org/index.php/HiDPI

xrandr是Xorg官方对于randr的配置工具。底层原理也是将两块屏幕的显示内容按照给定参数拼接到一块“画布 ”上,再进行输出。画布的大小等于两块屏幕的物理分辨率*缩放系数的和。当不进行任何配置的时候,Xorg默认使用1.0的缩放倍数对两显示器进行配置。因此出现了同样200DPI的情况下,外置显示器显示偏大的问题。

为优先确保内置屏幕的显示质量,我们采用统一DPI=200进行配置。因此,配置思路是把这块“画布”上内置显示器的区域不变,把外接显示器的画布扩展,实现同物理显示区域内显示内容增加来达到缩小的目的。

配置过程

根据HiDPI官方给出的公式,命令如下:

xrandr --output eDP-1 --auto --output HDMI-1 --auto --panning [C*E]x[D*F]+[A]+0 --scale [E]x[F] --right-of eDP-1
# Generically if your HiDPI monitor is AxB pixels and your regular monitor is CxD and you are scaling by [ExF], the commandline for right-of is:

以本文为例:

xrandr --output eDP-1 --auto --output DP-1 --auto --panning 2880x1620+2160+0 --scale 1.5x1.5 --right-of eDP-1

两显示器均配置为auto模式,–panning参数设置鼠标可取范围。一定要注意这个参数的设置,否则鼠标可能无法正常移动。命令执行后,Ubuntu将全局的缩放比例自动调节到了200%,手动调节回100%后,出现了两屏幕显示区域重叠、鼠标位置不正常的问题。此外,在内置显示器上还存在鼠标闪烁的问题。好消息是在200%缩放比例下,两屏幕的显示比例一致,没有出现一边大一边小的问题,证明整体思路是可行的。接下来,就是填坑了。

全局缩放比例调整带来的异常

在这一块,Gnome做得确实要比原来的Ubuntu Desktop差着不少,没想到会有这么多的麻烦。猜想可能是 xrandr 中 –auto参数导致的问题,在缩放比例进行调整后xrandr无法正确识别并应用配置文件。遂对需要的参数进行一一指定:

xrandr --dpi 200 --fb 5040x1620 --output eDP-1 --mode 2160x1440 --pos 0x0 --output DP-1 --scale 1.5x1.5 --pos 2160x0 --panning 2880x1620+2160+0

–dpi: 强制全局使用200% dpi
–fb: 指定画布大小。双显示器横向并列防止,故:长边 = 2160 + 1920 * 1.5 = 5040;短边取1620(1440 和 1080*1.5的较大值)。
–pos: 指定显示器的位置,笔记本在左侧,pos=0x0;第二显示器在右侧,pos=2160×0

经过设置后,显示效果恢复正常,但鼠标闪烁的问题仍未解决。

解决鼠标闪烁:玄学参数

将内置显示器的显示比例调整为:–scale 0.9999×0.9999。

完整命令:

xrandr --dpi 200 --fb 5040x1620 --output eDP-1 --mode 2160x1440 --pos 0x0 --scale 0.9999x0.9999 --output DP-1 --scale 1.5x1.5 --pos 2160x0 --panning 2880x1620+2160+0

(仅限Intel核显用户)除此解决方法外,也有帖子指出修改Xorg的配置文件才是根本解决方案。方法为:在 /etc/X11/xorg.conf.d/ 下新建20-intel.conf文件,内容为:

Section "Device"
    Identifier "Intel Graphics"
    Driver "intel"
    Option  "AccelMethod"  "sna"
    Option "TearFree" "true"
EndSection

以上内容可能适用于稍老型号的Intel核显。我在UHD620(8代i5)上实测并未解决鼠标闪烁,反而增加了水波纹、斜纹等问题。写在这里仅供参考。

最终还是会有点小毛病,首先是在移除第二显示器之后无法自动恢复,还需再次执行xrandr –auto。在快速拖动窗口时候仍旧可见一点斜纹和水波纹,不过终究不影响使用,以后再探究原因了。