yabai - Mac 的窗口平铺管理软件

https://github.com/koekeishiya/yabai

窗口平铺管理软件,可以让多个窗口安装自己的配置在桌面平铺展开,且随着单个窗口大小的改变而自适应调整、保证桌面上窗口的平铺效果。

类似的软件还有 Amethyst ,不过相比于 Amethyst,yabai 的上手难度会更高一些,也会更加灵活和可定制化。

希望使用 yabai,总的来说有以下步骤:

  1. (可选)禁用 Mac 的 SIP System Integrity Protection,这会解锁 yabai 更多的功能
  2. 按照 yabai 并运行
  3. 配置自己的 yabai
  4. (可选)用例如 skhd 的软件控制 yabai 的快捷键;或用例如 Übersicht 的软件高亮正在使用的窗口

安装方法

安装并启动 yabai

首先通过 Homebrew 安装 yabai

brew install koekeishiya/formulae/yabai 

在安装时,Homebrew 会有如下提示:

To start koekeishiya/formulae/yabai now and restart at login:   brew services start koekeishiya/formulae/yabai Or, if you don't want/need a background service you can just run:   yabai 

这里告诉我们两种启动 yabai 的方式,一种是让其一直在后台运行,一种是临时启动。

如果我们已经禁用了 Mac 的 SIP System Integrity Protection,则可以在启动前先输入以下命令,可以启用更多 yabai 的功能;但也会让系统变得相对不安全:

# install the scripting addition sudo yabai --install-sa  # if macOS Big Sur or Monterey, load the scripting addition manually; follow instructions below to automate on startup sudo yabai --load-sa 

这里我没有选择关闭 SIP,没有启用上面的功能。

我们希望 yabai 能总是在后台运行,因此我们输入 brew services start koekeishiya/formulae/yabai。之后会提示 yabai 需要对应的权限,允许即可。

启动后你会发现没有任何不同,这是因为 yabai 需要我们有对应的 .yabairc 配置文件才会生效,默认是没有这个文件的,也就是 yabai 不会做任何处理。我们会在后面的「配置」部分讲到相关的内容。

卸载 yabai

如果希望卸载 yabai,则输入以下命令:

# stop yabai brew services stop yabai  # uninstall the scripting addition sudo yabai --uninstall-sa # 如果之前有启用才需要  # uninstall yabai brew uninstall yabai  # these are logfiles that may be created when running yabai using brew services. # path may differ if a custom brew prefix has been selected. rm -rf /usr/local/var/log/yabai  # remove config and various temporary files rm ~/.yabairc rm /tmp/yabai_$USER.lock rm /tmp/yabai_$USER.socket rm /tmp/yabai-sa_$USER.socket  # unload the scripting addition by forcing a restart of Dock.app killall Dock 

配置 yabai

前面提到 yabai 刚启动时是没有任何不同的,这是因为我们没有对应的配置文件 .yabairc,我们需要在 HOME 目录下生成 .yabairc 并增加可执行权限,然后通过 brew services restart yabai 重新启动 yabai 即可让配置文件生效。

yabai 配置比较简单,可以用 man yabai项目中附带的 example 对照着看,可以先拷贝成自己的 ~/.yabairc 感受一下。文章末尾我也会贴上自己当前使用的配置。

配置 skhd

yabai 配置完成启动后便自动生效,往往我们希望通过快捷键来控制对应需要的行为。

例如,如果没有快捷键,yabai 中将窗口全屏,需要输入下面的终端指令:

yabai -m window --toggle zoom-fullscreen 

通过如 skhd 这类软件,我们通过如下配置,就可以将 ctrl + alt - enter 和对应指令绑定了:

ctrl + alt - enter  : yabai -m window --toggle zoom-fullscreen 

首先安装 jqkoekeishiya/formulae/skhd

brew install jq brew install koekeishiya/formulae/skhd 

jq 是一个 json 的 cli 工具,用于在终端对 json 进行处理。通过它我们可以方便地进行一些 yabai 的相关配置,例如当前我使用的「快速关闭当前窗口」:

## Close active application (快速关闭窗口) ctrl + alt - backspace : $(yabai -m window $(yabai -m query --windows --window | jq -re .id) --close) 

当然,我们也可以用其他的键盘映射工具来配置快捷键,例如 Karabiner;不过个人感觉他们对于命令行的配置没有 skhd 那样简洁直观。

同样的,和 yabai 一样,skhd 需要有 ~/.skhd 才生效,也可以看看 yabai 项目中附带的 example 学习一下。

需要额外说一下的是,运行 skhd 时会要求 Accessibility 权限,这里我们需要注意,终端软件也是需要一起开启对应权限的,否则不生效:

