复刻 Codex 权限引导交互:从逆向分析到开源实现
开源仓库:riko2chen/AskForPermission
一、背景
在 Codex 更新 Computer Use 能力后,其权限引导(Onboarding)的交互细节令人印象深刻:点击「Enable Accessibility」按钮后,系统设置窗口随即弹出;一张引导卡片沿着抛物线从按钮原位飞出,吸附停靠在系统设置窗口旁;卡片上展示宿主应用图标,用户只需将其拖入系统设置列表即可完成授权。落位时卡片与箭头带有细腻的过冲回弹,当用户拖动系统设置窗口时,指示箭头还会产生受惯性牵引拉伸的弹性形变。
macOS 的 TCC(Transparency, Consent, and Control)权限体系向来流程繁琐。多数应用通常仅弹出一个系统对话框,提示“请前往系统设置授权”,把复杂的查找路径留给用户。而 Codex 的这段引导则体现出对 macOS 系统机制的深入理解,通过视线引导和动作暗示,将原本割裂的授权流程转变为连贯顺畅的操作体验。
由于官方并未开源此段实现,社区现有的复刻方案在动画衔接和多场景适配上仍有缺失。为此,我通过逆向分析结合交互重构,完整复刻并开源了这套权限申请组件。
二、从纯视觉还原到逆向分析
2.1 第一阶段:基于录屏的视觉还原
最初的尝试是完全对照录屏逐帧拆解并编码还原,重点放在飞行动画与拖拽指引两个维度:
- 起点定位:卡片起飞位置是否精确对齐源按钮;
- 飞行轨迹:抛物线顶点高度与落位时的回弹阻尼;
- 属性渐变:飞行过程中卡片尺寸、圆角与阴影的过渡;
- 场景兼容:台前调度(Stage Manager)开启时的窗口行为。
然而第一版完成后的视觉质感与原版存在明显偏差,主要暴露两个工程问题:
- 起飞断层:由于无法精准捕捉窗口唤起的时机,动画往往从半途或窗口边缘突兀出现,原按钮与飞行卡片之间存在帧级脱节。
- 台前调度失效:在开启 Stage Manager 的环境下,唤起系统设置的瞬间,当前应用会被推移到屏幕左侧的缩略图堆叠(Pile)中。若未做特殊处理,飞行卡片会从一个正在移出的错误源头起飞,甚至直接飞落到屏幕外。
2.2 第二阶段:静态反编译与参数提取
为了探究底层实现,通过反编译工具分析了本地缓存中的 Codex macOS 插件二进制产物,提取其导出的符号、字符串常量以及布局参数:
- 动画机制:Codex 采用了两个独立视图控件做交叉淡入(Cross-fade),在位移过程中通过透明度渐变完成卡片形态转换;
- 视觉规格:获取了卡片尺寸、圆角半径以及内边距(Padding)的具体数值;
- 解耦结构:指示箭头的弹性形变与卡片本身的位移动画在逻辑上相互独立。
反编译给出了精准的静态参数,但仍存在局限:缓动函数与弹簧阻尼属于运行时组合,无法直接逆向;部分视图采用了自定义绘制,绕过了标准动画 API;且不同设备的显示缩放比与系统字体微调均会导致肉眼层面的视觉偏差。
因此,后续的重点转向了基于交互原理的自主重构与细节打磨。
三、关键交互重构与细节实现
3.1 单控件飞行方案
Codex 原版在飞行过程中同时使用两个控件:一个呈现源卡片样式,另一个呈现目标卡片样式,两者沿抛物线同步位移并通过透明度淡入淡出切换。
在复刻方案中,将其重构为单控件单一卡片方案:
- 整个生命周期内仅维护一个浮动窗口与卡片视图,源内容与目标内容在同一视图内完成插值过渡;
- 圆角(从 12pt 渐变至 24pt)、视图尺寸与窗口阴影在同一时间线上线性插值;
- 避免了多控件在复杂动画下可能出现的图层错位问题,同时减少了窗口与毛玻璃材质的渲染开销。
为了让内容变换更加自然,为模糊滤镜(Blur Filter)设计了钟形时间曲线:起点与终点模糊度归零,在抛物线顶点处达到峰值。卡片形态的切换恰好发生在最高点最模糊的瞬间,营造出在飞行中平滑变身的视觉感受。
3.2 消除起飞瞬间的视觉断层
在原版实现及多数开源尝试中,点击起飞瞬间常有短暂的空白:源按钮已经隐去,但飞行控件尚未渲染到位。我们通过以下流程消除了这一空隙:
- 瞬时快照:在用户点击的同一运行循环(RunLoop)内,直接捕获源按钮视图的渲染快照(读取自身窗口缓存,无需屏幕录制权限);
- 同帧占位替换:在启动飞行的前一帧,将原生按钮切换为虚线占位形态,同时将飞行卡片以相同的初始坐标覆盖在源按钮上方。
两项操作在同一帧内完成,利用飞行卡片完全遮盖源按钮的状态切换,肉眼看到的即是一张实体卡片从原地平滑升空。反向返回时逻辑对称,在抛物线最高点切换源按钮为完成态或恢复态,落地时无任何跳闪。
3.3 台前调度(Stage Manager)协同
Stage Manager 是 macOS 上极易导致浮动动画异常的系统特性。当系统设置被唤起时,宿主应用会被自动移出主屏幕。如果直接强行夺取应用焦点,会导致宿主应用与系统设置来回抢夺前台,光标与窗口剧烈抖动。
最终梳理出的协调时序如下:
触发打开系统设置 -> 监听设置窗口在 Stage Manager 下稳定落位 -> 激活宿主应用唤回前台 -> 从稳定位置计算坐标并起飞
必须严格按此顺序执行:若在 Stage Manager 调整窗口位置的中途计算源行坐标,会导致动画起点漂移。此外,飞行卡片与吸附引导卡的 NSWindow 必须显式去除 transient 标志,避免被 Stage Manager 误识别为主应用子窗口一同打包推走。
3.4 窗口恢复动画(Genie Effect)状态等待
若用户此前已将系统设置最小化至 Dock 栏,点击授权按钮时,系统会通过神奇效果(Genie Effect)恢复窗口。若此时直接读取窗口坐标,获取到的将是动画过渡中的中间帧,导致飞行卡片吸附在半空中。
为此建立了判定机制,满足以下任一条件即确认窗口落位稳定:
- 连续两次位置采样像素完全一致;
- 状态观察累计超时达到 1.2 秒(已完整覆盖系统恢复动画的最大耗时)。
3.5 指示箭头的反向惯性形变
引导卡片吸附在系统设置窗口边缘,当用户拖拽设置窗口时,卡片保持 1:1 刚性跟随。为增强交互的生动感,为指示箭头引入了基于速度的反向弹性形变:
- 高频采样窗口位移,计算出瞬时纵向速度;
- 窗口向下移动时,箭头反向向上拉伸(最大拉伸至 2 倍长度);窗口向上移动时则相应压缩;
- 窗口停止移动 150ms 后,箭头通过欠阻尼弹簧动画回弹复位,越过基准线后微幅震荡收敛;
- 停止 2 秒后额外触发一次轻微弹跳,作为交互的视觉结束信号。
反向形变模拟出如同拉拽橡皮筋的后坐力质感,使箭头在视觉上脱离刚性面板,具备独立的物理动量感。
3.6 拓展权限支持矩阵
Codex 原版仅支持「辅助功能(Accessibility)」与「屏幕录制(Screen Recording)」两项最常见的权限。本实现将引导覆盖范围扩展至 6 项:
| 权限类别 | PermissionKind 标识 | 授权机制特点 |
|---|---|---|
| 辅助功能 (Accessibility) | .accessibility | 系统设置静态列表,拖拽 App 授权 |
| 屏幕与系统音频录制 (Screen Recording) | .screenRecording | 系统设置静态列表,拖拽 App 授权 |
| 输入监控 (Input Monitoring) | .inputMonitoring | 系统设置静态列表,拖拽 App 授权 |
| 完全磁盘访问权限 (Full Disk Access) | .fullDiskAccess | 系统设置静态列表,拖拽 App 授权 |
| 开发者工具 (Developer Tools) | .developerTools | 动态符号解析,安全降级 |
| App 管理 (App Management) | .appManagement | 动态符号解析,安全降级 |
针对「开发者工具」与「App 管理」无公开查询 API 的限制,项目在运行时从 TCC 内部私有接口解析符号,且不添加编译期强依赖。若未来系统版本移除相关符号,会自动退化至未授权状态,确保应用稳定运行不崩溃。
四、TCC 授权状态与弹窗判定
用户将 App 图标拖入系统设置列表后,macOS 会触发二级系统弹窗确认。系统并未向宿主提供该弹窗的交互回调,因此需要自主推导授权状态。
项目通过组合监听四路信号进行判定,以最先命中者为准:
- 权限状态翻转:状态轮询检测到已授权,判定用户点击了「允许」;
- 在屏窗口数量回落:系统设置进程的窗口数从峰值下降,说明二级确认弹窗已被关闭;
- 应用前后台切换:宿主应用重获焦点,说明用户已切回主程序;
- 安全超时熔断:设置 10 秒最长等待超时。
在捕获到「弹窗关闭」类信号后,机制会额外延迟 200ms 再次读取 TCC 状态,以规避系统底层权限写入略滞后于 UI 销毁的时间差。整个判定过程仅利用公开的系统窗口列表与本地应用状态,无需任何额外系统权限。
五、工程取舍
- 拖拽后取消反向动画:当用户完成图标拖拽时,直接隐去引导卡片而不播放反向飞行动画。因为此时系统正在弹出原生的 TCC 确认框,过多的界面动效会干扰用户的决策焦点。
- 占位态平滑回退:源按钮在等待用户操作期间保持虚线占位态。若用户授权成功则平滑切至「已开启」,若超时或取消则直接恢复为初始按钮。
- 主动返回动画保留:仅当用户主动点击引导卡片上的「返回」按钮时,完整播放对称的反向飞行动画,让卡片平稳回归原位。
六、总结
Codex Computer Use 的权限引导之所以优秀,在于它充分利用了 AppKit 散落在各处的底层能力:从通过 URL Scheme 精准定位系统设置子面板,到构造独立浮动窗口实现跨应用吸附,再到对 Stage Manager 复杂窗口状态的精细调度。
复刻该交互的过程,本质是对 macOS 视窗渲染与系统交互细节的一次深入拆解与重构。通过单卡片插值、同帧快照占位、弹性惯性模拟以及全生命周期的状态判定,项目不仅还原了原版的灵动质感,还将适配范围拓展至多项系统权限。
项目现已开源,希望为 macOS 生态下的软件权限交互提供一份开箱即用、注重体验细节的工程参考。