# QMK Breaking Changes - 2025 Nov 30 Changelog ## Notable Features {#notable-features} ### Speculative Hold option for mod-taps: hold mods instantly while unsettled [#25572](https://github.com/qmk/qmk_firmware/pull/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](../tap_hold#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](https://github.com/qmk/qmk_firmware/pull/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 call `tap_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: ```c 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: ```c 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](../support_deprecation_policy#how-much-advance-notice-will-be-given), deprecation notices for larger items are listed here. ### Remove override of QK_{LED,RGB}_MATRIX_TOGGLE keycode [#25672](https://github.com/qmk/qmk_firmware/pull/25672) [#24649](https://github.com/qmk/qmk_firmware/pull/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](https://github.com/qmk/qmk_firmware/pull/23389)) * [Feature Improvement]add option to keep layer state when recording dynamic macros ([#24418](https://github.com/qmk/qmk_firmware/pull/24418)) * Add generic handling to cycle LED/RGB Matrix flags ([#24649](https://github.com/qmk/qmk_firmware/pull/24649)) * Implement `mod_t` packed struct ([#25168](https://github.com/qmk/qmk_firmware/pull/25168)) * Implement minimal connection update logic ([#25334](https://github.com/qmk/qmk_firmware/pull/25334)) * Reduce tap dance memory usage, move state out of data ([#25415](https://github.com/qmk/qmk_firmware/pull/25415)) * Refactor debounce algorithm with static allocation ([#25515](https://github.com/qmk/qmk_firmware/pull/25515)) * Restructure Pixel Rain interval code ([#25516](https://github.com/qmk/qmk_firmware/pull/25516)) * Guard remapping logic with MAGIC_ENABLE ([#25537](https://github.com/qmk/qmk_firmware/pull/25537)) * Update default OLED font ([#25565](https://github.com/qmk/qmk_firmware/pull/25565)) * Speculative Hold option for mod-taps: hold mods instantly while unsettled. ([#25572](https://github.com/qmk/qmk_firmware/pull/25572)) * Simplify hue calculation in raindrops animation ([#25587](https://github.com/qmk/qmk_firmware/pull/25587)) * Simplify tap_code16_delay ([#25595](https://github.com/qmk/qmk_firmware/pull/25595)) * Debounce: Deprecate num_rows parameter ([#25632](https://github.com/qmk/qmk_firmware/pull/25632)) * Add I2C Transmit and Receive function ([#25637](https://github.com/qmk/qmk_firmware/pull/25637)) * [QP] Minor cleanup and support for RGB888 surface ([#25706](https://github.com/qmk/qmk_firmware/pull/25706)) * Restrict mouse timer activation to movement keycodes ([#25716](https://github.com/qmk/qmk_firmware/pull/25716)) * Update STM32F446 default HSE to 8MHz ([#25717](https://github.com/qmk/qmk_firmware/pull/25717)) * making flowtap timer public so it can be used easily with combos ([#25731](https://github.com/qmk/qmk_firmware/pull/25731)) * Add PixArt PAW-3222 mouse sensor driver ([#25763](https://github.com/qmk/qmk_firmware/pull/25763)) * Merge upstream uf2conv changes ([#25786](https://github.com/qmk/qmk_firmware/pull/25786)) * Partially skip generating community modules when none enabled ([#25819](https://github.com/qmk/qmk_firmware/pull/25819)) CLI: * Generate default encoder resolution for sparse config ([#25247](https://github.com/qmk/qmk_firmware/pull/25247)) * Add DIP Switch map support to keymap.json ([#25431](https://github.com/qmk/qmk_firmware/pull/25431)) * Add return code to `qmk userspace-doctor` ([#25775](https://github.com/qmk/qmk_firmware/pull/25775)) * Better defaulting of `{RGB,LED}_MATRIX_DEFAULT_FLAGS` ([#25785](https://github.com/qmk/qmk_firmware/pull/25785)) * add BCD versions of QMK Version ([#25804](https://github.com/qmk/qmk_firmware/pull/25804)) * Lint error on missing keyboard readme ([#25814](https://github.com/qmk/qmk_firmware/pull/25814)) Submodule updates: * Update ChibiOS-Contrib. ([#25751](https://github.com/qmk/qmk_firmware/pull/25751)) Keyboards: * `atreus`: restore intended matrix implementations ([#24082](https://github.com/qmk/qmk_firmware/pull/24082)) * add SteelSeries prime, a stripped down prime+ ([#24719](https://github.com/qmk/qmk_firmware/pull/24719)) * Add new macropad Sharkropad ([#24961](https://github.com/qmk/qmk_firmware/pull/24961)) * Addition of the D60B tsangan pcb ([#25245](https://github.com/qmk/qmk_firmware/pull/25245)) * Migrate `eeconfig_init_kb` implementations to config ([#25422](https://github.com/qmk/qmk_firmware/pull/25422)) * Generate `CUSTOM_MATRIX = lite` without `matrix_pins.custom` ([#25453](https://github.com/qmk/qmk_firmware/pull/25453)) * Add classic48 keyboard ([#25492](https://github.com/qmk/qmk_firmware/pull/25492)) * add durgod venus iso support ([#25526](https://github.com/qmk/qmk_firmware/pull/25526)) * Migrate `g_led_config` to DD (0-9, A) ([#25558](https://github.com/qmk/qmk_firmware/pull/25558)) * Migrate `g_led_config` to DD (B, C) ([#25559](https://github.com/qmk/qmk_firmware/pull/25559)) * Migrate `g_led_config` to DD (D) ([#25560](https://github.com/qmk/qmk_firmware/pull/25560)) * Migrate `g_led_config` to DD (E, F) ([#25561](https://github.com/qmk/qmk_firmware/pull/25561)) * Remove duplication of RP2040 config defaults ([#25563](https://github.com/qmk/qmk_firmware/pull/25563)) * Refactor 40percentclub/ut47 ([#25571](https://github.com/qmk/qmk_firmware/pull/25571)) * E7-V2 Implementation ([#25594](https://github.com/qmk/qmk_firmware/pull/25594)) * Migrate `g_led_config` to DD (G) ([#25598](https://github.com/qmk/qmk_firmware/pull/25598)) * Migrate `g_led_config` to DD (H) ([#25599](https://github.com/qmk/qmk_firmware/pull/25599)) * Migrate `g_led_config` to DD (I) ([#25600](https://github.com/qmk/qmk_firmware/pull/25600)) * Migrate `g_led_config` to DD (JK1) ([#25601](https://github.com/qmk/qmk_firmware/pull/25601)) * Migrate `g_led_config` to DD (K2) ([#25602](https://github.com/qmk/qmk_firmware/pull/25602)) * Migrate `g_led_config` to DD (K3) ([#25603](https://github.com/qmk/qmk_firmware/pull/25603)) * Migrate `g_led_config` to DD (K4) ([#25605](https://github.com/qmk/qmk_firmware/pull/25605)) * Migrate `g_led_config` to DD (K5) ([#25606](https://github.com/qmk/qmk_firmware/pull/25606)) * Migrate `g_led_config` to DD (K6) ([#25607](https://github.com/qmk/qmk_firmware/pull/25607)) * Refactor `40percentclub/gherkin` ([#25608](https://github.com/qmk/qmk_firmware/pull/25608)) * Refactor `0xcb/splaytoraid` ([#25609](https://github.com/qmk/qmk_firmware/pull/25609)) * Refactor `1upkeyboards/sweet16v2` ([#25610](https://github.com/qmk/qmk_firmware/pull/25610)) * Migrate `g_led_config` to DD (K7) ([#25616](https://github.com/qmk/qmk_firmware/pull/25616)) * Migrate `g_led_config` to DD (L) ([#25617](https://github.com/qmk/qmk_firmware/pull/25617)) * Migrate `g_led_config` to DD (M1) ([#25618](https://github.com/qmk/qmk_firmware/pull/25618)) * Migrate `g_led_config` to DD (M2) ([#25619](https://github.com/qmk/qmk_firmware/pull/25619)) * Migrate `g_led_config` to DD (M3) ([#25620](https://github.com/qmk/qmk_firmware/pull/25620)) * Migrate `g_led_config` to DD (NO) ([#25621](https://github.com/qmk/qmk_firmware/pull/25621)) * Migrate `g_led_config` to DD (P) ([#25622](https://github.com/qmk/qmk_firmware/pull/25622)) * Migrate `g_led_config` to DD (QR) ([#25623](https://github.com/qmk/qmk_firmware/pull/25623)) * Migrate `g_led_config` to DD (S) ([#25624](https://github.com/qmk/qmk_firmware/pull/25624)) * Migrate `g_led_config` to DD (TUW) ([#25625](https://github.com/qmk/qmk_firmware/pull/25625)) * Remove idobao *_DISABLE_UNDERGLOW behaviour ([#25638](https://github.com/qmk/qmk_firmware/pull/25638)) * Migrate `g_led_config` to DD (YZ) ([#25650](https://github.com/qmk/qmk_firmware/pull/25650)) * Tidy Keebio keyboards ([#25653](https://github.com/qmk/qmk_firmware/pull/25653)) * Remove encoder resolution where duplicating defaults ([#25654](https://github.com/qmk/qmk_firmware/pull/25654)) * Custom oled fonts cleanup ([#25665](https://github.com/qmk/qmk_firmware/pull/25665)) * Binepad KnobX1 - refactor `x1_layer_led` function as weak ([#25668](https://github.com/qmk/qmk_firmware/pull/25668)) * Add DD {LED,RGB}_MATRIX_DEFAULT_FLAGS support ([#25671](https://github.com/qmk/qmk_firmware/pull/25671)) * keyboards: Add Royal Kludge RK61 ([#25694](https://github.com/qmk/qmk_firmware/pull/25694)) * Add TRKeyboard TRK2 keyboard ([#25754](https://github.com/qmk/qmk_firmware/pull/25754)) Keyboard fixes: * Fixup `kprepublic/bm60hsrgb/rev2` ([#25644](https://github.com/qmk/qmk_firmware/pull/25644)) * Fixup `kprepublic/bm60hsrgb_iso/rev2` ([#25648](https://github.com/qmk/qmk_firmware/pull/25648)) * Fixup `kprepublic/bm60hsrgb_poker/rev2` ([#25649](https://github.com/qmk/qmk_firmware/pull/25649)) * Fixup `rgbkb/pan` ([#25678](https://github.com/qmk/qmk_firmware/pull/25678)) * Align use of keymap level `_kb` callbacks ([#25774](https://github.com/qmk/qmk_firmware/pull/25774)) Others: * Rework converter docs ([#18314](https://github.com/qmk/qmk_firmware/pull/18314)) * Update USBaspLoader ISP instructions ([#25590](https://github.com/qmk/qmk_firmware/pull/25590)) * Add LED/RGB Matrix flags API docs ([#25673](https://github.com/qmk/qmk_firmware/pull/25673)) Bugs: * Fix single key combos activating only once ([#25198](https://github.com/qmk/qmk_firmware/pull/25198)) * Fix RGB matrix not syncing and turning off properly on timeout ([#25467](https://github.com/qmk/qmk_firmware/pull/25467)) * Fix drv haptics docs by using the correct function name ([#25733](https://github.com/qmk/qmk_firmware/pull/25733)) * Fix Magic GUI masking logic ([#25780](https://github.com/qmk/qmk_firmware/pull/25780)) * Fix Speculative Hold to enable also right-handed RSFT, RCTL by default. ([#25797](https://github.com/qmk/qmk_firmware/pull/25797)) * Fix community layout keymap discovery ([#25802](https://github.com/qmk/qmk_firmware/pull/25802)) * Fix preference of output file for 'qmk generate-autocorrect-data' ([#25818](https://github.com/qmk/qmk_firmware/pull/25818))