另外再分享两个 skhd 初配置时可能有用的东西:

  1. 如果 .skhdrc 有部分配置存在无法运行,那么整个 .skhdrc 都不会生效
    1. 我们可以先手动停止 skhd(brew services stop skhd),然后在终端运行 skhd -V 或者 skhd --verbose,这会加载 .skhdrc 并输出对应 debug 信息。
    2. 如果有不正确或者无法运行的,skhd 便会输出并提示(如下图)

  1. skhd 配置时,有些键位我们不知道如何表示
    1. 可以在终端运行 skhd --observe 查看键盘上对应按键在 skhd 中对应的编码,例如下面用 0x24 表示回车
## full screen / un-full screen(切换窗口全屏) 0x24 表示回车 ctrl + alt - 0x24 : yabai -m window --toggle zoom-fullscreen 

.yabairc 和 .skhdrc

当前还没整到 GitHub 上,最后就在文章末尾贴一下我自己当前使用的 .yabairc.skhdrc,仅供各位参考。

  • .yabairc
#!/usr/bin/env sh  # 如果没有关闭 Mac 的 SIP,那么在 BigSur 及以上的系统中,更改配置文件后,需要手动加载过配置文件 #  - https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release) # 如果已经关闭 Mac 的 SIP,那么通过下面命令就可以让 yabai 的配置文件热更新了 # sudo yabai --load-sa # 也可以在该配置文件中增加这句,这样每次重启系统时不用自己输入 # yabai -m signal --add event=dock_did_restart action=sudo yabai --load-sa  # ------------------------------------------------------------------------------------- # # ------------------------------global settings---------------------------------------- # # ------------------------------------------------------------------------------------- #  # 在多显示器情况下,新建的窗口默认在**哪个显示器**出现 # - default: 在创建窗口的显示器出现(mac 的默认行为) # - focused: 在当前聚焦的显示器出现 # - cursor: 在鼠标指针所在的显示器出现 yabai -m config window_origin_display        default          # 当前屏幕下,新窗口的出现在**屏幕的哪个位置** # - first_child: (父节点模式)如果当前是 vertical split,则出现在*左侧*;如果是 horizontal split,则出现在*上方* # - second_child: (子节点模式)如果当前是 vertical split,则出现在*右侧*;如果是 horizontal split,则出现在*下方* yabai -m config window_placement             second_child  # 浮动窗口是否置顶 yabai -m config window_topmost               on  # 窗口阴影值 # - on: 总是展示 # - off: 总是关闭 # - float: 只有浮动窗口展示 yabai -m config window_shadow                on  # 窗口不透明 # - on: 总是展示 # - off: 总是关闭 yabai -m config window_opacity               off # *激活*窗口的不透明度(仅当 window_opacity on 时才有效) yabai -m config active_window_opacity        1.0 # *普通*窗口不透明度(仅当 window_opacity on 时才有效) yabai -m config normal_window_opacity        0.90 # 激活窗口和普通窗口切换时,*不透明度的过渡时间*(仅当 window_opacity on 时才有效) yabai -m config window_opacity_duration      0.0  # 窗口边框 # - on: 总是展示 # - off: 总是关闭 yabai -m config window_border                off # 窗口*边框宽度*(单位 px) yabai -m config window_border_width          6 # 激活窗口的边框颜色 yabai -m config active_window_border_color   0xff775759 # 普通窗口的边框颜色 yabai -m config normal_window_border_color   0xff555555 yabai -m config insert_feedback_color        0xffd75f5f  # 所有窗口都使用相同比例的空间 # - on: 总是开启 # - off: 总是关闭 yabai -m config auto_balance                 off # 分屏后*旧:新*窗口的比例(仅当 auto_balance off 时有效) yabai -m config split_ratio                  0.50  # ==================================================== # # ====================鼠标相关======================== # # ==================================================== #  # 窗口切换时,鼠标自动移动到当前使用窗口的中心 # - on: 总是开启 # - off: 总是关闭 yabai -m config mouse_follows_focus          off  # 是否自动聚焦到鼠标所在窗口 # - off: 总是关闭 # - autoraise:  # - autofocus:  yabai -m config focus_follows_mouse          off              # 按住对应修饰键时,yabai 不自动调整平铺(默认情况下调整窗口大小时,yabai 会自适应调整平铺);配置时通常会关闭 focus_follows_mouse # - cmd # - alt # - shift # - ctrl # - fn yabai -m config mouse_modifier               fn # modifier + 左键的行为 # - move # - resize yabai -m config mouse_action1                move # modifier + 右键的行为 # - move # - resize yabai -m config mouse_action2                resize  # 在平铺管理情况下,拖动一个窗口到另一窗口位置时的操作 # - swap: 交换窗口位置 # - stack: 堆叠在旧窗口上 yabai -m config mouse_drop_action            swap  # ------------------------------------------------------------------------------------- # # ---------------------------general space settings------------------------------------ # # ------------------------------------------------------------------------------------- #  # yabai 布局模式 # - bsp: 平铺 # - stack: 堆叠 # - float: 浮动 yabai -m config layout                       bsp # 窗口和屏幕边缘的距离(优先级低于 gap) yabai -m config top_padding                  08 yabai -m config bottom_padding               08 yabai -m config left_padding                 08 yabai -m config right_padding                08 # 窗口与窗口之间的间距(优先级高于 padding) yabai -m config window_gap                   05  # ------------------------------------------------------------------------------------- # # ---------------------------------specific apps--------------------------------------- # # ------------------------------------------------------------------------------------- #  # manage: 是否使用 yabai 管理 # - on # - off # sticky: 是否总是置顶 # - on # - off # layer: # - below # - normal # - above yabai -m rule --add app=^System Preferences$ manage=off yabai -m rule --add app=^System Information$ sticky=on layer=above manage=off yabai -m rule --add app=^Activity Monitor$ sticky=on layer=above manage=off yabai -m rule --add app=^Finder$ sticky=on layer=above manage=off yabai -m rule --add app=^Alfred Preferences$ sticky=on layer=above manage=off yabai -m rule --add app=^飞书$ sticky=on layer=above manage=off yabai -m rule --add app=^Feishu$ sticky=on layer=above manage=off yabai -m rule --add app=^Lark$ sticky=on layer=above manage=off yabai -m rule --add app=^Lark Meetings$ sticky=on layer=above manage=off yabai -m rule --add app=^Seal$ sticky=on layer=above manage=off yabai -m rule --add app=^AppCleaner$ sticky=off layer=above manage=off yabai -m rule --add app=^Karabiner-Elements$ sticky=on layer=above manage=off yabai -m rule --add app=^Karabiner-EventViewer$ sticky=on layer=above manage=off yabai -m rule --add app=^Things$ manage=off yabai -m rule --add app=^Spotify$ manage=off yabai -m rule --add app=^Bartender 4$ manage=off yabai -m rule --add app=^BetterTouchTool$ manage=off yabai -m rule --add app=^Magnet$ manage=off yabai -m rule --add app=^WeChat$ manage=off yabai -m rule --add app=^微信$ manage=off  echo yabai configuration loaded.. 
  • .skhdrc,一些脚本就没贴上了,感兴趣的可以评论留言或者 GitHub 上翻翻看其他人的配置:
