资讯详情

资讯详情

QMK Magic Keycodes:在运行时切换 Caps Lock、GUI 等键位行为的持久化键码

QMK Magic Keycodes在运行时切换 Caps Lock、GUI 等键位行为的持久化键码【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmwareMagic Keycodes 是 QMK 固件中一组以MAGIC_为前缀的特殊键码它们让你可以在键盘初始化完成之后随时启用或关闭传统上只能在开机瞬间生效的 Bootmagic 类行为交换 Caps Lock 与 Control、禁用 GUI 键、开启 NKRO 等。本文以 QMK 官方文档 keycodes_magic.md 为骨架结合 process_magic.c 的实际实现讲清楚这些键码的完整清单、触发时机、状态持久化机制以及如何在键位图中直接使用它们。读完本文你将掌握全部 35 个 Magic Keycode 的名称、缩写别名及功能语义Magic 键码为什么在键抬起瞬间才生效、状态为什么会跨重启保留MAGIC_ENABLE配置项如何控制该功能是否编入固件分体键盘上EE_HANDS专用键码的作用对象与限制。一、Magic Keycodes 是什么按 keycodes_magic.md 的定义Magic Keycodes 以QK_MAGIC_为前缀允许你在键盘初始化完成后访问已被废弃deprecated的 Bootmagic 功能。使用时与任何其他键码没有区别——把它们分配到键位图的任意位置即可。从设计动机看Bootmagic 原本只能在键盘上电、尚未枚举为 USB 设备时通过特定组合键生效用来做主机无关的键位交换比如把 Caps Lock 换成 Control。而 Magic 键码把这些操作变成了普通键码按下一次、状态立即写入 EEPROM之后每次重新插拔、重新初始化键盘这些设置都会自动恢复。二、完整键码清单下表完整继承自 keycodes_magic.md按功能分组便于查阅2.1 Caps Lock 相关键码别名说明QK_MAGIC_SWAP_CONTROL_CAPS_LOCKCL_SWAP交换 Caps Lock 与左 ControlQK_MAGIC_UNSWAP_CONTROL_CAPS_LOCKCL_NORM取消交换 Caps Lock 与左 ControlQK_MAGIC_TOGGLE_CONTROL_CAPS_LOCKCL_TOGG切换交换 Caps Lock 与左 Control状态QK_MAGIC_CAPS_LOCK_AS_CONTROL_ONCL_CTRL把 Caps Lock 当作 Control 使用QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFFCL_CAPS停止把 Caps Lock 当作 ControlQK_MAGIC_SWAP_ESCAPE_CAPS_LOCKEC_SWAP交换 Caps Lock 与 EscapeQK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCKEC_NORM取消交换 Caps Lock 与 EscapeQK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCKEC_TOGG切换交换 Caps Lock 与 Escape状态2.2 Alt / GUI / Control 交换键码别名说明QK_MAGIC_SWAP_LCTL_LGUICG_LSWP交换左侧 Control 与 GUIQK_MAGIC_UNSWAP_LCTL_LGUICG_LNRM取消交换左侧 Control 与 GUIQK_MAGIC_SWAP_RCTL_RGUICG_RSWP交换右侧 Control 与 GUIQK_MAGIC_UNSWAP_RCTL_RGUICG_RNRM取消交换右侧 Control 与 GUIQK_MAGIC_SWAP_CTL_GUICG_SWAP同时交换两侧的 Control 与 GUIQK_MAGIC_UNSWAP_CTL_GUICG_NORM同时取消两侧的 Control 与 GUI 交换QK_MAGIC_TOGGLE_CTL_GUICG_TOGG同时切换两侧的 Control/GUI 交换状态QK_MAGIC_SWAP_LALT_LGUIAG_LSWP交换左侧 Alt 与 GUIQK_MAGIC_UNSWAP_LALT_LGUIAG_LNRM取消交换左侧 Alt 与 GUIQK_MAGIC_SWAP_RALT_RGUIAG_RSWP交换右侧 Alt 与 GUIQK_MAGIC_UNSWAP_RALT_RGUIAG_RNRM取消交换右侧 Alt 与 GUIQK_MAGIC_SWAP_ALT_GUIAG_SWAP同时交换两侧的 Alt 与 GUIQK_MAGIC_UNSWAP_ALT_GUIAG_NORM同时取消两侧的 Alt 与 GUI 交换QK_MAGIC_TOGGLE_ALT_GUIAG_TOGG同时切换两侧的 Alt/GUI 交换状态QK_MAGIC_GUI_OFFGU_OFF禁用所有 GUI 键QK_MAGIC_GUI_ONGU_ON启用 GUI 键QK_MAGIC_TOGGLE_GUIGU_TOGG切换 GUI 键的启用/禁用状态2.3 标点键交换、NKRO 与分体手性键码别名说明QK_MAGIC_SWAP_GRAVE_ESCGE_SWAP交换与 EscapeQK_MAGIC_UNSWAP_GRAVE_ESCGE_NORM取消交换与 EscapeQK_MAGIC_SWAP_BACKSLASH_BACKSPACEBS_SWAP交换\与 BackspaceQK_MAGIC_UNSWAP_BACKSLASH_BACKSPACEBS_NORM取消交换\与 BackspaceQK_MAGIC_TOGGLE_BACKSLASH_BACKSPACEBS_TOGG切换\与 Backspace 交换状态QK_MAGIC_NKRO_ONNK_ON启用 N 键全冲N-key rolloverQK_MAGIC_NKRO_OFFNK_OFF禁用 N 键全冲QK_MAGIC_TOGGLE_NKRONK_TOGG切换 N 键全冲开关QK_MAGIC_EE_HANDS_LEFTEH_LEFT把分体键盘的主控半区设为左手配合EE_HANDS功能QK_MAGIC_EE_HANDS_RIGHTEH_RGHT把分体键盘的主控半区设为右手配合EE_HANDS功能注意CG_SWAP/AG_SWAP这类双侧键码在实现上会同时设置左右两个位见下文源码分析而TOGG系列每次按键翻转当前状态适合做成一个专用物理按键免去记状态的心智负担。三、键码取值范围与别名映射在 quantum/keycodes.h 中所有 Magic 键码被集中定义在0x70000x7022的连续枚举区间内QK_MAGIC_SWAP_CONTROL_CAPS_LOCK 0x7000, QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK 0x7001, QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK 0x7002, QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF 0x7003, QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON 0x7004, /* ... 中间省略 ... */ QK_MAGIC_EE_HANDS_LEFT 0x701E, QK_MAGIC_EE_HANDS_RIGHT 0x701F, QK_MAGIC_SWAP_ESCAPE_CAPS_LOCK 0x7020, QK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCK 0x7021, QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK 0x7022,同文件提供了区间判定宏quantum/keycodes.h#define IS_MAGIC_KEYCODE(code) ((code) QK_MAGIC_SWAP_CONTROL_CAPS_LOCK (code) QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK)处理器正是靠这个宏判断一个键码是否属于 Magic 家族。紧随其后的0x7100起则是 MIDI 键码区间二者互不重叠。文档表格中的短别名CL_SWAP、CG_TOGG、NK_ON等在 quantum/keycodes.h 中以枚举别名形式给出例如CL_SWAP QK_MAGIC_SWAP_CONTROL_CAPS_LOCK, CL_NORM QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK, CL_TOGG QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK, CL_CAPS QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF, CL_CTRL QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON, /* ... 其余别名与文档表格一一对应 ... */因此在键位图中两种写法完全等价短别名更节省字符、便于阅读。四、实现剖析按键抬起时生效状态写入 EEPROMMagic 键码的核心处理逻辑位于 quantum/process_keycode/process_magic.c 的process_magic()函数中它在 quantum/quantum.c 的主键码处理链中被调用且受编译开关MAGIC_ENABLE保护#ifdef MAGIC_ENABLE process_magic(keycode, record) #endif也就是说若固件未启用MAGIC_ENABLE这些键码不会被处理使用前需确认键盘或自定义配置中已打开该选项。4.1 只在键抬起keyup时触发函数开头有这样的判断bool process_magic(uint16_t keycode, keyrecord_t *record) { // skip anything that isnt a keyup if (record-event.pressed) { // QMK 中 pressed1 表示键抬起事件从源码结构看record-event.pressed为真时代表本次事件是键的抬起。结合注释 skip anything that isnt a keyup 可以推断Magic 键码刻意选择在松手瞬间才执行而不是按下瞬间。这样做的好处是用户可以按住 Magic 键不放而不产生任何副作用必须真正按完这次键状态才会改变避免误触。4.2 状态保存在 keymap_config 位域中每个 Magic 键码并不直接改动硬件行为而是翻转 quantum/keycode_config.h 中keymap_config_t联合体里的一个位域标志/* NOTE: Not portable. Bit field order depends on implementation */ typedef union keymap_config_t { uint16_t raw; struct { bool swap_control_capslock : 1; bool capslock_to_control : 1; bool swap_lalt_lgui : 1; bool swap_ralt_rgui : 1; bool no_gui : 1; bool swap_grave_esc : 1; bool swap_backslash_backspace : 1; bool nkro : 1; bool swap_lctl_lgui : 1; bool swap_rctl_rgui : 1; bool oneshot_enable : 1; bool swap_escape_capslock : 1; bool autocorrect_enable : 1; }; } keymap_config_t; STATIC_ASSERT(sizeof(keymap_config_t) sizeof(uint16_t), Keycode (magic) EECONFIG out of spec.);这是一个 16 位容器每个 Magic 功能占 1 个 bit。以CL_SWAP为例处理链是键抬起时执行eeconfig_read_keymap(keymap_config)从 EEPROM 读出当前配置命中case QK_MAGIC_SWAP_CONTROL_CAPS_LOCK分支置keymap_config.swap_control_capslock true所有分支处理完后统一执行eeconfig_update_keymap(keymap_config)把整个 16 位写回 EEPROM。正因为状态落盘在 EEPROM 的 keymap 区这些交换/开关在断电、重新插拔、重刷键位图后依然有效——这正是 Magic 相对普通一次性键码的本质优势。4.3 执行后立即清空键盘缓冲每个 Magic 分支处理完毕后都有eeconfig_update_keymap(keymap_config); clear_keyboard(); // clear to prevent stuck keysclear_keyboard()会清空当前按键缓冲防止交换动作生效前已经按下的键出现卡键stuck keys。开启/关闭 NKRO 的分支在改状态前还会额外调用一次clear_keyboard()process_magic.c注释明确写着 clear first buffer to prevent stuck keys因为 NKRO 模式切换会改变矩阵扫描与上报方式残留状态风险更高。4.4 双侧交换与音效反馈CG_SWAP/AG_SWAP这类双侧键码在源码里同时置位左右两个 bitcase QK_MAGIC_SWAP_ALT_GUI: keymap_config.swap_lalt_lgui keymap_config.swap_ralt_rgui true; #ifdef AUDIO_ENABLE PLAY_SONG(ag_swap_song); #endifTOGG系列则是取反后再同步两侧并按结果播放不同音效。从源码结构看只有 Alt/GUI 与 Control/GUI 这几组交换在启用AUDIO_ENABLE时会播放提示音AG_NORM_SOUND/AG_SWAP_SOUND对应 process_magic.c 中的ag_norm_song、ag_swap_song等定义其余 Magic 键码没有配套音效。4.5 EE_HANDS 键码的特殊路径与上述翻位域不同EH_LEFT/EH_RGHT直接更新手性配置case QK_MAGIC_EE_HANDS_LEFT: eeconfig_update_handedness(true); break; case QK_MAGIC_EE_HANDS_RIGHT: eeconfig_update_handedness(false); break;这两个键码只对手持两半的分体键盘有意义EE_HANDS功能会让固件记住主控半区在哪只手交换双手后各层/各功能的左右归属保持不变。未启用EE_HANDS的键盘上它们只更新存储值对用户可感知行为没有影响。五、在键位图中使用Magic 键码与普通键码一样直接写进keymap.c例如const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] { [0] LAYOUT( KC_A, KC_B, KC_C, CL_TOGG, NK_TOGG, KC_G, KC_H, GU_TOGG ), /* ... 其余层 ... */ };上面示例把CL_TOGG放在第 4 键随时切换 Caps Lock 与左 Control 是否交换NK_TOGG、GU_TOGG各占一键。使用前注意两点键盘或自定义配置中需启用MAGIC_ENABLE否则 quantum/quantum.c 中对应调用不会参与编译键码在松开时才生效且状态持久化到 EEPROM重刷默认键位图不会清除这些交换设置清除方式为重置 EEPROM 或写入默认值与一般 keymap_config 维护方式一致。六、小结Magic KeycodesQK_MAGIC_*取值0x7000–0x7022把已废弃的 Bootmagic 键位交换能力变成了运行时可触发的持久化键码共 35 个覆盖 Caps Lock、Alt/GUI/Control/GUI、/Esc、\/Backspace、NKRO 以及分体手性六类操作实现在 process_magic.c仅在键抬起时处理翻转 keycode_config.h 中keymap_config_t的对应位域随后经eeconfig_update_keymap()写入 EEPROM并调用clear_keyboard()防止卡键功能受MAGIC_ENABLE编译开关控制Alt/GUI 与 Control/GUI 交换在启用AUDIO_ENABLE时附带提示音短别名CL_SWAP、AG_TOGG、NK_ON等定义在 quantum/keycodes.h键位图中可与全名互换使用。若需进一步了解每个键码的取值完整清单见 keycodes_magic.md整体键码体系可参见 keycodes.md。【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →