QMK Breaking Changes - 2025 Nov 30 Changelog
Notable Features
Speculative Hold option for mod-taps: hold mods instantly while unsettled #25572
Speculative Hold makes mod-tap keys more responsive by applying the modifier instantly on keydown, before the tap-hold decision is made. This is especially useful for actions like Shift+click and Ctrl+scroll wheel with an external mouse, which can feel laggy with standard mod-taps.
The firmware holds the modifier speculatively. Once the key's behavior is settled:
- If held, the modifier remains active as expected until the key is released.
- If tapped, the speculative modifier is canceled just before the tapping keycode is sent.
Speculative Hold applies the modifier early but does not change the underlying tap-hold decision logic. Speculative Hold is compatible to use in combination with any other tap-hold options.
see the Speculative Hold documentation for more information.
Changes Requiring User Action
Updated Keyboard Codebases
| Old Keyboard Name | New Keyboard Name |
|---|---|
| 0xcb/splaytoraid/32u4 | 0xcb/splaytoraid |
| 0xcb/splaytoraid/rp2040_ce | 0xcb/splaytoraid |
| 1upkeyboards/sweet16v2/kb2040 | 1upkeyboards/sweet16v2 |
| 1upkeyboards/sweet16v2/pro_micro | 1upkeyboards/sweet16v2 |
| 40percentclub/gherkin/kb2040 | 40percentclub/gherkin |
| 40percentclub/gherkin/pro_micro | 40percentclub/gherkin |
| durgod/dgk6x/venus | durgod/dgk6x/venus_ansi |
Reduce tap dance memory usage, move state out of data #25415
The tap dance state has been separated from the action structure. Custom tap dance functions now receive the state as a separate parameter instead of accessing it through action->state.
If your keymap uses custom tap dance functions that access the tap dance state, you need to update your code.
- You can't use
action->state. Instead you need to calltap_dance_state_t *tap_dance_get_state(uint8_t tap_dance_idx)to get the state. - You now get a pointer to the state, so use
->notation rather than.notation to get fields from it.
Before:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
tap_dance_action_t *action;
switch (keycode) {
case TD(CT_CLN):
action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
if (!record->event.pressed && action->state.count && !action->state.finished) {
tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
tap_code16(tap_hold->tap);
}
}
return true;
}After:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
tap_dance_action_t *action;
tap_dance_state_t* state;
switch (keycode) {
case TD(CT_CLN):
action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode));
if (!record->event.pressed && state != NULL && state->count && !state->finished) {
tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
tap_code16(tap_hold->tap);
}
}
return true;
}Deprecation Notices
In line with the notice period, deprecation notices for larger items are listed here.
Remove override of QK_{LED,RGB}_MATRIX_TOGGLE keycode #25672
#24649 implemented genetic behavior, including keycodes, to cycle flags.
Any overriding of existing keycodes that duplicate this behavior will be removed to ensure consistency with core functionality.
Full changelist
Core:
- suspend: suppress wake up keypress (#23389)
- [Feature Improvement]add option to keep layer state when recording dynamic macros (#24418)
- Add generic handling to cycle LED/RGB Matrix flags (#24649)
- Implement
mod_tpacked struct (#25168) - Implement minimal connection update logic (#25334)
- Reduce tap dance memory usage, move state out of data (#25415)
- Refactor debounce algorithm with static allocation (#25515)
- Restructure Pixel Rain interval code (#25516)
- Guard remapping logic with MAGIC_ENABLE (#25537)
- Update default OLED font (#25565)
- Speculative Hold option for mod-taps: hold mods instantly while unsettled. (#25572)
- Simplify hue calculation in raindrops animation (#25587)
- Simplify tap_code16_delay (#25595)
- Debounce: Deprecate num_rows parameter (#25632)
- Add I2C Transmit and Receive function (#25637)
- [QP] Minor cleanup and support for RGB888 surface (#25706)
- Restrict mouse timer activation to movement keycodes (#25716)
- Update STM32F446 default HSE to 8MHz (#25717)
- making flowtap timer public so it can be used easily with combos (#25731)
- Add PixArt PAW-3222 mouse sensor driver (#25763)
- Merge upstream uf2conv changes (#25786)
- Partially skip generating community modules when none enabled (#25819)
CLI:
- Generate default encoder resolution for sparse config (#25247)
- Add DIP Switch map support to keymap.json (#25431)
- Add return code to
qmk userspace-doctor(#25775) - Better defaulting of
{RGB,LED}_MATRIX_DEFAULT_FLAGS(#25785) - add BCD versions of QMK Version (#25804)
- Lint error on missing keyboard readme (#25814)
Submodule updates:
- Update ChibiOS-Contrib. (#25751)
Keyboards:
atreus: restore intended matrix implementations (#24082)- add SteelSeries prime, a stripped down prime+ (#24719)
- Add new macropad Sharkropad (#24961)
- Addition of the D60B tsangan pcb (#25245)
- Migrate
eeconfig_init_kbimplementations to config (#25422) - Generate
CUSTOM_MATRIX = litewithoutmatrix_pins.custom(#25453) - Add classic48 keyboard (#25492)
- add durgod venus iso support (#25526)
- Migrate
g_led_configto DD (0-9, A) (#25558) - Migrate
g_led_configto DD (B, C) (#25559) - Migrate
g_led_configto DD (D) (#25560) - Migrate
g_led_configto DD (E, F) (#25561) - Remove duplication of RP2040 config defaults (#25563)
- Refactor 40percentclub/ut47 (#25571)
- E7-V2 Implementation (#25594)
- Migrate
g_led_configto DD (G) (#25598) - Migrate
g_led_configto DD (H) (#25599) - Migrate
g_led_configto DD (I) (#25600) - Migrate
g_led_configto DD (JK1) (#25601) - Migrate
g_led_configto DD (K2) (#25602) - Migrate
g_led_configto DD (K3) (#25603) - Migrate
g_led_configto DD (K4) (#25605) - Migrate
g_led_configto DD (K5) (#25606) - Migrate
g_led_configto DD (K6) (#25607) - Refactor
40percentclub/gherkin(#25608) - Refactor
0xcb/splaytoraid(#25609) - Refactor
1upkeyboards/sweet16v2(#25610) - Migrate
g_led_configto DD (K7) (#25616) - Migrate
g_led_configto DD (L) (#25617) - Migrate
g_led_configto DD (M1) (#25618) - Migrate
g_led_configto DD (M2) (#25619) - Migrate
g_led_configto DD (M3) (#25620) - Migrate
g_led_configto DD (NO) (#25621) - Migrate
g_led_configto DD (P) (#25622) - Migrate
g_led_configto DD (QR) (#25623) - Migrate
g_led_configto DD (S) (#25624) - Migrate
g_led_configto DD (TUW) (#25625) - Remove idobao *_DISABLE_UNDERGLOW behaviour (#25638)
- Migrate
g_led_configto DD (YZ) (#25650) - Tidy Keebio keyboards (#25653)
- Remove encoder resolution where duplicating defaults (#25654)
- Custom oled fonts cleanup (#25665)
- Binepad KnobX1 - refactor
x1_layer_ledfunction as weak (#25668) - Add DD {LED,RGB}_MATRIX_DEFAULT_FLAGS support (#25671)
- keyboards: Add Royal Kludge RK61 (#25694)
- Add TRKeyboard TRK2 keyboard (#25754)
Keyboard fixes:
- Fixup
kprepublic/bm60hsrgb/rev2(#25644) - Fixup
kprepublic/bm60hsrgb_iso/rev2(#25648) - Fixup
kprepublic/bm60hsrgb_poker/rev2(#25649) - Fixup
rgbkb/pan(#25678) - Align use of keymap level
_kbcallbacks (#25774)
Others:
- Rework converter docs (#18314)
- Update USBaspLoader ISP instructions (#25590)
- Add LED/RGB Matrix flags API docs (#25673)
Bugs:
- Fix single key combos activating only once (#25198)
- Fix RGB matrix not syncing and turning off properly on timeout (#25467)
- Fix drv haptics docs by using the correct function name (#25733)
- Fix Magic GUI masking logic (#25780)
- Fix Speculative Hold to enable also right-handed RSFT, RCTL by default. (#25797)
- Fix community layout keymap discovery (#25802)
- Fix preference of output file for 'qmk generate-autocorrect-data' (#25818)