Topit可以直观设置Mac窗口层级,Hammerspoon支持按应用程序名称自动分配窗口优先级,AppleScript手动修改NSWindowLevel数值则更适合高级调试与开发排查。

如果你想让终端窗口始终显示在浏览器上方,同时让笔记软件固定在所有窗口底层,需要注意的是:Mac系统原生并不支持按程序分别设置窗口层级。不过,借助Topit或Hammerspoon,依然可以更精准地控制不同应用窗口在Z轴上的显示位置。
用Topit一键设置指定程序窗口层级
这是最直观、基本无需编程的方法,适合绝大多数日常场景。Topit界面会直接列出当前所有正在运行的窗口,选中后即可快速置顶,几乎没有学习门槛。
启动Topit应用后,先确认它已经获得辅助功能权限和屏幕录制权限(【若未授权,将无法控制任何窗口】)。
在主界面左侧的窗口列表中,找到你希望调整层级的程序,例如“Terminal”或“VS Code”。
点击右侧对应窗口卡片上的“立即置顶”按钮,目标窗口会马上出现蓝色边框,并固定在最前层显示。
重复相同步骤,为另一个程序(如“Notes”)点击“置底”按钮(部分版本可能显示为“取消置顶”),该窗口就会自动下沉到普通窗口之下——Topit本质上是通过动态调整NSWindowLevel数值来实现这个效果,无需用户手动计算具体参数。
用Hammerspoon脚本按程序名自动设层级
如果你希望按照固定规则自动管理窗口层级,例如每次打开Chrome时都让它显示在Finder之上、但仍低于终端窗口,那么Hammerspoon是目前更稳定、也更灵活的解决方案。
方法一:基础窗口层级绑定
打开Hammerspoon配置文件init.lua,粘贴以下代码:
hs.hotkey.bind({"cmd", "alt"}, "T", function()
local win = hs.window.focusedWindow()
如果当前有处于聚焦状态的窗口,就把它设置为悬浮层级,也就是始终置顶
if win then win:setLevel(hs.window.level.floating) end
end)
这段脚本的含义是:当你按下Cmd+Alt+T时,会把当前聚焦的窗口设置为浮动层级(NSFloatingWindowLevel)。该层级高于普通窗口,但仍低于菜单栏与Dock。
方法二:按进程名自动分级
在init.lua中继续追加:
hs.application.watcher.new(function(name, type, app)
if name == "Terminal" then
for _, w in ipairs(app:allWindows()) do w:setLevel(hs.window.level.desktop) end
elseif name == "Safari" then
for _, w in ipairs(app:allWindows()) do w:setLevel(hs.window.level.floating) end
end
end):start()
这样设置后,Terminal窗口在启动时就会自动获得更高的层级(NSDesktopWindowLevel),而Safari则始终处于浮动层。需要注意的是,这一逻辑只会在应用启动时触发,因此已经打开的窗口通常需要重启对应应用后才会生效。
保存配置后,在Hammerspoon菜单栏图标上右键,选择 → Reload Config,即可立即启用新的窗口层级规则。
手动修改NSWindowLevel值(高级调试用)
这种方式只建议用于验证窗口层级行为或进行开发调试,不适合日常使用,因为操作不当很容易导致窗口异常,而且应用重启后设置也会失效。
第一步:获取目标窗口ID
在终端执行:osascript -e 'id of first application process whose frontmost is true',可得到类似com.apple.Terminal的Bundle ID。
第二步:用AppleScript强制设级
执行:osascript -e 'tell application "Terminal" to set level of first window to 24',其中24对应NSDesktopWindowLevel。
⚠️ 注意:这里使用的数值必须与系统预定义常量严格对应,例如20=NSNormalWindowLevel,21=NSFloatingWindowLevel,24=NSDesktopWindowLevel。只要填错,目标窗口就可能直接消失,甚至导致应用卡死,【并且无法撤销,只能强制退出该应用】。
第三步:验证结果
切换到其他应用后,观察目标窗口是否依然可见。若窗口不可见,通常说明层级值设置过低;若它遮挡了菜单栏或Dock,则说明层级值设得过高。
