前言💬

最近日常使用的软件逐渐增多,目前多数人常用的的层叠式窗口管理,似乎开始不适合我的日常使用 所以我决定折腾一下mac下的平铺式窗口管理软件yabai

什么是yabai

yabaiLOGO

yabai 是一款适用于 macOS Big Sur 11.0.1+ 和 Monterey 12.0.0+ 的平铺式窗口管理器。 它使用二叉空间分割算法自动修改您的窗口布局,使您能够专注于窗口内容而不受干扰。 灵活且易于理解的命令行界面允许您控制和查询窗口、空间和显示器,实现与诸如↗ skhd等工具的强大集成,使您能够更高效地使用 macOS。轻松创建自定义快捷键来控制窗口、空间和显示器,几乎不需要时间,让您的双手离开鼠标和触控板,回到键盘上进行实际工作。

平铺式与层叠式的区别

层叠式窗口管理(Stacking Window Manager)与平铺式窗口管理(Tiling Window Manager)是两种不同的计算机桌面环境中的窗口管理方式。它们的主要区别在于如何组织和显示打开的应用程序窗口。 层叠式窗口管理:

层叠式窗口管理

  1. 概念:层叠式窗口管理器将打开的窗口以层叠或重叠的形式显示在桌面上,就像摆放在桌子上的纸张一样。这是许多传统桌面环境的默认窗口管理方式,如 Microsoft Windows 和 Apple macOS。
  2. 灵活性:用户可以自由移动、缩放和重叠窗口,根据自己的需求调整窗口的位置和大小。
  3. 窗口切换:用户可能需要频繁切换窗口或将窗口最小化以查看其他窗口。在多任务情况下,可能导致桌面混乱。
  4. 空间利用:层叠式窗口管理可能无法充分利用屏幕空间,特别是当用户打开大量窗口时。

平铺式窗口管理:

平铺式窗口管理

  1. 概念:平铺式窗口管理器会将打开的窗口以非重叠的方式自动排列在桌面上。每个窗口都被分配一个固定的屏幕区域,这使得所有窗口都可以同时显示,无需重叠或最小化。一些流行的平铺式窗口管理器包括 i3、xmonad 和 dwm。
  2. 空间利用:平铺式窗口管理器通常更有效地利用屏幕空间,特别是在多任务和多显示器设置中。
  3. 键盘驱动:许多平铺式窗口管理器主要依赖键盘快捷键来操作,这对于喜欢使用键盘的高效用户来说可能更加方便。
  4. 学习曲线:平铺式窗口管理器通常具有较高的学习曲线,因为它们可能需要用户学习新的操作习惯和快捷键。同时,它们通常提供高度的可定制性,让用户能够根据自己的需求和喜好进行调整。

安装yabai

可以通过 Homebrew 的软件源 koekeishiya/formulae 安装 yabai 的经过代码签名的二进制版本

brew install koekeishiya/formulae/yabai

安装yabai

启动yabai服务

启动yabai服务成功

弹出Accessibility权限申请的窗口

Accessibility权限申请

开启yabai的Accessibility权限即可

开启yabai的Accessibility权限

启动后你会发现没有任何不同,这是因为 yabai 需要我们有对应的 .yabairc 配置文件才会生效,默认是没有这个文件的,也就是 yabai 不会做任何处理。

配置yabai

我们需要在 HOME 目录下生成 .yabairc 并增加可执行权限,然后通过 brew services restart yabai 重新启动 yabai 即可让配置文件生效。 yabai 配置比较简单,可以用 man yabai项目中附带的 example 对照着看,可以先拷贝成自己的 ~/.yabairc 感受一下。

一键下载配置文件

如果你嫌麻烦可以直接下载示例配置文件

curl https://raw.githubusercontent.com/koekeishiya/yabai/master/examples/yabairc --output ~/.yabairc

手动安装配置文件

1.使用vim配置~/.yabairc

vim ~/.yabairc

2,粘贴example配置文件

example配置文件

3.重启yabai

brew services restart yabai

现在你就会发现,窗口已经是平铺式的了

平铺式窗口

yabai的启动方式

yabai一直在后台运行,用户登陆的时候也会自动启动

brew services start koekeishiya/formulae/yabai

临时启动

yabai

启用yabai更多功能

