在 i3 中使用多显示器

之前我以为大家用多屏都是因为没有 tiling window manager 不会切屏用了才知道竖屏好

但两个横屏的话确实就那样吧其实之前看室友也基本上就用一个屏幕然后另一个放壁纸请买旋转升降支架学习使用 tiling window manager

xrandr 屏幕布局配置

可以使用 arandr 在 GUI 中调整屏幕布局设置坐标和方向比较方便但它调不了帧率之类的可以保存为脚本之后手动修改在相应的 --output HDMI-0 之后加上 --rate 120 就行

我配置了 verticalhorizontalsingle 三种模式用脚本切换

#!/bin/bash

set -euo pipefail

hdmi="HDMI-0"

if xrandr | grep "$hdmi connected 1080x1920"; then
    # already vertical, switch to horizontal
    "$HOME"/.screenlayout/horizontal.sh
elif xrandr | grep "$hdmi connected"; then
    # startup or currently horizontal, switch to vertical
    "$HOME"/.screenlayout/vertical.sh
else
    # HDMI not connected, switch to single
    "$HOME"/.screenlayout/single.sh
fi

在启动时调用脚本进行初始化在 i3 中可以配置快捷键调用脚本切换布局

i3 多显示器配置

可以参考 Multiple monitors - i3 Users Guide 的说明配置中用 primary / nonprimary 会比直接写具体的显示器名称更加通用需要在 xrandr 配置中设置 --primary

默认给各个显示器分配 workspaceworkspace $ws1 output primaryworkspace $ws2 output nonprimary

bar 可以只在一个显示器显示bar { output primary }或者在每个显示器都显示配置托盘图标显示在哪bar { tray_output primary }

绑快捷键

  • focus 到另一个显示器focus output next
  • 移动当前 workspace 到另一个显示器move workspace to output next

我之前一直设的 workspace_auto_back_and_forth yes切换 workspace 时如果目标就是当前所在的 workspace就会回到之前所在的 workspace但是之前就觉得有时候会有些混乱在多显示器时更是容易搞不清当前在哪个 workspace所以把它关了

picom 高亮当前窗口

即使是单显示器高亮当前窗口也是有用的多显示器时尤其有用有助于提示当前在哪个显示器

旧版 picom 使用 inactive-dim 选项现在推荐使用更加灵活的 window rule

rules = (
    { match = "window_type = 'normal' && window_type != 'popup_menu' && !_NET_WM_STATE && !(focused || group_focused)"; dim = 0.2; },
)

这里 window_type != 'popup_menu' 主要是为了 konsole 的菜单它同时是 popup_menunormal_NET_WM_STATE 主要是为了 rofi它没设 window type但有 _NET_WM_STATE_ABOVE

调整 DPI 修复字体和光标大小

由于不同显示器 DPI 不同字体大小之类的可能出问题

在 Xorg 启动后i3 启动前使用 xrandr --dpi 调整 DPI 可以改变 i3 窗口标题和 bar 的字体大小例如 xrandr --dpi 144 / xrandr --dpi DP-2

调整 DPI 似乎并不能修复光标大小可以在 ~/.Xresources 中设置 Xcursor.size: 24然后在启动时加载 xrdb -merge ~/.Xresources1

fcitx5 会根据各个屏幕的 DPI 分别调整字体大小可以在 classic user interface 的设置中禁用 use per screen DPI

i3lock 布局配置

position 是基于整个 screen 而非单个 display所以需要分别加上 xy

  • x - x position of the current display. Corresponds to the leftmost column of pixels on that display.

  • y - y position of the current display. Corresponds to the topmost row of pixels on that display.

坐标计算可以基于 wh 来同时适配横屏和竖屏例如

    --ind-pos "x+w/2:y+h/2-35" \
    --greeter-pos "ix:iy+h/6+160" \
    --time-pos "ix:iy+h/8+100" \

背景图片适配修复

