用途
本技能用于在 macOS 上发出真正的 Fn 键(现代 MacBook 上亦称“地球”键),以便让宏键盘按钮、鼠标按钮或任意外部按键触发依赖 Fn 语义的功能,例如 Typeless 的按键通话(push-to-talk,默认 pushToTalk: "Fn")、macOS 听写(连按两下 Fn,或在系统设置中单按 Fn)、表情选择器(Fn+E)、经地球键唤起 Spotlight,以及在某些被 BTT 重映射后失效的应用专有 Fn 组合键。
问题背景
资料说明,macOS 的 Fn 键不是普通修饰键。它携带 kCGEventFlagMaskSecondaryFn 标志,而该标志若通过用户态的 CGEventPost 设置,会被 macOS 输入子系统在送达前丢弃。很多工具假设 Fn 与 Cmd / Option / Ctrl 行为一致,试图经 CGEventPost 发出 Fn,结果对听写、Typeless、macOS 听写快捷键、经地球键的 Spotlight、表情选择器等场景静默失败。资料称,用户态唯一能让内核接受 Fn 的路径是 DriverKit VirtualHIDDevice,而 Karabiner-Elements 自带该驱动,因此被视为 2026 年唯一能完成此任务的开源工具。
前提检查
资料列出以下检查项:
- Karabiner-Elements 是否已安装。资料给出的检查与安装命令为:
test -d /Applications/Karabiner-Elements.app && echo OK || brew install --cask karabiner-elements
- Karabiner 是否已获得“输入监控”与“辅助功能”权限。资料指明需在 系统设置 → 隐私与安全性 → 输入监控 中将 Karabiner 设为开启,并在 系统设置 → 隐私与安全性 → 辅助功能 中将 Karabiner 设为开启。
- 在 macOS Sequoia 及以上版本,是否已在登录项中批准特权守护进程。资料指明需在 系统设置 → 通用 → 登录项 → 允许在后台 中将 Karabiner-Elements Privileged Daemon 设为开启,否则 Karabiner 的 DriverKit VirtualHIDDevice 不会加载,Fn 重映射将静默无效。
资料还给出判断思路:若内置键盘直接按 Fn 可用,但经重映射不可用,则说明 DriverKit 守护进程已加载但重映射规则有误;若连内置 Fn 也失效,则需重新检查上述第 3 项。
核心事实
资料用对比方式说明:真实 Fn(来自键盘)经 硬件 → DriverKit → 带有 NX_DEVICE_CAPABILITY_INPUTKEYBOARD_FUNCTION 标志的 HIDEvent 路径,Typeless 与听写可以接受;而经 CGEventPost 的 Fn,其 kCGEventFlagMaskSecondaryFn 标志在到达输入子系统前被丢弃,Typeless 与听写永远不会触发。Karabiner-Elements 注册 DriverKit VirtualHIDDevice,当其重映射规则要求“发出 Fn”时,会走与硬件键盘相同的内核路径,NX_DEVICE_CAPABILITY_INPUTKEYBOARD_FUNCTION 标志得以保留,Typeless 与听写可以接受。
正确的写法
资料强调在 Karabiner manipulator 的 to 块中应使用:
{ "apple_vendor_top_case_key_code": "keyboard_fn" }
资料列出了无效写法:{"key_code": "fn"}(不存在该 key_code,会被静默忽略)、{"modifiers": ["fn"]}(只有修饰标志而无 key-down,不触发 Fn 语义)、{"consumer_key_code": "..."}(HID usage page 错误)、{"key_code": "function"}(不是 Karabiner 关键字)。资料解释,apple_vendor_top_case_key_code 命名空间对应 HID Usage Page 0x00FF(Apple Top Case)与 Usage 0x03(Keyboard Fn),即 Apple 自身内置键盘使用的描述符。
最小可用示例
资料给出将 Caps Lock(仅针对特定外部键盘,需调整 VID/PID)重映射为发出真实 Fn 的配置:
{
"description": "Caps Lock → Fn (on external keyboard)",
"manipulators": [
{
"type": "basic",
"from": { "key_code": "caps_lock" },
"to": [{ "apple_vendor_top_case_key_code": "keyboard_fn" }],
"conditions": [
{
"type": "device_if",
"identifiers": [{ "vendor_id": 19530, "product_id": 16725 }]
}
]
}
]
}
资料指出应将其放入 ~/.config/karabiner/karabiner.json → profile 0 → complex_modifications.rules。
验证
资料给出验证步骤:
open -a "Karabiner-EventViewer"
按下重映射后的按键,Main 标签页应显示 name: fn。资料说明 Karabiner 会把显示规范回“fn”,但底层发出的是携带内核标志的 Apple-Top-Case 变体。随后测试真实使用方(例如 pushToTalk: "Fn" 的 Typeless):按住时麦克风打开,松开时麦克风关闭并出现转写文本。
若 EventViewer 显示正确事件但 Typeless 不触发,资料建议:检查 Typeless 是否具有辅助功能权限;确认 Typeless 的 app-settings.json 中 pushToTalk 设为 "Fn"(不是 "fn",也不是 "Function");确认没有其他工具同时抢占 Fn —— 例如带 Fn 触发器的 BTT 会在 Typeless 看到事件前将其窃取。
重要限制:不要把 Fn 设为长按目标
资料警告,尝试用 Karabiner 的 to_if_alone + to_if_held_down 实现“轻按顶部按钮 → Return,长按顶部按钮 → Fn”会破坏系统级 Fn。资料记录 2026-04-21 的验证失败:加载含 to_if_held_down: [{"apple_vendor_top_case_key_code": "keyboard_fn"}] 的规则后,即使直接在键盘上按 Fn,macOS 原生 Fn 也停止产生 Fn,需要完整回滚。原因尚不清楚,可能与 Karabiner 的长按状态机持有 Fn 标志的方式与真实硬件 Fn 事件冲突有关。在 Karabiner 上游修复前,资料建议为 Fn 使用单独按钮。
其他方法失败的原因
资料说明:BTT 的“Trigger Key Sequence”和“Send Shortcut”动作经 CGEventPost 及 CGEventCreateKeyboardEvent + CGEventSetFlags 执行,kCGEventFlagMaskSecondaryFn 被 CGEventSetFlags 接受(不报错)但在送达前被输入事件管理器丢弃,Apple 从未记录该限制,且在 macOS 13 / 14 / 15 上表现一致。hidutil 的 property --set '{"UserKeyMapping":[...]}' 在 HID 报告层面工作,可交换键码,但无法合成 Fn 标志,因为该标志是键盘驱动(DriverKit 或 Apple 内置键盘驱动)根据所按按键逐事件计算设置的,无法在 HID 报告层面伪造。
在可刷写开发板上运行 QMK 时,若其 USB HID 报告描述符实际声明 Usage Page 0x00FF、Usage 0x03,并支持 NKRO + Apple Fn keycode,则可以原生发出 Fn,内核会接受,因为这是真实硬件报告。但廉价 Jieli/Realtek/CH57x 键盘不可刷写,其固件已烧录并暴露固定的 HID 描述符(通常是标准键盘 Usage Page 0x07),无法通过 QMK/VIA/Vial 重新刷写。可刷写开发板参见 https://github.com/qmk/qmk_firmware → APPLE_FN_ENABLE。
相关参考
资料列出的深层参考包括:../configure-macro-keyboard/references/03-patterns.md(Apple vendor Fn 编码模式与完整规则摘录)、../configure-macro-keyboard/references/04-anti-patterns.md(BTT CGEventPost 失败、轻按对长按 Fn 失败、Jieli 上 QMK/VIA 失败)、./references/failed-approaches.md(本特定任务的失败目录)。相关技能还有 configure-macro-keyboard(端到端设置流程,把本技能作为其中一个步骤)与 diagnose-hid-keycodes(若尚不清楚硬件发出的键码,应先用该技能确诊,再回到本技能重映射为 Fn)。
执行后反思
资料要求技能完成后进行反思:确认本 SKILL.md 为编辑前的规范文件;修复导致失败的指令;将效果优于预期的做法提升为推荐实践;当现实与文档不符时更新 vendor ID、键码或开源工具版本;并添加演化日志条目(或 04-anti-patterns.md 行),记录触发条件、修复与证据。资料强调不要推迟。