如果我们已经禁用了 Mac 的 SIP System Integrity Protection,则可以在启动前先输入以下命令,可以启用更多 yabai 的功能;但也会让系统变得相对不安全: 关于如何禁用SIP可以网上搜索相关文章,如果你和我一样使用OpenCore Legacy Patcher安装的macOS 可以看我写的(文章)[https://blog.erratas.cloud/index.php/2023/04/10/opencore-legacy-patcher%e5%85%b3%e9%97%adsip%e4%bf%9d%e6%8a%a4%f0%9f%94%92/\]来关闭SIP保护

# 安装脚本附加组件
sudo yabai --install-sa

# 如果使用的是 macOS Big Sur 或 Monterey,请手动加载脚本附加组件。请按照以下说明在启动时自动化
sudo yabai --load-sa

由于yabai使用macOS Mach API将代码注入Dock.app;这需要提升 (root) 权限。因此可以配置用户以root身份执行yabai –load-sa 而无需输入密码。为此需要添加一个_/etc/sudoers_加载的新配置条目 创建一个新文件进行编写 - visudo 默认使用 vim 编辑器

sudo visudo -f /private/etc/sudoers.d/yabai

将下面的行输入到你正在编辑的文件中。 将 替换为 yabai 二进制文件的路径(输出结果:which yabai)。 将 替换为你的用户名(输出结果:whoami)。 将 替换为 yabai 二进制文件的 sha256 哈希值(输出结果:shasum -a 256 $(which yabai))。 运行 brew upgrade 后必须手动更新此哈希值。

<user> ALL=(root) NOPASSWD: sha256:<hash> <yabai> --load-sa

例如

获取配置信息

eitan ALL=(root) NOPASSWD: sha256:740b9e6aab46f8c499f0fc651ae1861d4ebe48b6e6a50296bf4a9ad879bbad93 /usr/local/bin/yabai --load-sa

粘贴到yabai的sudoers条目

完成上述编辑后,在 yabairc 配置文件顶部添加加载脚本的命令

yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
sudo yabai --load-sa

yabairc配置文件添加加载脚本

完成之后重启yabai

brew services restart yabai

image-20230416003901612

安装并配置skhd

配置好了 yabai 后,我们已经实现了智能分屏,但是有时候算法提供的窗口位置不满足我们的需求,或是我们需要频繁在各个窗口之间切换/调整,那就需要用到 skhd 工具来定制一些快捷键配置。

安装skhd

brew install koekeishiya/formulae/skhd

安装skhd

下载skhd配置文件

同样的,和 yabai 一样,skhd 需要有 ~/.skhd 才生效,也可以看看 yabai 项目中附带的 example 学习一下。 你可以使用以下命令一键下载配置文件

curl https://raw.githubusercontent.com/koekeishiya/yabai/master/examples/skhdrc --output ~/.skhdrc

下载skhd配置文件

启动skhd

brew services start skhd

启动skhd

同样第一次启动 skhd 和 yabai 一样,macOS 会提示是否允许两者访问辅助功能。在系统偏好设置中添加权限后,再重启一次 skhd 即可正常工作

第一次启动skhd申请Accessibility权限

启用skhd Accessibility权限

重启skhd

brew services restart skhd

重启skhd

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

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

img

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

安装jq

jq 是一个轻量级且灵活的命令行 JSON 数据处理工具。它可以帮助你解析、过滤、查询和操作 JSON 数据。使用 jq,你可以在命令行中对 JSON 数据执行各种操作,例如提取特定字段、过滤数组元素或转换数据格式等 通过它我们可以方便地进行一些 yabai 的相关配置,例如当前我使用的「快速关闭当前窗口」

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

安装jq

brew install jq

安装jq

.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                 on
# 分屏后*旧:新*窗口的比例(仅当 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
yabai -m rule --add app="^QQ$" manage=off
yabai -m rule --add app="^Clash for Windows$" manage=off
yabai -m rule --add app="^CleanMyMac X$" manage=off
yabai -m rule --add app="^PicGo$" manage=off
yabai -m rule --add app="^OpenCore-Patcher$" manage=off
yabai -m rule --add app="^ToDesk$" manage=off
yabai -m rule --add app="^Bandizip$" manage=off
yabai -m rule --add app="^Archive Utility$" manage=off

echo "yabai configuration loaded.."

.skhdrc

#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

### ============================================================================ ###
###                               Eitan's Settings                               ###
### ============================================================================ ###

# open terminal
cmd - return : /Applications/Warp.app/Contents/MacOS/stable --single-instance -d ~ &> /dev/null


## 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 (切换窗口焦点)
alt - x : yabai -m window --focus recent
alt - h : yabai -m window --focus west
alt - j : yabai -m window --focus south
alt - k : yabai -m window --focus north
alt - l : yabai -m window --focus east
alt - z : yabai -m window --focus stack.prev
alt - c : yabai -m window --focus stack.next

## swap window & move window in floating mode (交换窗口)
shift + alt - x : yabai -m window --swap recent
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

# move window (启动窗口)
shift + cmd - h : yabai -m window --warp west
shift + cmd - j : yabai -m window --warp south
shift + cmd - k : yabai -m window --warp north
shift + cmd - l : yabai -m window --warp 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

# toggle picture-in-picture(启用画中画)
alt - p : yabai -m window --toggle border --toggle pip

## 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

## 创建桌面、移动窗口和跟随焦点 - 使用 jq 解析 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}"