Releases: xdzgithub/FocusTrafficLight
Release list
v5.0.1 — 聚焦速度与双屏修复
v5.0.1 — 聚焦速度与双屏修复
功能与 v5.0.0 一致,修复若干聚焦速度与双屏行为问题。
系统要求
- macOS 27 及以上:使用本版本(v5.0.1)
- macOS 15 及更早:请使用 V4 版本(v4.0.6)
安装前请先退出正在运行的旧版本。升级后若提示需要辅助功能权限,请在「系统设置 → 隐私与安全性 → 辅助功能」中重新勾选本应用。
双屏
- 修复:双屏下同一应用各有窗口时,聚焦会让另一块屏上该应用的窗口闪烁一下。 根因是激活用了「应用级」调用,会把该应用的全部窗口抬到最前;现改为「窗口级」激活(只抬目标窗口,与鼠标点击窗口的行为一致),不再波及另一块屏
关闭(Cmd+W)
- 修复:关闭窗口后聚焦偏慢(Chrome 中位约 270ms,约 19% 超时跳过)。「关闭应用的最后一个窗口」原本会走到较慢的判定路径,现改走更早的信号;实测 Finder 106–118ms、系统设置 135–149ms、Chrome 256–273ms 且不再超时
- 未能识别窗口号的关闭、以及窗口数基线读取失败的边界情形,不再空等到超时
隐藏与最小化
- 修复:应用隐藏的等待时间缩短,实测隐藏墙钟由 94–106ms 降至 45–61ms
- 区分「元素销毁」与「应用隐藏」两类通知,元素销毁类单独设 400ms 上限(此前约三分之一要等满 1.2s)
可观测性
- 每次判定都会记录所用的信号来源,激活后若有显示器窗口顺序变化也会记录,便于以后定位这类问题
排查问题
log stream --predicate 'subsystem == "com.focustrafficlight.app"' --level noticev5.0.0 — macOS 27 Support
v5.0.0 — macOS 27 支持
macOS 27 移除了 v4 依赖的私有接口,导致焦点恢复失效。本版本改用公开 API 重写,功能与 v4 保持一致。
系统要求
- macOS 27 及以上:使用本版本(v5.0.0)
- macOS 15 及更早:请使用 V4 版本(v4.0.6)
安装前请先退出正在运行的旧版本。升级后若提示需要辅助功能权限,请在「系统设置 → 隐私与安全性 → 辅助功能」中重新勾选本应用。
功能
Cmd+W关闭窗口、Cmd+M最小化窗口后,焦点自动切换到下一个最顶层窗口- 点击窗口红灯 / 黄灯按钮同样生效
- 微信、QQ、飞书等自带隐藏快捷键的应用,隐藏后自动切换焦点
- 若当前应用还有其他窗口,焦点保持不动
- 多显示器下只聚焦「关闭窗口所在的那块屏」,不会切到另一块屏
- 菜单栏图标可一键启用 / 停用,支持开机自启
本版修复
- 关闭、最小化、应用隐藏在 macOS 27 上全部失效的问题
- 多 Space / 多显示器下误切换到其他 Space 的窗口
- Finder 桌面空格预览(Quick Look)误触发聚焦
- 双屏下聚焦范围收窄到「关闭窗口所在的那块屏」,且不再把另一块屏上同一应用的窗口一起置顶
- 关闭 / 最小化窗口后,动画结束前不再提前抢走焦点
排查问题
log stream --predicate 'subsystem == "com.focustrafficlight.app"' --level noticev4.0.6
v4.0.5
v4.0.5
- 修复:Chrome 下载浮层打开文件时,Archive Utility 等临时系统工具销毁窗口被误判为应用隐藏,导致焦点被抢回 Chrome
- 跳过 Archive Utility、Disk Image Mounter 的 AX 窗口通知,不再对临时系统工具执行焦点恢复
- 保留微信/QQ、飞书隐藏,
Cmd+W/Cmd+M、红黄点点击和桌面 Quick Look 的现有行为
功能逻辑不变:用户主动关闭、最小化或隐藏窗口后,自动聚焦当前 Space 最顶层的可见窗口。
v4.0.4
v4.0.3
V4.0.3
V4 对焦点恢复逻辑做了彻底重构,与 V3 的持续窗口监控方案完全不同。
程序逻辑调整
- 不再持续监听所有窗口的销毁/最小化事件,改为只响应用户显式动作
- 触发来源:
Cmd+W关闭窗口、Cmd+M最小化窗口、点击红灯关闭 / 黄灯最小化、应用自带隐藏快捷键(微信、QQ、飞书等) - 触发后只检查一次目标窗口,50ms 时确认窗口已从屏幕消失才聚焦;窗口仍在屏幕(例如浏览器关闭标签页)直接跳过,不做轮询
- 目标窗口消失后,自动聚焦当前 Space 最顶层的可见窗口
- 不再依赖 AX 窗口角色、尺寸、激活策略等启发式判断,v2rayN、Keynote 保存面板等非标准窗口也能正常聚焦
- 修复桌面 Quick Look(Finder 空格预览):Finder 前台时的 AX 销毁/最小化通知直接跳过,打开或关闭预览不再触发焦点误切换
附带防护
Cmd+H后 0.5 秒内的隐藏通知会被忽略,避免和系统自身的隐藏行为重复- 0.2 秒防抖合并快速重复触发,忽略长按自动重复的按键
- 后台应用的窗口销毁/最小化通知按 PID 过滤,不会抢焦点
其他
- 菜单栏一键开关,支持开机自启
- 全部监听事件驱动,空闲时几乎不占 CPU
v4.0.2
V4.0.2
V4 对焦点恢复逻辑做了彻底重构,与 V3 的持续窗口监控方案完全不同。
程序逻辑调整
- 不再持续监听所有窗口的销毁/最小化事件,改为只响应用户显式动作
- 触发来源:
Cmd+W关闭窗口、Cmd+M最小化窗口、点击红灯关闭 / 黄灯最小化、应用自带隐藏快捷键(微信、QQ、飞书等) - 触发后只检查一次目标窗口,50ms 时确认窗口已从屏幕消失才聚焦;窗口仍在屏幕(例如浏览器关闭标签页)直接跳过,不做轮询
- 目标窗口消失后,自动聚焦当前 Space 最顶层的可见窗口
- 不再依赖 AX 窗口角色、尺寸、激活策略等启发式判断,v2rayN、Keynote 保存面板等非标准窗口也能正常聚焦
- 移除 V3 的 Quick Look、Finder 预览、启动宽限等多层守卫逻辑
附带防护
Cmd+H后 0.5 秒内的隐藏通知会被忽略,避免和系统自身的隐藏行为重复- 0.2 秒防抖合并快速重复触发,忽略长按自动重复的按键
- 后台应用的窗口销毁/最小化通知按 PID 过滤,不会抢焦点
其他
- 菜单栏一键开关,支持开机自启
- 全部监听事件驱动,空闲时几乎不占 CPU
V3.4.0
v3.3.9 — Frontmost-Only AX Event Filter
v3.3.9 (2026-07-29)
Bug Fix: Frontmost-Only AX Event Filter
FocusEventMonitor now ignores AX events from non-frontmost applications. Background apps constantly create/destroy internal UI elements; previously any such event would trigger performRecoveryCheck(), which could steal focus back to the previous app during a user-initiated app switch.
The fix: only kAXUIElementDestroyedNotification / kAXWindowMiniaturizedNotification from the currently-frontmost app schedule a focus recovery check. This is a one-line PID comparison in the AXObserver callback — no time-based heuristics, no deferred retries.
v3.3.8 — Guard 2 CGWindowID Fallback
Fix — Window tiling / snapping focus loss
Guard 2 now passes when both CGWindowList and AX report visible windows for the frontmost app, even if the AXCGWindowID cross-reference fails.
Details
macOS window tiling, window snapping, and certain apps can have mismatched window IDs between AX and CGWindow. The v3.3.6 CGWindowID cross-reference was too strict — it treated any mismatch as "not visible", triggering unwanted focus recovery.
Preserved
- Ghost/hidden window filtering (v3.3.6): if CGWindowList has no windows for the app, Guard 2 still fails
- Launch grace period (v3.3.7): AXUIElementDestroyed from apps launched <2.0s ago are ignored