用 mac 办公到第六年,我才承认一件事:真正拖慢我的不是机器性能,而是每天都在重复的窗口拖拽。浏览器放左边、编辑器放右边、终端压在最下面,调一次位置要十几秒,一天下来几十次。后来我接触到平铺式窗口管理,具体落地用的是Yabai这个开源方案,把它装在 mac 上跑了很长一段时间,才明白效率差异并不来自快捷键快多少,而是来自“窗口位置由规则决定,不由手感决定”。这篇内容讲的就是我在 mac 上折腾 Yabai 的完整过程:它到底是什么、解决什么问题、哪些功能需要付出额外代价、配置怎么写、哪些坑必须提前知道。适合三类人参考:每天开十几个窗口的重度使用者、愿意花一个晚上换长期顺手的人、以及已经装过但配置跑不起来想排查的人。完全没接触过命令行也能看懂,我会把每个参数为什么这么设讲清楚。
1. 为什么mac用户会突然迷上平铺式布局
1.1 我每天花在拖窗口上的时间
先说一个我真实算过的账。某段时间我记录了三个工作日,平均每天手动调整窗口位置和大小 62 次,每次连“找到窗口边缘、拖到大致位置、再微调”算 8 秒,一天就是 8 分钟出头,一周 40 多分钟。这个数字单看不算吓人,但它的问题在于碎片化:每次拖拽都会打断一次思路,从“我在想问题”切换到“我在对齐像素”,再切回来要重新找回上下文,这部分成本远比 8 分钟高。
mac 自带的窗口管理能力其实不算弱:双击标题栏最大化、长按绿色按钮分屏、调度中心(Mission Control)管理多个空间。但这些机制本质上是手动触发的——你得先想到要用,再去按。而当你桌面上同时开着浏览器、编辑器、终端、聊天窗口、设计稿这五类东西时,靠手动触发意味着每切换一次任务组合,就要重组一次桌面。
平铺式窗口管理器解决的就是这个“重组成本”。它的核心承诺只有一句话:窗口不需要你摆,它自己会占满该占的地方。你新开一个窗口,它会自动切分当前屏幕空间;你关掉一个,剩下的会自动铺满。
1.2 平铺式的底层逻辑:把位置交给规则
理解平铺式,最好的类比是文件系统里的自动布局,而不是“更聪明的拖拽”。传统浮动式窗口(也就是 mac 默认行为)里,每个窗口有独立坐标 (x, y) 和尺寸 (w, h),互不干涉,重叠是常态。平铺式则把屏幕看成一整块可以不断二分的区域:第一个窗口占满全屏,第二个窗口进来时把当前区域按比例切成两半,第三个窗口再把其中一半切一半,依次递归下去。这就是所谓 BSP(二叉空间分割)布局的名称来源。
这种结构带来三个直接结果。第一,永远不会重叠,任何窗口都完整可见,不存在“被挡住的那个窗口找不到”的情况。第二,屏幕利用率接近 100%,大屏上不会再出现中间一大片空白、窗口挤在角落的情况。第三,位置可预测,你按“向右切分”就一定是向右切分,不需要用眼睛去确认。
代价同样明显:你需要放弃“把某个窗口随手拖到某个位置”的自由。对习惯了自由摆放的人来说,前三天会非常别扭,这也是绝大多数人装上又卸载的原因。我的建议是给自己一周适应期,并且只在新任务开始时用平铺,老任务里的窗口先全部固定为浮动,逐步过渡。
1.3 动手前的三道门槛:版本、权限、习惯
在敲第一条命令之前,有三件事要先确认清楚,否则后面会反复卡住。
第一道是系统版本。窗口管理类工具高度依赖系统底层接口,近两年的系统版本在权限模型上有过几次调整,不同版本的行为差异不小。判断方法很简单:先看工具官方文档里写明的支持范围,再对照自己的系统信息,不要直接照抄网上两年前的教程,那类教程里的步骤很可能已经失效。
第二道是权限模型。Yabai 的功能分成两层:一层是普通的窗口布局计算,只需要辅助功能授权;另一层是“移动任意窗口、切换空间、改透明度”这类深度操作,需要一个额外的脚本附加组件,而这个组件要加载,就得放宽系统的完整性保护设置。这一步会降低系统防护等级,公司配发的设备、多人共用的设备、处理敏感资料的设备,我建议直接跳过这一层,只用基础布局功能,也足够覆盖八成日常需求。
第三道是习惯。平铺式的价值来自键盘驱动:手不离键盘地切焦点、调比例、换空间。如果你习惯用触控板,平铺式的收益会砍掉一半。所以我的建议是先配好一套快捷键,再开始用,否则体验会很割裂。
2. Yabai的四个核心机制
2.1 布局引擎:bsp、stack、float三种模式
Yabai 的布局不是只有一种,它内置三种模式,通过一条命令随时切换。理解它们的差别,比背命令重要得多。
bsp是二叉空间分割,也就是我上面说的递归切分,适合“同时看多个窗口”的场景,比如一边写代码一边看日志一边查文档。它的切分比例由split_ratio控制,默认 0.5,也就是每次对半分。我会把它设成 0.5 保持对称,但在宽屏上会临时用命令把某个窗口拉宽,看完再缩回。
stack是堆叠模式,所有窗口都铺满同一块区域,只有最上面那个可见,其余的叠在下面。它适合“一次只专注一件事”的状态,比如写文档、看长文。和普通的浮动窗口不同,堆叠模式下窗口尺寸始终等于屏幕区域,切换时不会有尺寸跳变。
float是浮动模式,也就是回归系统默认行为。这个模式的意义在于例外处理:某些窗口天生不适合平铺,比如视频小窗、系统设置面板、某些不支持自由缩放的对话框,把它们扔进浮动层,就不会被布局引擎折腾变形。
三种模式并不是互斥的,它们是分层的:整个桌面有一个全局布局模式,同时每个窗口可以单独被标记为浮动,脱离布局引擎的管理。这个设计很关键,后面讲应用规则时还会用到。
2.2 命令与查询:一套JSON接口
Yabai 的第二个机制是命令 + 查询的双向接口。所有操作都是一条以yabai -m开头的命令,语法结构统一为“对象 + 动作 + 参数”,比如:
yabai -m window --focus west yabai -m window --swap east yabai -m space --focus 2 yabai -m config window_gap 8这四类对象分别是window(窗口)、space(空间/桌面)、display(显示器)、config(全局配置),外加rule(应用规则)和signal(事件信号)。记住这个分类,基本就能看懂官方文档里所有命令,不用死记。
查询接口更有意思。加上-m query之后,工具会把当前状态以 JSON 吐出来,比如查当前聚焦窗口的信息:
yabai -m query --windows --window输出里包含窗口标题、所属应用、所属空间、坐标、是否浮动、是否全屏等字段。配合jq这类命令行 JSON 处理工具,就能写出很灵活的逻辑,比如“如果当前窗口是聊天软件,就把它切到第三空间”。这也是 Yabai 相比图形化窗口管理工具最大的优势——它是可编程的,不是一个固定功能集合。
我实际用到查询的场景主要有两个:一是写脚本让某些窗口自动归位,二是在状态栏上显示“当前空间有几个窗口”,避免误切。
2.3 信号系统:让窗口事件触发动作
第三个机制是信号(signal)。简单说,就是“当某件事发生时,执行某条命令”。可监听的事件包括窗口创建、窗口关闭、窗口获得焦点、空间切换、显示器变化、窗口移动和缩放等。
yabai -m signal --add event=window_created action="yabai -m window --insert east" label=auto_insert上面这条的意思是:每当有新窗口创建,就把它插入到当前窗口的东侧。label是给这条信号起的名字,方便之后用--remove删除,不加标签的话信号多了很难管理。
信号系统真正好用的地方在于处理例外。比如某些应用每次打开都会弹一个欢迎页,平铺之后会把整个布局撑乱;又比如某些设计软件的主窗口一旦被缩放就会错位。与其全局关掉管理,不如用信号做定点处理:
yabai -m signal --add event=window_created \ action="yabai -m window --toggle float" \ app="^某个设计软件$" label=design_float提示:信号里的应用匹配支持正则,写全名并加上首尾锚点
^...$,能避免匹配到同名前缀的其他应用,这个细节能省掉很多莫名其妙的误触发。
信号不要加太多。我一开始兴致上来写了十几条,结果窗口一多,每次创建都要串行执行一串命令,能明显感觉到卡顿。后来精简到三条,只处理最影响体验的场景,反而更顺。
2.4 脚本附加组件:能力与代价
第四个机制必须单独拿出来讲,因为它决定了你能用多少功能。
Yabai 的布局计算、规则管理、信号系统,这些都在用户态完成,不需要特殊授权。但“移动一个不属于自己的窗口”“切换空间”“设置窗口透明度”“给窗口画边框”这些操作,系统本身不开放对应接口,只能通过注入一段代码到系统窗口服务进程里实现,这就是所谓的脚本附加组件。
加载这个组件需要两步:一是在恢复模式下放宽系统完整性保护中的调试限制,二是每次系统重启后手动加载一次(可以写进配置自动化,但自动化本身也要权限)。这一步会实质性降低系统防护等级,我前面说过,办公设备和敏感环境不要做。
即使做了,也要接受两个现实问题。其一,系统每次大版本更新后大概率要重新处理,甚至可能暂时不可用,得等工具跟进适配。其二,部分新版系统还加入了额外的授权确认流程,需要每次开机点一下。
如果你的需求只是“窗口自动铺满、键盘切焦点”,完全不需要这一层。我在一台只用来写文档的机器上就没启用附加组件,只保留基础布局,用了几个月没有遇到任何阻碍。
3. 从零开始搭建:安装、配置、快捷键
3.1 安装与开机自启
安装走包管理器最省事。mac 上常见的做法是先装包管理器,再一条命令拉取:
brew install yabai装完之后先别急着配,手动启动一次确认能跑起来:
yabai --start-service如果终端没有任何报错,菜单栏区域也没有出现异常图标,说明进程已经起来了。接着让它随开机启动,这样每次登录就自动接管窗口:
brew services start yabai注意:如果你同时装了多个窗口管理工具,一定要先卸掉或者停掉其他的,两个工具同时接管窗口会导致焦点乱跳、窗口尺寸反复抖动,这类问题极难定位,我在这上面浪费过一个下午。
首次启动后系统会弹出辅助功能授权请求,去系统设置的隐私与安全性里手动勾选,这一步不做后面所有命令都会静默失败——静默失败是新手最容易踩的坑,命令不报错但也没有效果,很容易以为是配置写错了。
3.2 配置文件逐段拆解
Yabai 启动时会读取用户目录下的一个配置文件,通常是~/.yabairc。这个文件本质就是一个 shell 脚本,所以里面可以写任意 shell 逻辑,这也是它灵活的原因。
最基础的骨架长这样:
#!/usr/bin/env sh # 布局模式 yabai -m config layout bsp yabai -m config window_placement second_child yabai -m config split_ratio 0.50 # 间距 yabai -m config window_gap 8 yabai -m config top_padding 8 yabai -m config bottom_padding 8 yabai -m config left_padding 8 yabai -m config right_padding 8 # 鼠标行为 yabai -m config focus_follows_mouse autoraise yabai -m config mouse_follows_focus on逐条解释几个容易设错的值。
window_placement决定新窗口插进切分区域的哪一侧,可选first_child和second_child。默认值会让新窗口占据较大的一侧,我改成second_child,让新窗口固定进较小的一侧,这样主窗口(通常是编辑器)始终保持大面积不被挤压,符合我的使用习惯。
window_gap是窗口之间的缝隙,单位像素。设 0 是全贴合,视觉上很密;设 8 到 12 之间有明显呼吸感又不会浪费空间。我用 8,因为 27 寸屏幕上 12 会显得过于松散。
*_padding是屏幕边缘到窗口之间的内边距。这几个值存在的意义是给菜单栏、Dock 或者你自己加的状态栏留位置。如果你用了顶部状态栏工具,需要把top_padding设成状态栏高度,否则窗口会被压在状态栏下面看不到标题。
focus_follows_mouse控制鼠标移动时焦点是否跟随,autoraise表示跟随并把窗口提到前面。这条争议很大:喜欢的人觉得“指哪打哪”很自然,不喜欢的人觉得鼠标路过就抢焦点很烦。我的建议是先关掉(设成off),等键盘操作熟练了再考虑打开,否则一开始会频繁误切。
3.3 快捷键层的设计思路
Yabai 本身不接管键盘,它只提供命令。所以你需要一个按键映射工具,把“按键组合”翻译成“执行命令”。常见的做法是配一个轻量的按键守护进程(skhd是这类工具中比较常用的一个,同类工具还有几个,选顺手的即可),配置写在~/.skhdrc里。
# 焦点切换 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 + shift - h : yabai -m window --swap west alt + shift - l : yabai -m window --swap east # 空间切换 alt - 1 : yabai -m space --focus 1 alt - 2 : yabai -m space --focus 2 alt - 3 : yabai -m space --focus 3 # 窗口放入指定空间 alt + shift - 2 : yabai -m window --space 2 # 浮动切换与最大化 alt - return : yabai -m window --toggle zoom-fullscreen alt - t : yabai -m window --toggle float设计快捷键有三个原则,都是踩过坑之后总结的。
一是用alt做修饰键,不要用ctrl。ctrl在终端和编辑器里有大量既有绑定,抢占之后会痛苦不堪,尤其是 shell 里的ctrl+a、ctrl+e这类行编辑快捷键,被占用后连改命令都难。
二是用 h/j/k/l 而不是方向键。方向键需要把手移开主键区,vim 用户应该很熟悉这套映射,四个键正好对应左右上下,且和“焦点向某方向移动”的语义天然吻合。
三是加减号区分层级。不加shift是“移动焦点”,加shift是“移动窗口本身”,这个约定统一之后,几十条快捷键也不容易记混。中间再叠加数字键做空间操作,形成三个清晰的层级。
提示:快捷键配置文件改完必须重启对应的按键守护进程才生效。很多人改完发现没反应,其实只是没重载,别急着怀疑 Yabai 出问题。
3.4 应用规则:让不该被管理的窗口逃出去
规则系统解决的是“一刀切”的问题。有些窗口根本不该被平铺引擎接管,比如系统设置面板、文件选择对话框、视频小窗、某些带自定义绘制的应用。规则用一条命令添加:
yabai -m rule --add app="^系统设置$" manage=off yabai -m rule --add app="^访达$" manage=off yabai -m rule --add title=".*画中画.*" manage=off sticky=onmanage=off表示这个应用的窗口完全交给系统管理,平铺引擎不碰它。sticky=on表示这个窗口在所有空间都可见,适合画中画、便签、悬浮笔记这类工具。
规则里还可以用grid强制指定窗口出现在第几个空间的第几个位置,或者用display指定放到哪块屏幕。我实际只用了manage=off和sticky=on两种,其他参数用得很少——规则加得越多,行为越难预测,这是所有自动化配置的通病。
这里有个我个人的经验:不要一开始就写一大堆规则,先什么都不加跑两三天,把那些真的被铺坏了、影响使用的应用记下来,再针对性加规则。反过来做的话,你会给很多其实没问题的应用加上规则,最后配置越来越臃肿,出了问题也不知道是哪条导致的。
4. 一套可以直接照抄的日常配置
4.1 视觉参数:间距、内边距、圆角与边框
视觉这块纯看个人审美,但有几个参数会影响实际可用性,值得单独说。
window_gap别设太大。我试过 16,确实好看,但每切一次窗口都觉得屏幕被切碎了,能看的内容明显变少。8 到 10 是比较平衡的区间。多显示器的情况下,两块屏用同样的值容易在小屏上显得过密,可以把值写在条件判断里:
if [ "$(yabai -m query --displays --display | jq '.frame.w')" -gt 2000 ]; then yabai -m config window_gap 10 else yabai -m config window_gap 6 fi窗口边框和圆角属于“看起来是小事、实际影响辨识度”的部分。平铺之后窗口彼此紧贴,边界很容易模糊,加一条 1 到 2 像素的细边框,能明显改善“哪个窗口是焦点”的判断速度。边框的实现方式有两种:靠附加组件自带的绘制能力,或者用一个专门画边框的独立小工具。前者和 Yabai 深度集成但依赖附加组件,后者独立运行、不碰系统设置,我更倾向后者。
透明度我没开。平铺状态下窗口不重叠,透明度除了好看没有任何功能价值,反而增加渲染负担。只有一种情况我会开:需要对着参考图写东西时,临时把浏览器窗口调半透明叠在上面,用完立刻关掉。
4.2 多显示器与多空间的策略
多显示器和多空间是两个维度,容易混。显示器是物理的,空间是虚拟的。Yabai 把两者分开管理,命令也分开:display --focus切显示器,space --focus切空间。
我用的策略是“一屏一用途”。主屏放编辑器加终端,副屏放浏览器和沟通工具,第三块(如果有)放监控类的东西。切换显示器用固定快捷键,切换空间只用数字键,两套快捷键互不干扰。
一个必须提前知道的行为:mac 的每个显示器默认拥有独立的菜单栏和空间集合,当你在副屏上切换空间时,主屏的空间不会跟着变。这个设计本身挺好,但会让“按数字键切空间”这个操作产生歧义——到底是切哪块屏的空间?解决办法是在命令里明确指定目标显示器:
# 把焦点移到第 2 块屏 yabai -m display --focus 2 # 把当前窗口送到第 2 块屏 yabai -m window --display 2 # 把当前窗口丢到第 1 块屏的第 3 个空间 yabai -m window --space 3 --display 1另一个容易出问题的是外接屏拔插。笔记本插拔显示器时,窗口会重新计算布局,有时候某些窗口会被挤到看不见的位置。我的处理方式是写一个在显示器数量变化时触发的小动作,把所有窗口重新归位:
yabai -m signal --add event=display_changed \ action="yabai -m space --balance" label=rebalancespace --balance会把当前空间的所有窗口重新均分,相当于“重排一次”。这个命令在布局变得奇怪时也很好用,比逐个手动调整快得多。我甚至给它配了一个快捷键,一按就恢复整齐。
4.3 常用操作速查表
命令不少,但真正高频的就十来个。下面这张表是我贴在桌面便签上用了两个月的那一版,按使用频率排序。
| 操作意图 | 命令 | 使用频率 |
|---|---|---|
| 焦点移到某个方向的窗口 | yabai -m window --focus west | 极高 |
| 和相邻窗口交换位置 | yabai -m window --swap east | 高 |
| 把窗口移到相邻显示器 | yabai -m window --display 2 | 高 |
| 重排当前空间 | yabai -m space --balance | 高 |
| 窗口在浮动/平铺间切换 | yabai -m window --toggle float | 高 |
| 窗口占满当前区域 | yabai -m window --toggle zoom-fullscreen | 中 |
| 调整窗口尺寸 | yabai -m window --resize left:-50:0 | 中 |
| 查询当前窗口信息 | yabai -m query --windows --window | 中 |
| 切换全局布局模式 | yabai -m config layout stack | 低 |
| 临时关闭某项管理 | yabai -m window --manage off | 低 |
几个参数细节值得说明。--resize的格式是“方向:水平增量:垂直增量”,负数表示缩小、正数表示放大。比如left:-50:0是把左边界向右收 50 像素,也就是窗口变窄 50 像素。这个方向和直觉相反,第一次用容易生气,记住“移动的是边界不是窗口”就顺了。
--toggle zoom-fullscreen有个细节:它最大化的是“当前区域”而不是整个屏幕。如果一个窗口只占屏幕左半边,触发后它会占满左半边,而不是占满全屏。这个行为一开始让我困惑,后来发现这正是平铺式的合理逻辑——最大化是相对父容器而言的。
4.4 一个完整的启动脚本模板
把上面所有内容串起来,~/.yabairc的完整形态大概是这样的:
#!/usr/bin/env sh # ==== 基础布局 ==== yabai -m config layout bsp yabai -m config window_placement second_child yabai -m config split_ratio 0.50 yabai -m config auto_balance off # ==== 视觉 ==== yabai -m config window_gap 8 yabai -m config top_padding 8 yabai -m config bottom_padding 8 yabai -m config left_padding 8 yabai -m config right_padding 8 yabai -m config window_shadow off # ==== 鼠标 ==== yabai -m config focus_follows_mouse off yabai -m config mouse_follows_focus on yabai -m config mouse_modifier alt yabai -m config mouse_action1 move yabai -m config mouse_action2 resize # ==== 规则 ==== yabai -m rule --add app="^系统设置$" manage=off yabai -m rule --add app="^访达$" manage=off # ==== 信号 ==== yabai -m signal --add event=display_changed \ action="yabai -m space --balance" label=rebalance echo "yabai config loaded"最后那行echo看着多余,其实很有用:如果启动日志里能看到这句话,说明脚本确实被执行了;如果看不到,问题就出在加载环节而不是配置内容。区分“配置没生效”和“配置写错了”,第一步永远是打日志,这个小习惯帮我省过很多排查时间。
auto_balance off这个值单独说下。开着的话,每次窗口关闭后剩余窗口会自动重新均分,看起来更整齐;关掉的话,剩余窗口保持原来的尺寸比例。我选后者,因为关闭窗口后通常还想继续看剩下那个窗口的原始尺寸,突然放大反而打断思路。这个纯属偏好,没有对错。
5. 踩坑实录:常见故障与排查顺序
5.1 开机后配置不生效
这是最高频的问题,没有之一。表现是:重启或重新登录之后,窗口完全不受管理,但手动执行一条命令又立刻生效。原因基本只有一个——进程没随登录启动,或者启动得比配置加载早。
排查顺序我固定成三步。第一,确认后台服务状态,看它是不是真的在跑;第二,手动执行一条配置命令,看有没有反应,有反应说明进程在、只是配置没加载;第三,检查配置文件的路径和可执行权限,这个文件必须是可执行的 shell 脚本,权限不对的话会被静默跳过。
还有一个隐蔽的坑:配置文件里第一行的#!/usr/bin/env sh不能丢,丢了之后某些环境下脚本根本不会被执行。另外如果脚本里写了中文注释,注意文件编码,编码不对可能导致解析异常。我自己踩过一次,注释里的特殊符号导致整个文件解析中断,前面所有配置都没生效,排查了很久才发现问题在最后一行。
5.2 窗口拖不动、焦点乱跳
这个症状分两种,原因完全不同。
第一种是命令没反应但也不报错。九成是辅助功能授权没给到位,或者给了但系统在更新后重置了。解决办法是去隐私设置里把对应项目取消勾选再重新勾选,强制刷新一次授权状态。
第二种是焦点自己在跳。典型表现是鼠标没动,但当前窗口不断变化。原因是两个工具同时在抢窗口管理权,或者focus_follows_mouse打开了但鼠标停在了多窗口交界处。前者的解决方式是只保留一个窗口管理器;后者把focus_follows_mouse设成off就能立刻缓解,然后慢慢调。
还有一种较少见的情况:某些应用会创建一层透明的辅助窗口,平铺引擎把它当成真窗口管理,导致可视区域的布局错乱。判断方法是打开查询命令,看看当前空间的窗口数量是不是比肉眼看到的多。如果是,给那个应用加一条manage=off规则即可。
5.3 全屏应用、空间切换、外接屏的冲突
系统的原生全屏(绿灯那个)和平铺管理天然冲突。原生全屏会把窗口放到一个独立的空间里,并且禁用大部分窗口操作,平铺引擎在这期间基本失效。我的处理原则很简单:需要原生全屏的场景(看视频、演示),就先按alt+t切浮动再全屏,退出全屏后手动切回平铺。虽然多一步,但比让引擎和系统互相打架要省心。
空间切换的问题更微妙。系统的空间切换有动画,动画期间窗口尺寸变化事件会集中触发,如果这时候信号里有动作,可能会执行一连串操作,看起来像“抽风”。规避方式有两个:一是信号里避免绑定窗口尺寸变化这类高频事件;二是在动作前加一个短延迟,等动画结束再执行。
yabai -m signal --add event=space_changed \ action="sleep 0.3 && yabai -m space --balance" label=space_fix外接屏的冲突我前面提过,这里补充一个细节:镜像模式下很多命令会异常,因为两块屏显示同一块画布,坐标计算会混乱。需要平铺时用扩展模式,需要镜像时先暂停窗口管理进程,用完再启动。
5.4 故障速查表
把上面这些整理成一张表,遇到问题时按症状查,比从头读文档快得多。
| 症状 | 最可能原因 | 处理动作 |
|---|---|---|
| 命令无反应也不报错 | 辅助功能授权缺失或被重置 | 取消勾选后重新授权 |
| 开机后完全不生效 | 服务未随登录启动 | 检查服务状态,配置写进启动项 |
| 部分配置生效部分不生效 | 配置文件解析中断 | 从后往前逐段注释排查 |
| 焦点自己跳动 | 多个管理器抢权或鼠标跟随设置 | 只保留一个工具,关闭鼠标跟随 |
| 窗口尺寸反复抖动 | 信号绑定高频事件形成循环 | 移除相关信号,加延迟 |
| 某应用窗口变形 | 应用有自定义绘制层 | 为该应用加manage=off |
| 窗口消失找不到 | 被移到其他空间或屏外 | 查询窗口状态后--space拉回 |
| 空间切换后布局乱 | 动画期间事件集中触发 | 空间切换信号加短延迟 |
| 全屏后失去管理 | 原生全屏独占行为 | 先切浮动再全屏 |
| 外接屏后布局错乱 | 显示器变化触发重算 | 加display_changed信号重新平衡 |
注意:排查时一次只改一个变量。我见过不少人一次性改五六个配置项,结果问题消失了但不知道是哪条起的作用,下次再遇到依旧不会解决。慢就是快。
6. 长期维护与进阶玩法
6.1 配置版本化的必要性
配置文件这东西,改着改着就忘了当初为什么这么写。我最开始把所有东西堆在一个文件里,半年后某条规则导致了奇怪的行为,我花了两小时才定位到是它。
后来我做了三件事,成本很低但收益很大。第一,把配置文件放进版本管理,每次改动提交一次,写清楚改了什么、为什么改。出了问题直接回滚,比逐行注释快得多。第二,给每个配置段加注释,注明这行是为了解决什么具体场景,比如“这条是为了让某设计软件打开时不挤走编辑器”。第三,保留一份最小可用配置作为备份,当折腾过头导致完全跑不起来时,直接换成最小版恢复,再逐步加回。
顺便说一句,配置文件里不要写太长的单行命令。超过一屏宽度的命令几乎无法阅读和调试,拆成多行并且对齐参数,可读性会好很多。信号类的命令尤其容易写长,一定要拆。
6.2 几个值得试的扩展玩法
基础配置跑顺之后,还有几个方向值得投入时间,按性价比排序。
第一个是自动归位。给常用应用写好目标空间,通过信号实现“打开就自动送到指定位置”。比如浏览器总在第二空间、聊天工具总在第三空间,打开就不用管了。这个玩法收益最大,因为你不再需要记住每个应用在哪,习惯自动形成。
第二个是状态栏联动。把当前空间的窗口数量、当前聚焦的应用名显示在状态栏上,配合点击切换空间。这需要一点脚本能力,但做完之后对整体状态的感知会强很多,尤其是在多空间之间切来切去的时候。
第三个是场景化布局。写几个脚本,一键切换到“写作模式”(浏览器 + 文档双栏)、“调试模式”(编辑器 + 终端 + 日志三栏)、“会议模式”(单窗口全屏)。每个脚本就是几条命令的组合,切换时按一下。我用得最多的是写作模式和调试模式,两者来回切换的频率很高。
第四个是和其他工具联动,比如窗口焦点变化时触发输入法的自动切换,或者根据当前应用自动调整键位映射。这类玩法依赖较多,建议在基础稳定之后再尝试。
最后说一个我自己的判断:平铺式窗口管理的收益,在配置完成后的第三周才开始显现。前三天是纯粹的磨合期,会觉得处处别扭;第一周开始形成肌肉记忆;第三周之后,你会在用别人电脑时突然不知道该干什么——因为下意识伸手去按那些不存在的快捷键。这时候才算真正装上了。如果你现在正处在第三天想卸载的阶段,我的建议是再撑四天,把快捷键那张表打印出来贴在显示器边上,一周后再决定要不要留。
另外提醒一句:无论配置多顺手,务必留一份“紧急退出”的办法,比如记住进程名和终止命令,或者保留一个不启用窗口管理的登录账户。我有次配置写坏了,所有窗口都不受控地叠在一起,连配置文件都打不开,最后是靠终端强制退出才恢复。这种时候,能敲一条命令救命,比任何配置技巧都值钱。