MacOS 窗口管理器 yabai 玩耍笔记

2024-01-28 更新:换了新 Macbook Pro 之后,我又重新把 yabai 装上了,目前体验还不错,比 23 年好了不少。另外我新的配置完全基于 nix-darwin 部署,内容也有些改动,有兴趣的可以看看:ryan4yin/nix-config/darwin/wm 附上 nix-darwin 新手起步模板ryan4yin/nix-darwin-kickstarter

在 Linux 上用了一段时间 i3wm 后,我就有点忍受不了工作电脑的桌面环境了,公司给配的是 Macbook Pro 2020,一番查找发现 yabai 比较符合我的需求,于是开始了折腾之旅。

我的电脑配置为 Macbook Pro 2020,i5 + 16G RAM + 512G Disk,性能尚可。

一句话总结:体验还不错,但是还不太成熟,Bug 比较多,而且有点吃性能,安装 yabai 后偶尔就会卡顿一下。

自动分屏 + 快捷键自动调整窗口的体验还是很舒服的,劝退我的主要是如下这些问题:

  1. 对有些软件,比如企业微信、微信、QQ,自动分屏功能不太行,会出现窗口错位。
  2. 如下两个问题逼着我一会儿进入全屏模式,一会儿又要退出全屏,简直离谱。
    1. 全屏下 Chrome 搜索框下方的提示栏被会 Chrome 本身遮挡,必须退出全屏功能才能看到。
    2. 非全屏下,Chrome 页面中的输入框「自动填充」功能会被 Chrome 遮挡,必须进入全屏模式才能看到…
  3. 在右键修改 Firefox Bookmark 中标签时,弹出的修改菜单会被 Bookmark 收藏夹本身的弹窗遮挡,导致有些选项无法点击到。
  4. 开始使用 yabai 后,系统经常性地卡顿,或者风扇狂转,说明这玩意儿有点吃性能。

首先参考这篇官方 WikiDisabling System Integrity Protection 关闭 SIP,然后参照如下流程安装 yabai 与 skhd。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 安装yabai
brew install koekeishiya/formulae/yabai
sudo yabai --install-sa
# 启动yabai 这时候需要授权辅助功能
brew services start yabai

# 安装skhd
brew install koekeishiya/formulae/skhd
# 启动skhd 这时候需要授权辅助功能
brew services start skhd

########### 为 yabai 添加 sudo 权限 ###########
sudo yabai --load-sa
sudo visudo -f /private/etc/sudoers.d/yabai

# 然后输入以下内容 其中 <user> 修改为当前 mac 的用户名
# input the line below into the file you are editing.
#  replace <yabai> with the path to the yabai binary (output of: which yabai).
#  replace <user> with your username (output of: whoami).
#  replace <hash> with the sha256 hash of the yabai binary (output of: shasum -a 256 $(which yabai)).
#   this hash must be updated manually after running brew upgrade.
<user> ALL=(root) NOPASSWD: sha256:<hash> <yabai> --load-sa

上面就完成了安装流程,但是到这里还不能使用,还需要为 skhd 与 yabai 添加配置文件,并添加自定义配置。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 创建yabai配置文件
touch ~/.yabairc
chmod +x ~/.yabairc
# 创建skhd配置文件
touch ~/.skhdrc
chmod +x ~/.skhdrc

# 之后在 ~/.yabairc 中添加以下命令
cat <<EOF > ~/.yabairc
#!/usr/bin/env sh

# wiki 要求在配置最前面加这个,看起来是跟 sudo 权限相关的东西
sudo yabai --load-sa
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
EOF

这里配置的目标是,尽量与 i3wm 的默认快捷键保持一致,因为我在家用的是 Linux,只有办公电脑是 Mac.

我目前的 ~/.yabairc,它用于配置 yabai 的各种行为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env sh

# wiki 要求在配置最前面加这个,看起来是跟 sudo 权限相关的东西
sudo yabai --load-sa
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"

## 输出 debug 日志,出问题时方便排查
yabai -m config debug_output on

# 窗口平铺
yabai -m space --layout bsp
# 默认拆分规则 first_child second_child
yabai -m config window_placement             second_child
# 窗口间距设置
yabai -m config top_padding                  10
yabai -m config bottom_padding               10
yabai -m config left_padding                 10
yabai -m config right_padding                10
yabai -m config window_gap                   10
# 自动平衡所有窗口始终占据相同的空间
yabai -m config auto_balance                 off
# 如果禁用自动平衡,此项属性定义的是新窗口占用的空间量。0.5意为旧窗口占用50%
yabai -m config split_ratio                 0.50
# 鼠标修饰键 意思就是按着这个键就可以使用鼠标单独修改窗口大小了
yabai -m config mouse_modifier ctrl
# ctrl + 鼠标左键 移动窗口
yabai -m config mouse_action1 move
# ctrl + 鼠标右键 调整窗口大小
yabai -m config mouse_action2 resize
# 焦点跟随鼠标 默认off: 关闭  autoraise:自动提升 autofocus: 自动对焦
yabai -m config focus_follows_mouse          autofocus
# 设置鼠标是否跟随当前活动窗口 默认 off: 关闭 on: 开启
yabai -m config mouse_follows_focus          on

# 浮动窗口问题在顶部
yabai -m config window_topmost               on
# 修改窗口阴影 on: 打开 off: 关闭 float: 只显示浮动窗口的阴影
yabai -m config window_shadow                float

# 窗口透明度设置
yabai -m config window_opacity               on
# 配置活动窗口不透明度
yabai -m config active_window_opacity        0.98
yabai -m config normal_window_opacity        0.9
yabai -m config window_opacity_duration      0.0


