QMK 固件 2026-05-31 更新日志解读:isLeftHand 移除、FORCE_NKRO 弃用与 NKRO 默认值的新配置方式

QMK 固件 2026-05-31 更新日志解读:isLeftHand 移除、FORCE_NKRO 弃用与 NKRO 默认值的新配置方式

【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware

本篇围绕 QMK 固件的 2026-05-31 版本更新日志(docs/ChangeLog/20260531.md)展开,解读其中两项影响面最广的弃用变更——isLeftHand全局变量的移除与usb.force_nkro/FORCE_NKRO的弃用——并说明各自的迁移路径与三种新的 NKRO 默认值配置方式。读完后,你可以完成键盘代码的兼容性迁移,并通过keyboard.json、keymap.json或config.h正确地为整键板设置 NKRO 启动默认值。

更新日志在 QMK 文档体系中的定位

QMK 的破坏性变更集中记录在docs/ChangeLog/目录下的日期命名日志中,本篇对应的文件为 docs/ChangeLog/20260531.md。按照 QMK 的支持/弃用政策,较大规模的弃用项需要预留公告周期:日志先发布“Deprecation Notices(弃用通知)”,说明替代方案,随后在后续版本中实际移除。因此这份 2026-05-31 日志实际上对应的是“通知期结束、正式移除”这一阶段:

  • 拆分键盘的全局布尔变量isLeftHand被移除,替代 API 是is_keyboard_left();
  • 配置项usb.force_nkro与宏FORCE_NKRO被移除,NKRO 启动默认值改为通过主机层(host)配置或NKRO_DEFAULT_ON宏指定。

变更一:移除已弃用的 isLeftHand,迁移到 is_keyboard_left()

原问题:全局变量 vs 函数

