bspwm
bspwm 是一款平铺窗口管理器,它将窗口表示为全二叉树的叶子节点。bspwm 支持多显示器,并通过消息进行配置和控制。部分支持 EWMH。
安装
安装 bspwm 作为窗口管理器本身,以及 sxhkd 作为 X 热键守护进程。
启动
使用 xinit 运行 bspwm。
配置
示例配置位于 /usr/share/doc/bspwm/examples/。
将 bspwmrc 从该目录复制/安装到 ~/.config/bspwm/,将 sxhkdrc 安装到 ~/.config/sxhkd/。
bspwmrc 文件需要具有可执行权限,因为默认示例只是一个 shell 脚本,它随后通过 bspc 命令来配置 bspwm。
$ install -Dm755 /usr/share/doc/bspwm/examples/bspwmrc ~/.config/bspwm/bspwmrc $ install -Dm644 /usr/share/doc/bspwm/examples/sxhkdrc ~/.config/sxhkd/sxhkdrc
这两个文件分别用于设置窗口管理器配置和快捷键绑定。
详细文档请参阅 bspwm(1) 和 sxhkd(1) 手册。
多显示器设置注意事项
示例 bspwmrc 在一个显示器上配置了十个桌面,如下所示
bspc monitor -d I II III IV V VI VII VIII IX X
你需要修改此行并为每个显示器添加一行,类似于这样
bspc monitor DVI-I-1 -d I II III IV bspc monitor DVI-I-2 -d V VI VII bspc monitor DP-1 -d VIII IX X
你可以使用 xrandr -q 或 bspc query -M --names 来查找显示器名称。请注意,如果显示器名称包含特殊字符,整个名称需要用百分号转义,例如 bspc monitor %DVI-I-1.5 -d I II III IV 才能被正确识别。
上述示例中桌面的总数保持在十个。要在 sxhkdrc 中指定每个桌面,你应该引用精确的桌面名称(由上述 bspc monitor 命令定义),如下所示
# focus or send to the given desktop
alt + {_,shift + }{1-9,0}
bspc {desktop --focus,node --to-desktop} '{I,II,III,IV,V,VI,VII,VIII,IX,X}'
注意:在默认配置中,sxhkd 通过数字引用桌面。但这些数字在每次更改显示器设置时都会发生变化。
bspwm 中的桌面通过其索引激活。除非明确设置,否则 bspwm 将自动选择显示顺序,从而决定桌面索引。如果你遇到桌面在错误显示器上的问题,你应该明确设置显示顺序,类似于这样
bspc wm -O DVI-I-1 DVI-I-2 DP-1 bspc monitor DVI-I-1 -d I II III IV bspc monitor DVI-I-2 -d V VI VII bspc monitor DP-1 -d VIII IX X
如果你希望在定期更改显示器布局时自动执行显示器设置,你需要使用条件结构来检查特定显示器是否连接并进行相应配置;你可以用以下脚本替换标准的 bspc monitor -d I II III IV V VI VII VIII IX X 命令
if [[ $(xrandr -q | grep "DP-1 connected") ]];
then
xrandr --output DP-1 --primary --mode 1920x1080 --pos 0x0 --rotate normal \
--output DVI-I-1 --off \
--output DVI-I-2 --off
bspc monitor DP-1 -d I II III IV V VI VII VIII IX
fi
之前的脚本使用 xrandr 来设置虚拟显示配置,并使用 bspc 来分配相应的桌面布局。
请注意,你应该先使用 arandr 设置你偏好的显示器布局,然后导出 xrandr 配置脚本,再将脚本中的内容复制并替换到 xrandr 命令处。
规则
bspwm 可以根据类名(class name)对窗口应用规则,类名是由 ICCM 指定的 WM_CLASS 属性中的第二个字符串。要确定类名,你可以
- 安装 xorg-xprop。
- 运行
xprop | grep WM_CLASS。 - 点击感兴趣的窗口以将其指示给
xprop。 - 记录命令输出中的第二个字符串。
有两种配置窗口规则的方法(自 cd97a32 起)。
第一种是使用内置的 rule 命令,如示例 bspwmrc 所示
bspc rule -a Gimp desktop=^8 follow=on state=floating bspc rule -a Chromium desktop=^2 bspc rule -a mplayer2 state=floating bspc rule -a Kupfer.py focus=on bspc rule -a Screenkey manage=off
第二种选项是使用外部规则命令。这种方法更复杂,但允许你创建更复杂的窗口规则。请参阅这些示例以获取样本规则命令。
面板 (Panels)
使用 lemonbar
lemonbarAUR 的示例面板在 GitHub 页面的 examples 文件夹中提供。你也可以从 lemonbar wiki 页面获得一些启发。在 bspwmrc 中放入 panel & 即可执行该面板。请检查 bspwm 软件包中的 optdepends 以查看可能需要的依赖项。
要在状态栏上显示系统信息,你可以使用各种系统调用。本示例将向你展示如何编辑你的 panel 以在状态栏 (BAR) 上获取音量状态
panel_volume()
{
volStatus=$(amixer get Master | tail -n 1 | cut -d '[' -f 4 | sed 's/].*//g')
volLevel=$(amixer get Master | tail -n 1 | cut -d '[' -f 2 | sed 's/%.*//g')
# is alsa muted or not muted?
if [ "$volStatus" == "on" ]
then
echo "%{Fyellowgreen} $volLevel %{F-}"
else
# If it is muted, make the font red
echo "%{Findianred} $volLevel %{F-}"
fi
}
接下来,我们需要确保它被调用并重定向到 $PANEL_FIFO
while true; do
echo "S" "$(panel_volume) $(panel_clock)" > "$PANEL_FIFO"
sleep 1s
done &
使用 polybar
Polybar 可以通过在 bspwmrc 配置文件中添加 polybar example & 来使用,其中 example 是状态栏的名称。
暂存窗 (Scratchpad)
使用 PID
你可以模拟一个下拉终端。
首先创建名为 /usr/local/bin/scratch 的文件
/usr/local/bin/scratch
#!/bin/bash
name="$1"
filename=/tmp/"$1"
bspc_write_nodeid() {
while true
do
flag=false
for id in $(bspc query -d focused -N -n .floating.sticky.hidden)
do
bspc query --node $id -T | grep -q $name && { echo $id > $filename; flag=true; break; }
done
[[ "$flag" == "true" ]] && break
sleep 0.1s
done
}
hide_all_except_current(){
for id in $(bspc query -d focused -N -n .floating.sticky.!hidden)
do
bspc query --node $id -T | grep -qv $name && bspc node $id --flag hidden=on
done
}
toggle_hidden() {
[ -e "$filename" ] || exit 1
hide_all_except_current
id=$(<$filename)
bspc node $id --flag hidden -f
}
create_terminal(){
alacritty --class="$name","$name" -e $1 &
}
if ! ps -ef | grep -q "[c]lass=$name"
then
bspc rule -a "$name" --one-shot state=floating sticky=on hidden=on
case "$name" in
"htop")
create_terminal htop
;;
"neomutt")
create_terminal neomutt
;;
"newsboat")
create_terminal newsboat
;;
"ranger")
create_terminal ranger
;;
"terminal")
create_terminal $SHELL
;;
*)
exit 1
esac
dunstify "Scratch: starting $name"
bspc_write_nodeid
toggle_hidden
else
toggle_hidden
fi
terminal 应用程序为 alacritty。对于其他终端,请修改上述脚本中的类定义和命令执行部分。
alacritty --class="$name","$name" -e $1 &
要切换暂存窗,请修改 ~/.config/sxhkd/sxhkdrc
~/.config/sxhkd/sxhkdrc
# scratchpads
super + alt + {b,g,i,space,t}
scratch {newsboat,neomutt,ranger,terminal,htop}
(来源: [1])
使用 Polybar 显示暂存窗状态
使用以下内容修改 polybar 配置:
modules-left = scratchpad [module/scratchpad] type = custom/script interval = 0.1 exec = ~/.config/polybar/scratchpads_status.sh
并创建文件 ~/.config/polybar/scratchpads_status.sh,内容如下:
~/.config/polybar/scratchpads_status.sh
#!/bin/bash
names="
htop H
neomutt M
newsboat N
ranger R
terminal T
"
status=""
cmd=$(ps -ef)
check_scratchpad() {
grep -q "[c]lass=$1" <<< "$cmd"
}
IFS=$'\n'
for name in $names
do
status+=$(check_scratchpad ${name% *} && echo ${name#* })
done
if [ -n "$status" ]
then
echo "[$status]"
else
echo ""
fi
(来源: [2])
使用类名 (class name)
在本示例中,我们将使用带有自定义类名的 termite 作为下拉终端。不一定非要是 termite。
首先在你的路径中创建一个包含以下内容的文件并使其可执行。在本例中,我们将其命名为 scratchpad.sh
#!/usr/bin/bash
if [ -z $1 ]; then
echo "Usage: $0 <name of hidden scratchpad window>"
exit 1
fi
pids=$(xdotool search --class ${1})
for pid in $pids; do
echo "Toggle $pid"
bspc node $pid --flag hidden -f
done
然后将其添加到你的 bspwm 配置中。
... bspc rule -a dropdown sticky=on state=floating hidden=on termite --class dropdown -e "zsh -i" & ...
要切换窗口,需要在 sxhkd 中定义自定义规则。将自定义类名作为参数传递。
super + u
scratchpad.sh dropdown
其他
关于可以使用任何窗口类型且无需预定义规则的暂存窗,请参阅:[3]
如果你需要一个更高级的暂存窗脚本,能够开箱即用地支持多种终端,并具有可选启动 tmuxinator/tmux 会话、即时将任何窗口变为暂存窗以及自动调整暂存窗大小以适应当前显示器的功能,请参阅 tdrop-gitAUR。
针对不同机器的不同显示器配置
由于 bspwmrc 是一个 shell 脚本,它允许你执行类似以下的操作
#!/bin/bash -
if [[ $HOSTNAME == myhost ]]; then
bspc monitor eDP1 -d I II III IV V VI VII VIII IX X
elif [[ $HOSTNAME == otherhost ]]; then
bspc wm -O VGA-0 VGA-1
bspc monitor VGA-0 -d I II III IV V
bspc monitor VGA-1 -d VI VII VIII IX X
elif [[ $HOSTNAME == yetanotherhost ]]; then
bspc wm -O DVI-I-2 DVI-I-3
bspc monitor DVI-I-3 -d VI VII VIII IX X
bspc monitor DVI-I-2 -d I II III IV V
fi
设置一个所有窗口均为浮动的桌面
以下是将桌面 3 设置为仅包含浮动窗口的方法。这对于 GIMP 或其他具有多个窗口的应用程序非常有用。
将此脚本放在你的 $PATH 路径下的某个位置,并从 .xinitrc 或类似文件调用(末尾加上 &)
#!/bin/bash
# change the desktop number here
FLOATING_DESKTOP_ID=$(bspc query -D -d '^3')
bspc subscribe node_add | while read -a msg ; do
desk_id=${msg[2]}
wid=${msg[4]}
[ "$FLOATING_DESKTOP_ID" = "$desk_id" ] && bspc node "$wid" -t floating
done
(来源)
键盘
Bspwm 不处理任何键盘输入,而是提供 bspc 程序作为其接口。
对于键盘快捷键,你需要设置一个热键守护进程,如 sxhkd(开发版本为 sxhkd-gitAUR)。
故障排除
屏幕空白且快捷键失效
- 确保已安装 sxhkd。
- 确保你启动了 sxhkd(在后台启动,因为它会阻塞进程)。
- 确保
~/.config/bspwm/bspwmrc具有可执行权限。 - sxhkd 的示例配置文件将 urxvt 指定为终端模拟器。如果你没有安装它,请编辑
~/.config/sxhkd/sxhkdrc指向你选择的终端模拟器。
光标主题未应用于桌面
请参阅 光标主题#更改 X 形状默认光标
窗口边框大于实际应用程序
如果你使用 GTK3 应用程序,且通常在对话框窗口中,可能会发生这种情况。创建或添加以下内容
~/.config/gtk-3.0/gtk.css
.window-frame, .window-frame:backdrop {
box-shadow: 0 0 0 black;
border-style: none;
margin: 0;
border-radius: 0;
}
.titlebar {
border-radius: 0;
}
(来源: Bspwm 论坛帖)
Java 应用程序的问题
如果你遇到 Java 应用程序窗口无法调整大小,或菜单在点击后立即关闭等问题,请参阅 Java#灰色窗口,应用程序无法随 WM 调整大小,菜单立即关闭。
此外,一些基于 Java 的应用程序可能完全无法显示任何窗口内容(例如 PyCharm, CLion 等 Intellij IDE)。一种解决方法是安装 wmname 并添加以下行
~/.config/bspwm/bspwmrc
wmname LG3D
此外,这些错误通常可以通过在例如 bspwmrc 中为 JVM 设置 环境变量 来解决
export _JAVA_AWT_WM_NONREPARENTING=1
使用 fish 时的快捷键问题
如果你使用 fish,你会发现无法切换桌面。这是因为 bspc 使用的 ^ 字符与 fish 不兼容。你可以通过明确告知 sxhkd 使用 bash 来执行命令来修复此问题
$ set -U SXHKD_SHELL /usr/bin/bash
或者,在 sxhkdrc 文件中可以使用反斜杠对 ^ 字符进行转义。
使用 fish 时的性能问题
sxhkd 使用 SHELL 环境变量中设置的 shell 来执行命令。fish 可能会因为庞大或不恰当的配置文件而导致初始化时间过长,因此所有 sxhkd 命令的执行时间可能比其他 shell 长得多。要在不更改默认 SHELL 的情况下解决此问题,你可以明确告知 sxhkd 使用 bash 或其他更快的 shell(例如 sh)来执行命令
$ set -U SXHKD_SHELL sh
启动时出现错误信息 "Could not grab key 43 with modfield 68"
要么是你尝试两次使用同一个按键,要么是你启动了两次 sxhkd。检查 bspwmrc 以及 ~/.profile 或 ~/.bash_profile 中是否有重复启动 sxhkd 的命令。
参见
- 邮件列表: bspwm at librelist.com。
- #bspwm - irc.libera.chat 上的 IRC 频道
- #bspwm:matrix.org - Matrix 频道
- https://bbs.archlinux.org/viewtopic.php?id=149444 - Arch BBS 讨论帖
- https://github.com/baskerville/bspwm - GitHub 项目
- https://github.com/windelicato/dotfiles/wiki/bspwm-for-dummies - earsplit 的 "bspwm 入门指南"