# 在所有显示器上的每个空间顶部添加 0 填充 底部添加 0 填充
yabai -m config external_bar all:0:0

# ================================ 规则 ================================
# 打开系统偏好设置,不使用平铺模式
yabai -m rule --add app="^系统偏好设置$" manage=off
yabai -m rule --add app="^提醒事项$" manage=off
yabai -m rule --add app="^关于本机$" manage=off

echo "yabai configuration loaded.."

再就是 ~/.skhdrc,它负责配置各种快捷键,如下是我的配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 配置语法 : <modifier> - <key> : <command>
# modifier 可以是单个键比如 cmd, alt, ctrl, 也可以是组合键比如  ctrl + shift, ctrl + alt
# ================================ 打开终端 ================================
# 启动终端
cmd - return : open -a iTerm
# 关闭当前窗口,这个不需要加,macOS 默认是 cmd + q,我 Linux 也这么设置的
# ================================ 窗口设置 ================================
# =============== 为了避免快捷键冲突改用了 ctrl 作为 modifier =================
# ctrl + e 切换为平铺模式
ctrl - e : yabai -m space --layout bsp
# ctrl + s 切换为堆叠模式
ctrl - s : yabai -m space --layout stack
# 浮动/不浮动窗口 float
ctrl - f : yabai -m window --toggle float

# ================================ 多桌面配置  ================================
# 创建一个新桌面,并把当前活动的窗口发送到新桌面,并且自动跳转到新桌面. 需要 jq 支持 brew install jq
shift + cmd - n : yabai -m space --create && index="$(yabai -m query --spaces --display | jq '.| length')" && yabai -m window --space "${index}" && yabai -m space --focus "${index}" && yabai -m space --layout bsp

# 在 stack 模式下通过方向键切换窗口
ctrl - down : yabai -m window --focus stack.next || yabai -m window --focus south
ctrl - up : yabai -m window --focus stack.prev || yabai -m window --focus north
# 在 bsp 模式下通过方向键切换窗口
cmd - left : yabai -m window --focus west
cmd - right : yabai -m window --focus east

# 在 9 个桌面之间切换
ctrl - 1 : yabai -m space --focus 1
ctrl - 2 : yabai -m space --focus 2
ctrl - 3 : yabai -m space --focus 3
ctrl - 4 : yabai -m space --focus 4
ctrl - 5 : yabai -m space --focus 5
ctrl - 6 : yabai -m space --focus 6
ctrl - 7 : yabai -m space --focus 7
ctrl - 8 : yabai -m space --focus 8
ctrl - 9 : yabai -m space --focus 9
# 将窗口发送到某个其他桌面
ctrl + shift - 1 : yabai -m window --space 1
ctrl + shift - 2 : yabai -m window --space 2
ctrl + shift - 3 : yabai -m window --space 3
ctrl + shift - 4 : yabai -m window --space 4
ctrl + shift - 5 : yabai -m window --space 5
ctrl + shift - 6 : yabai -m window --space 6
ctrl + shift - 7 : yabai -m window --space 7
ctrl + shift - 8 : yabai -m window --space 8
ctrl + shift - 9 : yabai -m window --space 9

配置加好后重启 yabai 与 skhd:

1
2
brew services restart yabai
brew services restart skhd

现在就可以随便打开几个程序试试,正常情况下 yabai 会自动帮你分屏。再尝试下添加好的这些快捷键,看看是否生效。

如果 yabai 配置没有生效,有可能是权限问题,可以试下这个命令重启 yabai:

1
sudo yabai --uninstall-sa; sudo yabai --load-sa; brew services restart yabai

其他问题可查看 yabai 的日志解决:

  • 错误日志路径: /usr/local/var/log/yabai/yabai.err.log
  • 普通日志路径: /usr/local/var/log/yabai/yabai.out.log

如果 skhd 配置没有生效,首先可以查看 skhd 的日志:

1
cat /usr/local/var/log/skhd/*.log

如果日志文件不存在,可以停止 skhd 服务并手动启动它,看看是否有输出报错:

1
2
brew services stop skhd
skhd -c ~/.skhdrc

比如我之前改错了配置,执行上述命令就会报错:

1
#27:7 expected modifier

提示我配置的第 27 行配置有问题,我就去看了下,发现是我把 cmd - return 写成了cmd + return,改正后再 brew services start skhd 重启 skhd 就好了。

yabai 在堆叠模式下的可视化效果不是很好,可以使用stackline 来改善一下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# stackline 依赖 hammerspoon,这是一个 macOS 桌面自动化工具
brew install hammerspoon --cask

# 现在将 stackline 安装到 hammerspoon 的配置目录中
git clone https://github.com/AdamWagner/stackline.git ~/.hammerspoon/stackline

# Make stackline run when hammerspoon launches
cd ~/.hammerspoon
echo 'stackline = require "stackline"' >> init.lua
echo 'stackline:init()' >> init.lua

现在还需要安装下 hammerspoon 的命令行工具 hs,它用于在脚本中执行 stackline 操作,安装方法如下:

  1. 首先搜索打开 Hamerspoon 程序,或者使用命令 open -a "Hammerspoon"
    1. 这里启动时会申请权限,需要手动打开下
    2. 同时注意勾选登录时自动启动
  2. 在下方的命令输出栏中键入 hs.ipc.cliInstall() 再回车,即可完成安装

现在确认下 hs 命令已经可用:

1
which hs
  1. Chrome/WeChat 等程序的弹窗无法显示: 尝试下进入全屏或者退出全屏,总有一种场景下可以显示弹窗…