旧版 QMK 中,拆分键盘(Split Keyboard)通过全局布尔变量isLeftHand判断当前固件实例运行在左半还是右半。这种方式要求键盘侧代码直接引用一个外部符号,且与is_keyboard_master()这类“主从判断”的 API 在风格上不统一。本次更新按 [PR #25897] 移除了该全局变量,统一使用函数调用is_keyboard_left()。

迁移示例

更新日志给出的标准迁移 diff 如下(以 OLED 初始化回调为例):

oled_rotation_t oled_init_user(oled_rotation_t rotation) { - return isLeftHand ? OLED_ROTATION_180 : OLED_ROTATION_0; + return is_keyboard_left() ? OLED_ROTATION_180 : OLED_ROTATION_0; }

只需把isLeftHand直接替换为is_keyboard_left()调用,语义不变。

源码层面的佐证

在当前仓库快照中,is_keyboard_left()的声明位于 quantum/keyboard.h,其弱(weak)默认实现在 quantum/keyboard.c 第 378~384 行附近:

/** \brief is_keyboard_left */ __attribute__((weak)) bool is_keyboard_left(void) { return true; }

可以看到两点实现细节:

  1. 函数带有__attribute__((weak))修饰,即框架提供默认实现,拆分键盘平台会提供覆盖版本;单侧板(非SPLIT_KEYBOARD)下该函数返回true。
  2. 框架自身代码已全面改用函数形式。例如 quantum/bootmagic/bootmagic.c 中if (!is_keyboard_left())的左右侧判断,以及 quantum/dip_switch.c 中 DIP 开关的左右侧同步逻辑,均调用is_keyboard_left()而非读取全局变量。

注意:更新日志原文表述为“is_keyboard_left()可在split_util.h中找到”。在当前仓库快照中,拆分相关工具头文件位于 quantum/split_common/split_util.h,而该函数的原型声明实际位于 quantum/keyboard.h。编写代码时以实际头文件声明为准,包含键盘侧通用头文件即可正常使用该函数。

变更二:移除 usb.force_nkro / FORCE_NKRO,NKRO 默认值改由 host 配置控制

为什么移除

QMK 历史上存在usb.force_nkro配置项与FORCE_NKRO宏,作用是“每次启动时强制启用 NKRO(N-Key Rollover,全键无冲)”。这一设计的隐含前提是:只有 USB 传输的键盘才需要强制 NKRO(因为 USB HID 存在按键去重问题,而某些 PS/2 等传输则不受影响)。

但从日志的说明看,这个假设已经不成立——QMK 不再把 NKRO 视为 USB 独有能力。更关键的是实际使用层面的问题:force_nkro是一个持久化(persist)配置,它会让NK_TOGG等一系列 NKRO 相关键码在用户预期之外改变行为,造成不必要的困惑。因此本次更新移除了“启动即强制”这一机制,改为只允许设置默认值,运行时状态仍可像以前一样通过NK_TOGG等键码切换。

三种配置新默认值的方式

移除FORCE_NKRO后,NKRO 的启动默认值可以通过以下三种方式配置(三者任选其一,效果均为“开机 NKRO 开启”)。

方式 1:keyboard.json(数据驱动配置)
{ "host": { "default": { "nkro": true } } }

该字段有 schema 与模板支撑:"nkro"布尔字段已定义在 data/schemas/keyboard.jsonschema("nkro": {"type": "boolean"}),官方键盘模板 data/templates/keyboard/keyboard.json 中也包含"nkro": true示例。对于使用 Configurator/数据驱动配置流程的键盘,这是推荐写法。

方式 2:keymap.json(键位映射层)
{ "config": { "host": { "default": { "nkro": true } } } }

keymap.json中同样的host.default.nkro字段允许在键位映射层面覆盖默认值,适合“同一块键盘、不同键位方案使用不同 NKRO 策略”的场景。

方式 3:config.h(传统 C 宏)
#pragma once #define NKRO_DEFAULT_ON true

源码层面的佐证

NKRO_DEFAULT_ON的消费点在 quantum/eeconfig.c 中。该文件第 50~52 行定义了回退默认值,第 89 行在初始化键位配置时赋给它:

#ifndef NKRO_DEFAULT_ON # define NKRO_DEFAULT_ON false #endif
keymap_config_t keymap_config = { .swap_control_capslock = false, // ... .nkro = NKRO_DEFAULT_ON, };

由此可以确认完整的默认值决策链:

  1. 若用户通过keyboard.json/keymap.json设置了host.default.nkro,则数据驱动配置在构建期生成对应定义;
  2. 否则若config.h中定义了NKRO_DEFAULT_ON,则使用用户定义值;
  3. 若两者都没有,则回退到false,即启动时 NKRO 关闭,与传统FORCE_NKRO未启用时的行为一致。

同时要注意一个行为差异:旧FORCE_NKRO是“每次启动都强制”,新机制只决定初始默认值,之后NK_TOGG等键码可以正常改变状态,这正是日志中“消除用户困惑”意图的体现。

完整变更清单(Full changelist)

以下为 2026-05-31 更新日志中的完整条目,按原始分类整理(保留 PR 编号以便检索):

Core(核心)

  • 移除已弃用的isLeftHand(#25897)
  • 支持“输出 Unicode”或“插入 Leader 序列”两种行为(#25940)
  • 为 digitizer(数位板类输入设备)添加分辨率信息(#25958)
  • 构建时始终生成.map文件(#25961)
  • 为 kiibohd 启动器添加mcu_reset实现(#25963)
  • 升级 VIA 至 v13(#26001)
  • 新增 PixArt PMW-3325 鼠标传感器驱动(#26065)
  • AT32 平台 wear leveling(磨损均衡)后备存储从 16 位升级到 32 位(#26066)
  • 重构 Pixel Fractal 灯效(#26071)
  • combo 代码的小型优化(#26073)
  • Speculative Hold 新增约束选项:SPECULATIVE_HOLD_ONE_KEY与SPECULATIVE_HOLD_FLOW_TERM(#26099)
  • 添加std::setw头文件包含(#26153)
  • gtest 颜色输出绑定到 QMK 的COLOR变量(#26159)
  • 修复测试名称打印错误(#26160)
  • 测试拆除阶段忽略 Uninteresting test 警告(#26161)
  • 移除FORCE_NKRO(#26206)

CLI(命令行工具)

  • lint 检查范围扩展到仓库内所有键位映射(#25970)
  • 检测到重复模块名时直接报错失败(#26238)

子模块更新(Submodule updates)

  • 更新 ChibiOS、ChibiOS-Contrib(#25730)
  • 回滚上述 ChibiOS 更新(#26074)
  • ChibiOS、ChibiOS-Contrib 再次更新(#26079)
  • googletest 升级到 v1.16.0(#26154)

Keyboards(键盘侧)

  • url字段不允许为空(#25152)
  • 新增 nomis/rpi_pico_25x1 宏键盘(#25346)
  • 移除对QK_{LED,RGB}_MATRIX_TOGGLE键码的覆盖(#25672)
  • SouthPad v2 增加反向布局(#25707)
  • 新增 Handwired Bouvet 宏键盘(#26040)
  • 移除 blockader 用户键位映射(#26075)
  • 移除已弃用的音频引脚定义(#26111)
  • 移除OLED_DISPLAY_128X32配置(#26190)
  • 迁移SPLIT_OLED_ENABLE(#26194)
  • 为 split_data_sync 模块添加 API 版本断言(#26237)

Others(其他)

  • 文档站点 VitePress 升级到 1.6.4(#26067)
  • docs/features/unicode.md 补充使用方式说明(#26156)

Bugs(缺陷修复)

  • 修复USER_PRINT预处理错误剥离uprintf的问题(#25919)
  • 修复 repeat key 可能陷入无限递归的问题(#25926)
  • 修复arm-none-eabi-gcc下cc-option行为(#26114)
  • 修复arm-none-eabi-gcc的颜色诊断输出(#26115)
  • 修复 retro tap 后注销按键时未屏蔽仍激活的修饰键(#26127)
  • 修复 macOS Tahoe 上make test:all的失败(#26136)
  • 为 mingw 工具链下弱符号未定义引用问题添加变通方案(#26167)
  • ws2812-pwm:允许覆盖WS2812_PWM_TICK_FREQUENCY(#26186)
  • 将鼠标上报值裁剪到 USB 描述符定义的逻辑范围内(#26195)
  • 对齐鼠标 USB 描述符(#26230)

值得关注的其他核心变更解读

VIA 升级到 v13

VIA 是 QMK 的图形化按键配置协议,本次升级至 v13(#26001)。使用 VIA 的键盘固件在升级后,建议同步使用支持该协议版本的 VIA 前端,避免新旧协议混用带来的兼容问题。

鼠标传感器与鼠标上报

本周期与鼠标(数字小键盘/数位输入设备方向)相关的变更较多:新增 PixArt PMW-3325 传感器驱动(#26065)、digitizer 分辨率信息(#25958),以及两处鼠标上报相关的缺陷修复——把上报值裁剪到 USB 描述符逻辑范围内(#26195)和对齐鼠标 USB 描述符(#26230)。从源码结构看,这几项共同收紧了 QMK 作为复合 HID 设备(键盘 + 鼠标)时的边界正确性。

构建与测试基础设施

  • 始终生成.map文件(#25961):.map文件记录符号与段布局,对排查“flash/RAM 溢出”类问题非常有用,此变更让该产物不再依赖特定构建选项。
  • 测试体系:googletest 升级 v1.16.0、gtest 颜色绑定COLOR变量、修复测试名称打印、忽略 teardown 阶段警告(#26153~#26161 区间内的一组 PR),整体改善make test:all的输出可读性,并修复了 macOS Tahoe 上的测试失败(#26136)。
  • CLI 严格化:lint 现在会检查仓库内所有键位映射(#25970),且检测到重复模块名时构建直接失败(#26238)。对提交新键盘/键位映射的贡献者而言,重复模块命名将成为硬性错误。

键盘侧清理项

本周期键盘目录还有一组“移除/迁移”类变更,如果你在维护自己的键盘,值得对照检查:

  • 音频引脚定义清理:已弃用的AUDIO_PIN相关旧宏被移除(#26111),应使用新版音频引脚定义方式;
  • OLED 配置迁移:OLED_DISPLAY_128X32配置被移除(#26190),SPLIT_OLED_ENABLE完成迁移(#26194),拆分 OLED 键盘需要检查自己的rules.mk/配置是否仍引用旧符号;
  • 元数据约束:键盘url字段不允许为空(#25152),信息不完整的键盘定义将无法通过校验。

迁移建议小结

如果你正在升级依赖旧接口的键盘或键位映射,建议按以下顺序自查:

  1. 全局搜索isLeftHand,统一替换为is_keyboard_left()(声明见 quantum/keyboard.h,默认实现见 quantum/keyboard.c);
  2. 全局搜索FORCE_NKRO与force_nkro:若原来依赖“开机强制 NKRO”,改为在keyboard.json/keymap.json的host.default.nkro或config.h的NKRO_DEFAULT_ON中设置默认值(默认值消费逻辑见 quantum/eeconfig.c);
  3. 检查 OLED 与音频配置:确认未再引用已移除的OLED_DISPLAY_128X32、SPLIT_OLED_ENABLE(旧用法)及已弃用音频引脚宏;
  4. 重新构建并检查.map输出:现在每次构建都会生成.map文件,可顺手确认 flash/RAM 占用是否仍在余量之内。

以上所有条目与配置方式均以当前仓库中 docs/ChangeLog/20260531.md 的记载及对应源码实现为准;PR 编号(如 #25897、#26206)可用于在变更历史中检索原始讨论。

【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考