今天排查了一个 BetterTouchTool 很有意思的边界问题:同一个“鼠标在屏幕底部滚轮调 SoundSource 音量”的配置,在 QQ、Finder 等窗口前台都正常,但 Chrome 前台时不触发。
现象
- Global 里有两条 Normal Mouse 触发器:
996/997。 - 在 BTT 里这两个代号分别是鼠标滚轮向下 / 向上。
- 这两条 Global 触发器的条件是
mouse_pos_percent_y < -98,也就是指针在屏幕底部。 - Chrome 里另外有几条 app-specific 的
996/997:- Cmd+scroll 缩放页面
- 顶部滚轮切标签
- 左边缘滚轮 Page Up / Page Down
- QQ 里没有 app-specific 的
996/997。
直觉上,Chrome 里的那些触发器和底部音量触发不冲突:顶部、左边缘、Cmd 修饰键、底部位置条件都不重叠。但实际表现是 Chrome 前台时 Global 底部滚轮触发不稳定或者不触发,QQ 前台则正常。
推断
这不是 Chrome 拦截了滚轮,也不是位置条件真的冲突,而是 BTT 对高频 mouse trigger 的匹配策略。
当当前 app 下面已经有同类 Normal Mouse / Mouse Wheel trigger 时,BTT 会优先进入当前 app 的 app-specific 规则层。即使这些 app-specific 规则的条件不命中,BTT 也不一定继续遍历 Global 里的同类 trigger。
BTT 作者 Andreas 在一个类似问题里也提过:mouse triggers 不会为了条件判断跨 app 全量循环查找所有可能命中的 trigger,主要原因是性能。类似问题见:
修复方式
最小修复是:给 Chrome 也复制一份底部音量触发器,让它进入 Chrome 自己的 996 / 997 规则层。
也就是说:
- Global 保留底部滚轮音量触发,给没有 app-specific 滚轮配置的应用使用。
- Chrome 单独放一份同样的底部滚轮音量触发,和 Chrome 的顶部切标签、左边缘翻页、Cmd+滚轮缩放处在同一层。
长期更干净的结构是:如果某类输入是高频 mouse wheel trigger,尽量不要混合依赖 app-specific 规则和 Global fallback,而是把相关规则放到同一层,用条件区分位置、修饰键和 app。
感想
BTT 现在功能很强,但也越来越臃肿。这类行为本质上是性能取舍:为了避免每次滚轮事件都遍历大量 app/global 条件,它牺牲了一部分“继承式配置”的直觉一致性。
这个坑比较隐蔽,因为从条件逻辑看完全不冲突,但从 BTT 的匹配层级看已经冲突了。