OpenFire 🔥

March 30, 2026 · View on GitHub

OpenFire 🔥

一个在 macOS 上支持“松开后点击执行”和“松开后按下拖拽再松开执行”的丝滑圆环菜单工具。

English简体中文

macOS 13.0+ Swift 5.9 License: MIT

OpenFire 演示 1 OpenFire 演示 2

OpenFire 的灵感同时来自 GTA V 和 PopClip,并在 UI、交互与性能上基于原生 Core Animation 和 Swift Concurrency 做了大规模重构与极速优化。


✨ 核心特性

🚀 电竞级响应速度 基于 mouseDown / mouseDragged / mouseUp 的底层命中测试,告别点击丢失。两种交互的共同前提都是:先完成选中文字,再松开鼠标,圆环才会触发。触发后有两种执行方式:

  • 松开后直接点一下执行:先选中文字,松开鼠标让圆环弹出,再点击目标扇区执行功能。
  • 松开后立即按下、拖拽到目标、再松开执行:先选中文字并松开触发圆环,随后立刻按下鼠标,拖到目标扇区,最后松开执行。

悬停高亮几乎零延迟,“指哪打哪”,第二种方式尤其像 GTA 5 的武器轮盘,而不是传统右键菜单。

💫 原生毛玻璃与 60FPS 动画 采用 NSVisualEffectViewCAShapeLayer 缓冲池,翻页、悬停、点击动画丝滑无掉帧。

🎛️ 高度可定制 UI 支持在菜单栏直接调节圆环的 背景透明度单页最大显示数量(6、8、12 或 16 个),也支持一键切换 GTA 氛围,把圆环切成更厚重的武器轮盘 HUD 风格。

🔌 热插拔插件系统 支持自定义 .openfireext 插件包。提供双击安装、后台线程异步加载、支持删除/禁用的包管理机制。

🧠 智能触发上下文 底层重写 Accessibility 识别逻辑。与“选中文本”直接相关的动作保留在主圆环里,而输入相关动作也会继续尊重“当前焦点是否真的可编辑”。

✂️ 更干净的快捷操作 当 OpenFire 检测到你点击的是可编辑输入框,且当前没有选中文本时,可以在光标附近弹出轻量的 Paste / Clear 胶囊操作条,方便快速粘贴,或直接清空当前剪贴板内容。当剪贴板为空时,这个快捷入口不会显示。内置 粘贴 动作在可编辑选区里也可以出现在主圆环中。

🚫 可定制黑名单应用 自带全自动黑名单管理 UI,支持拖拽添加应用、点击 + 浏览添加应用,精准屏蔽特定软件。


🚀 安装指南

安装步骤

  1. Releases 页面下载最新的 .dmg 安装包。
  2. 双击打开,将 OpenFire 图标拖入 Applications 应用程序文件夹。
  3. 运行 OpenFire。
  4. 前往 系统设置 → 隐私与安全 → 辅助功能,为 OpenFire 授予必须的辅助功能权限(用于监听文本选中事件)。

触发方式说明

OpenFire 实际上有 两个“打开圆环”的入口,之前容易和“打开后怎么执行动作”混在一起:

  1. 鼠标选中触发:正常框选文字,等你松开鼠标后,圆环才会出现。也就是说,圆环不会在按住拖拽选中的过程中提前弹出。
  2. 可选的手动快捷键触发:如果你在菜单栏里设置了 呼出菜单快捷键,OpenFire 也可以针对当前已选中的文本直接打开圆环,不必依赖“选中后松开鼠标”这条路径。

而在圆环已经出现之后,又有 两种执行动作的方式

  1. 选中,松开,再点击:圆环弹出后,直接点击目标扇区执行动作。
  2. 选中,松开,再按下拖拽,最后松开:圆环弹出后,立刻再次按下鼠标,拖到目标扇区,松开时执行动作。

第二种是 OpenFire 很有辨识度的交互方式:圆环一出现,你就可以立刻进入“按下-拖拽-松开”的武器轮盘式操作,而不必停下来改用传统菜单式的点按节奏。

如果你想排查“为什么会触发”或“为什么没有触发”,可以直接查看独立的诊断文档

当前触发逻辑概览

OpenFire 并不是“只要鼠标拖了一下就触发”。当前这版触发链路是偏保守的:

  1. 一次手势首先得看起来像真正的文本拖选。位移过短会被当成普通点击,而不是文本选择。
  2. 在尝试取文本之前,OpenFire 会先拦掉明显不是文本选择的场景:
    • 通过 drag pasteboard 识别出的文件拖拽
    • Finder、Dock、Desktop、OpenFire 自身这类前台文件管理或自干扰场景
    • 已知截图工具
    • 窗口拖拽:通过比较本次手势前后前台窗口 frame 是否真的发生变化来判断
  3. 如果这次手势通过了上面的过滤,OpenFire 会优先尝试原生 Accessibility 选区获取。
  4. 如果 Accessibility 没能及时拿到可用文本,就会退到受保护的 Cmd+C fallback
  5. 只有在某条链路真的拿到了非空选中文本后,圆环才会弹出。

实际效果可以理解成:

  • 原生编辑器里的普通文本选择,通常优先走 Accessibility
  • 浏览器和 WebView 里的文本选择,可能走 Accessibility,也可能走 Cmd+C fallback
  • Telegram 因为鼠标抬起时 AX 命中和焦点都不稳定,所以更依赖 Cmd+C fallback
  • 拖文件、拖窗口不应该触发圆环
  • 像 Finder 重命名这种“虽然应用本身通常被拦住,但当前确实进入可编辑文本态”的场景,仍然可以正常触发

Cmd+C fallback 到底是什么