#SKHD STUFF  # if you're having troubles finding key codes for a key just type skhd --observe in a terminal and type a key. Pretty cool! Or just check the wiki.  ## HYPER == SHIFT + CMD + ALT + OPTION  ### ============================================================================ ### ###                               My Settings                                    ### ### ============================================================================ ###  ## Close active application (快速关闭窗口) ctrl + alt - backspace : $(yabai -m window $(yabai -m query --windows --window | jq -re .id) --close)  ## Equalize size of windows (平铺当前界面所有窗口) ctrl + alt - 0 : yabai -m space --balance  ## focus window (切换窗口焦点) ctrl + alt - k : sh ~/.config/dotfiles/yabai/script/focus_window.sh up ctrl + alt - j : sh ~/.config/dotfiles/yabai/script/focus_window.sh down ctrl + alt - h : sh ~/.config/dotfiles/yabai/script/focus_window.sh left ctrl + alt - l : sh ~/.config/dotfiles/yabai/script/focus_window.sh right  ## swap window & move window in floating mode (移动窗口) shift + alt - k : yabai -m window --swap north shift + alt - j : yabai -m window --swap south shift + alt - h : yabai -m window --swap west shift + alt - l : yabai -m window --swap east  ## Rotate windows clockwise and anticlockwise (旋转窗口) ctrl + alt - e : yabai -m space --rotate 90 ctrl + alt - r : yabai -m space --rotate 270  ## float / Unfloat window (切换窗口浮动) ctrl + alt - space : yabai -m window --toggle float ;  yabai -m window --grid 12:12:1:1:9:9  ## full screen / un-full screen(切换窗口全屏) 0x24 表示回车 ctrl + alt - 0x24 : yabai -m window --toggle zoom-fullscreen  ## window resize ctrl + shift + alt - k : yabai -m window --resize top:0:-20 || yabai -m window --resize bottom:0:-20 ctrl + shift + alt - j : yabai -m window --resize top:0:20 || yabai -m window --resize bottom:0:20 ctrl + shift + alt - h : yabai -m window --resize left:-20:0 || yabai -m window --resize right:-20:0 ctrl + shift + alt - l : yabai -m window --resize right:20:0 || yabai -m window --resize left:20:0  ## send window to next monitor and follow focus (将窗口发送到另一个显示器) ctrl + alt - left : sh ~/.config/dotfiles/yabai/script/move_window_to_left.sh display ctrl + alt - right : sh ~/.config/dotfiles/yabai/script/move_window_to_right.sh display  ## create desktop, move window and follow focus - uses jq for parsing json (brew install jq) shift + alt - n : yabai -m space --create && \                 index=$(yabai -m query --spaces --display | jq 'map(select(.native-fullscreen == 0))[-1].index') && \                 yabai -m space --focus ${index}