docs/ChangeLog/20230226.md
IGNORE_MOD_TAP_INTERRUPT behaviour changes (#15741) {#i-m-t-i}IGNORE_MOD_TAP_INTERRUPT_PER_KEY has been removed and IGNORE_MOD_TAP_INTERRUPT deprecated as a stepping stone towards making IGNORE_MOD_TAP_INTERRUPT the new default behavior for mod-taps in the future.
In place of the now removed IGNORE_MOD_TAP_INTERRUPT_PER_KEY, one must use the pre-existing HOLD_ON_OTHER_KEY_PRESS option.
In most cases, updating get_ignore_mod_tap_interrupt to get_hold_on_other_key_press is simply a matter of renaming the function and swapping every true by false and vice versa. The one subtlety you may need to look out for is that the get_ignore_mod_tap_interrupt was only ever called with mod-taps passed in as the keycode argument, while the keycode argument of get_hold_on_other_key_press can be any dual-role key. This includes not only mod-taps, but also layer-taps, one shot keys, TT(layer) and more. This has an impact on the effect of the default case in a typical per-key configuration making use of a switch(keycode) statement.
To illustrate, let's take the example of a configuration where we'd want all mod-taps to activate the modifier if another key is pressed while held with the exception of LCTL_T(KC_A), which should ignore keys pressed while it is held and activate the modifier only if it has been held for longer than the tapping term. In addition, we would like to keep the default "ignore-interrupt" behavior of layer taps.
An old way to do this would be via the following code:
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case LCTL_T(KC_A):
return true;
default:
return false;
}
}
The correct way to update this code without accidentally changing how the layer-taps work would be the following:
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
// Capture all mod-tap keycodes.
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
if (keycode == LCTL_T(KC_A)) {
// Disable HOLD_ON_OTHER_KEY_PRESS for LCTL_T(KC_A)
// aka enable IGNORE_MOD_TAP_INTERRUPT for LCTL_T(KC_A).
return false;
} else {
// Enable HOLD_ON_OTHER_KEY_PRESS for every other mod-tap keycode.
return true;
}
default:
return false;
}
}
For more information, you are invited to read the sections on IGNORE_MOD_TAP_INTERRUPT and HOLD_ON_OTHER_KEY_PRESS in the page on Tap-Hold configuration options.
TAPPING_FORCE_HOLD => QUICK_TAP_TERM (#17007) {#quick-tap-term}TAPPING_FORCE_HOLD feature is now replaced by QUICK_TAP_TERM. Instead of turning off auto-repeat completely, user will have the option to configure a QUICK_TAP_TERM in milliseconds. When the user holds a tap-hold key after tapping it within QUICK_TAP_TERM, QMK will send the tap keycode to the host, enabling auto-repeat.
Its value is set to TAPPING_TERM by default and it can be reduced to match typing habits to avoid false triggers. To disable auto-repeat completely, set QUICK_TAP_TERM to zero.
TAPPING_FORCE_HOLD_PER_KEY is also deprecated and replaced by QUICK_TAP_TERM_PER_KEY. The old granular control function for tapping force hold is:
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case LT(1, KC_BSPC):
return true;
default:
return false;
}
}
That function can be replaced with:
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case SFT_T(KC_SPC):
return 0;
default:
return QUICK_TAP_TERM;
}
}
For more details, please read the updated documentation section on Quick Tap Term.
The Leader Key feature API has been significantly improved, along with some bugfixes and added tests.
Instead of defining your leader sequences in matrix_scan_user(), they are now handled in the leader_end_user() callback, and the LEADER_EXTERNS()/LEADER_DICTIONARY() macros are no longer needed:
void leader_end_user(void) {
if (leader_sequence_one_key(KC_F)) {
// Leader, f => Types the below string
SEND_STRING("QMK is awesome.");
} else if (leader_sequence_two_keys(KC_D, KC_D)) {
// Leader, d, d => Ctrl+A, Ctrl+C
SEND_STRING(SS_LCTL("a") SS_LCTL("c"));
} else if (leader_sequence_three_keys(KC_D, KC_D, KC_S)) {
// Leader, d, d, s => Types the below string
SEND_STRING("https://start.duckduckgo.com\n");
} else if (leader_sequence_two_keys(KC_A, KC_S)) {
// Leader, a, s => GUI+S
tap_code16(LGUI(KC_S));
}
}
For more information please see the Leader Key documentation.
The following keyboards have had their source moved within QMK:
| Old Keyboard Name | New Keyboard Name |
|---|---|
| ramonimbao/aelith | rmi_kb/aelith |
| ramonimbao/herringbone/pro | rmi_kb/herringbone/pro |
| ramonimbao/herringbone/v1 | rmi_kb/herringbone/v1 |
| ramonimbao/mona/v1_1 | rmi_kb/mona/v1_1 |
| ramonimbao/mona/v1 | rmi_kb/mona/v1 |
| ramonimbao/mona/v32a | rmi_kb/mona/v32a |
| ramonimbao/squishy65 | rmi_kb/squishy65 |
| ramonimbao/squishytkl | rmi_kb/squishytkl |
| ramonimbao/tkl_ff | rmi_kb/tkl_ff |
| ramonimbao/tkl_ff/v1 | rmi_kb/tkl_ff/v1 |
| ramonimbao/tkl_ff/v2 | rmi_kb/tkl_ff/v2 |
| ramonimbao/wete/v1 | rmi_kb/wete/v1 |
| ramonimbao/wete/v2 | rmi_kb/wete/v2 |
| the_uni | stenothe_uni |
| xelus/xs60 | xelus/xs60/soldered |
As per last breaking changes cycle, there has been a lot of emphasis on behind-the-scenes changes, mainly around consolidation of core subsystems and constant values, as well as addressing tech debt. Whilst not outwardly visible, this cleanup and refactoring should start paying dividends as it simplifies future development and maintenance.
A handful of examples:
info.json, such as backlight, encodersCore:
*_RIGHT configuration for PMW33XX driver (#19243)IS_EVENT macro instead of !IS_NOEVENT (#19366)make all-<platform> build targets (#19496)CH_KERNEL_MAJOR check (#19597)IS_HOST_LED_ON and migrate usages (#19753)config.h include from quantum files (#19817)KC_MISSION_CONTROL/KC_LAUNCHPAD keycodes to core (#19884)CLI:
qmk compile/qmk flash - Validate keymap argument (#19530)version.h (#19542)multibuild, cformat, fileformat, pyformat. (#19629)mass-compile ability to filter by key existence. (#19885)Submodule updates:
Keyboards:
MCU and BOOTLOADER to data-driven (#19529)LAYOUTS to data driven (#19541)MATRIX_HAS_GHOST from config.h (#19726)LOCKING_SUPPORT_ENABLE from config.h (#19748)DEBOUNCE macro usage (#19750)GRAVE_ESC_CTRL_OVERRIDE from config.h (#19752)SOFT_SERIAL_PIN from config.h (#19768)SOFT_SERIAL_PIN for non-split boards (#19774)DIRECT_PINS to data driven (#19826)I2CD2 usages w/ RP2040 (#19833)SOFT_SERIAL_PIN to data driven (#19863)KC_MISSION_CONTROL/KC_LAUNCHPAD usages (#19891)BACKLIGHT_LEVELS (#19898)MACRO0* (#19918)yandrstudio keymaps (#19919)Keyboard fixes:
MCU/BOOTLOADERs (#19778)info.json (#19815)backlight.breathing_period) (#19901)#pragma onces (#19902)keebio/kbo5000: fix encoder config (#19941)Others:
Bugs:
NO_ACTION_TAPPING is defined (#11528)qk_ prefix (#19302)qk_ prefix (#19304)qk_ prefix (#19313)qmk doctor - Handle permission issues while checking udev (#19548)qmk doctor - Handle timeouts while checking binaries (#19549)pinToMux() for STM32F0xx (#19658)OPT = 0 due to inline functions (#19767)develop compiles. (#19828)