bspwm

来自 ArchWiki

bspwm 是一个平铺窗口管理器,它将窗口表示为完整二叉树的叶节点。bspwm 支持多显示器,并通过消息进行配置和控制。部分支持 EWMH

安装

安装 bspwm 以获取窗口管理器本身,并安装 sxhkd 以获取 X 热键守护程序。

注意: 自 2020 年以来没有发布新版本。如果您遇到任何问题或需要缺少的功能,请安装 bspwm-gitAURsxhkd-gitAUR

启动

使用 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 -qbspc 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 可以根据类名将规则应用于窗口,类名是 WM_CLASS 属性中的第二个字符串,该属性由 ICCM 指定。要确定类名,您可以

  1. 安装 xorg-xprop
  2. 运行 xprop | grep WM_CLASS
  3. 单击感兴趣的窗口以指示 xprop
  4. 记录命令输出中的第二个字符串。

配置窗口规则有两种方法(截至 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

第二种选择是使用外部规则命令。这更复杂,但可以让您制定更复杂的窗口规则。请参阅 这些示例 以获取示例规则命令。

面板

使用 lemonbar

GitHub 页面上的 examples 文件夹中提供了 lemonbar-gitAUR 的示例面板。您也可以从 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 example & 添加到您的 bspwmrc 配置文件来使用 Polybar,其中 example 是栏的名称。

暂存区

使用 pid

您可以模拟一个下拉终端。

首先创建一个名为 /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

# 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 = $XDG_CONFIG_HOME/polybar/scratchpads_status.sh


并创建一个文件 $XDG_CONFIG_HOME/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]

使用类名

在本示例中,我们将使用带有自定义类名的 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 程序作为其接口。

对于键盘快捷键,您将必须设置一个热键守护程序,如 sxhkdsxhkd-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#灰色窗口,应用程序无法随窗口管理器调整大小,菜单立即关闭

此外,某些基于 Java 的应用程序可能根本无法显示任何窗口内容(例如 Intellij IDE(如 PyCharm、CLion 等))。一个解决方案是安装 wmname 并在您的 ~/.config/bspwm/bspwmrc 中添加以下行

wmname LG3D

此外,这些错误通常可以通过在 bspwmrc 或 shell rc(如 ~/.bashrc)中为 JVM 设置环境变量来解决,因为 BSPWM 是一个非重父窗口管理器。

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 的过多命令。

参见