Cmd+C fallback 是 OpenFire 在某些应用里拿不到稳定 Accessibility 选中文本时使用的兼容路径。

它不是“猜测你选中了什么”,而是按下面的步骤工作:

  1. 先保存当前系统剪贴板快照。
  2. 短暂等待一下,避免用户手势里残留的物理修饰键影响这次模拟复制。
  3. 发送一次合成的 Cmd+C
  4. 在一个很短的时间窗口里轮询系统 pasteboard,等待新的非空文本真正出现。
  5. 如果确认这次复制确实产出了新的文本,就把这段文本当作当前选中内容使用,并恢复之前的剪贴板快照。

这条路径主要是为下面这类应用准备的:

  • Telegram
  • Electron 应用
  • Accessibility 选区暴露不完整或时序很飘的浏览器 / WebView 宿主

它也不是“对所有拖拽都无脑复制”。即使走到 fallback,OpenFire 仍然会先判断这次手势是否像文本选择,而不是文件拖拽、窗口拖拽或其他非文本交互。与此同时,只有在确认这次模拟复制真的拿到了新的复制结果时,才会恢复旧剪贴板,从而尽量减少不必要的剪贴板抖动。

所以可以简单理解成:

  • Accessibility API 是首选路径
  • Cmd+C fallback 是兼容路径
  • 两条路径都要先通过“这次像是在选文本,而不是在拖文件或拖窗口”的判断

菜单栏可调项

OpenFire 常驻在 macOS 菜单栏里,主要设置都可以直接从这里调:

  • 圆环透明度0%(不透明)100%(完全透明)
  • GTA 氛围:切换成更重、更像 GTA 5 武器轮盘的 HUD 风格
  • 菜单最大功能数6 / 8 / 12 / 16
  • 呼出菜单快捷键:手动对当前已选中文本打开圆环。默认:Shift + Option + D
  • 自动触发开关快捷键:切换“选中文字后自动弹出圆环”功能。默认:Shift + Option + X
  • 插件管理黑名单应用

注意:开启 GTA 氛围 后,圆环会强制使用不透明渲染,因此透明度菜单会自动禁用。


🧩 插件生态

OpenFire 的强大之处在于插件自定义能力。插件以 .openfireext 文件夹形式存在,内含极简的 Config.json 配置。

默认预装插件

🔌 插件📝 功能描述
复制 / 剪切 / 删除直接作用于当前选中文本的基础编辑动作。
搜索 / 翻译 / 词典面向日常文本处理的常用动作,可直接搜索、翻译或调用 macOS 原生词典。
打开链接 / 打开文件位置这类内置动作会根据当前选中文本判断是否可执行,例如 URL 和文件路径。

这些默认预装插件属于 OpenFire 内置能力本身,可以在菜单栏里启用、禁用、排序,也可以直接编辑;编辑内置插件时,OpenFire 会在系统默认版本之上创建你的用户覆盖版本。 只要插件处于启用状态,就会在圆环里保留自己的位置;如果当前上下文不匹配,它会以灰态显示,而不是在分页前被直接过滤掉。 内置 粘贴 动作在当前焦点可编辑时可以进入主圆环;在空输入框场景下,它也会继续复用 Paste / Clear 胶囊入口。

社区生态插件

内置于安装包中,可随时通过“插件管理”界面启用或删除:


🛠️ 自己动手写插件

OpenFire 内置了功能完善的可视化插件编辑器,无需再手动编写繁琐的 JSON 配置文件!

  1. 点击 macOS 顶部状态栏的 🔥 OpenFire 图标。
  2. 在下拉菜单中选择 插件管理...
  3. 点击界面最下方中间的 + 按钮打开编辑器。
  4. 填写插件名称、图标,并选择动作类型即可完成创建。

支持的扩展类型 (Action type)

  • 🌐 url: 打开系统浏览器访问 {text}
  • 🐚 shell-script: 执行打包在插件里的 Shell 脚本,OpenFire 会通过环境变量注入选中文本
  • 🍎 applescript: 执行打包在插件里的 AppleScript,供插件处理当前选中文本
  • ⌨️ key-combo: 直接在 UI 上录制并发送系统快捷键
  • 📋 copy: 复制到剪切板
  • 📝 paste: 粘贴到当前输入区
  • 📂 reveal-path: 当选中文本是文件路径时,在 Finder 中打开对应位置

脚本类扩展

对于 shell-scriptapplescript,标准插件写法是让 action.script 指向 .openfireext 包内附带的脚本文件。OpenFire 也支持把简短脚本直接内联写进同一个 script 字段。当触发脚本时,OpenFire 会自动注入 $OPENFIRE_TEXTOPENFIRE_TEXT_FILE

推荐的插件结构

My Script.openfireext/
  Config.json
  script.sh

示例:引用 Shell 脚本文件

"action": {
  "type": "shell-script",
  "script": "script.sh"
}

示例:引用 AppleScript 文件

"action": {
  "type": "applescript",
  "script": "script.applescript"
}

短脚本也可以直接内联

"action": {
  "type": "shell-script",
  "script": "echo \"Selected: $OPENFIRE_TEXT\" >> ~/Desktop/openfire.log"
}

💻 技术栈简介

  • 语言与框架: Swift 5.9, AppKit, Objective-C Runtime 辅助
  • 渲染引擎: Core Animation (CAShapeLayer, CATextLayer, CATransaction 无阻塞动画)
  • 底层监听: CGEventTap, macOS Accessibility API (AXUIElement, AXObserver)
  • 并发控制: GCD (DispatchQueue.global) 与 Swift Concurrency 异步加载

📒 更新日志

请查看 CHANGELOG.md


📄 开源协议

OpenFire 采用 MIT License 协议开源。