为了同时适配横屏和竖屏如果i3lockkonsolefeh背景图片是少量元素 + 大片背景可以上下扩展背景编辑成竖屏再用 centered / crop 显示横屏时上下背景被截掉就可以正好显示中间的元素其中 konsole 还可以设置 anchor 的位置就不一定要放正中间例如可以放最下面我用的背景 78468574 就很适合放下面

屏幕布局旋转方向发生改变时使用 feh 设置的桌面背景可能会乱掉可以在每次布局改变后重新调用 feh 设置背景放在调整屏幕布局的脚本里即可也可以为横竖屏设置不同的背景

为不同显示器设置不同壁纸

feh 传多个文件名参数就可以依次为各个显示器设置不同的壁纸使用 xrandr --listmonitors 查看显示器的顺序

禁用 HDMI 音频输出

在连接到外部显示器后我的 pulseaudio 会自动切换到 HDMI 音频输出手动修改 default sink 也没有用在 xrandr 中禁用 HDMI output 就可以恢复正常

单次修复可以手动在 pavucontrolConfiguration 中将外部输出的 profile 设为 Off自动修复可以在启动时执行 pactl set-card-profile <card> off其中 card 名称可以通过 pactl list cards 得到2

另外还有一种更粗暴的方法是禁用 snd_hda_codec_hdmi只不过我这里 blacklist 不管用要执行 rmmod -f snd_hda_codec_hdmi 才行3

限制鼠标跨屏移动

多显示器时鼠标光标可以通过屏幕边缘在各个显示器之间移动这在一般的 window manager 中是必不可少的功能但在 i3 中就没必要了反而容易带来麻烦导致移动光标到屏幕边缘更加困难

如果将屏幕布局设置为两个显示器角对角只有一个像素相交从一个显示器移动到另一个显示器就只能在这一个像素进行能一定程度上缓解问题但实际上由于光标会卡在屏幕边缘角落的这一个像素其实很容易移动到还是很容易意外滑到另一个显示器另外虽然空出来的大量屏幕空间不会显示出来但仍然会占用显存也可能导致神秘渲染问题4

更好的解决方法是使用 xpointerbarrier可以在 AUR 安装运行 xpointerbarrier 0 0 0 0 即可4我实测这个 barrier 并不 100% 靠谱大力多晃几次鼠标可以越过去但实际使用中效果还行

xpointerbarrier 只是限制了光标在 i3 中 focus / move 时依然可以跨屏不会 wrap around循环设置为对角布局可以解决这个问题对于 focus还有一种办法是设置 focus_wrapping workspace 来避免 focus 到另一个显示器但 move 并没有类似的设置倒是影响不大

只不过如果不设置为对角布局光标跨屏显示可能会令人困惑而且也有小概率不小心越过 barrier所以设置对角布局也有其好处如果不缺显存的话

dunst 通知跟随当前显示器

~/.config/dunst/dunstrc 中可以修改通知显示在哪个显示器其中 follow 选项可以根据当前的 focus 改变通知显示的位置

解决运行时连接显示器导致黑屏

我观察到如果开机后再连接显示器切换布局后会黑屏后来确认是 picom 使用 glx / egl backend 时的问题使用 xrender 就不会这样关闭 / 重启 picom 就可以恢复显示但 Firefox 也会卡一会儿应该也是 OpenGL 相关问题暂不清楚具体原因以及彻底修复的方法目前我的 workaround 是在切换布局的脚本中重启 picom

log 里观察到大量 Duplicate vblank event found with msc可能和 https://github.com/yshui/picom/issues/1265 相关下个版本看看会不会好

Footnotes

  1. How can I change the mouse cursor size : r/i3wm

  2. How to remove Nvidia HDMI audio output in PulseAudio? - Ask Ubuntu

  3. [SOLVED] How to disable nvidia hdmi audio? / Kernel & Hardware / Arch Linux Forums

  4. [SOLVED]Multihead: is there a way to forbid mouse from leaving screen? / Applications & Desktop Environments / Arch Linux Forums 2