aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPascal Getreuer <[email protected]>2025-01-29 11:17:54 -0800
committerGitHub <[email protected]>2025-01-30 06:17:54 +1100
commit9d799aff97163a1cce24c2bd1551a085fac7a8f6 (patch)
tree25d1c2eb3359722e6a336998d1ab40bef7dbb380
parent08dcc8856f078e50f6dbdd6a75647f131e270645 (diff)
downloadqmk_firmware-9d799aff97163a1cce24c2bd1551a085fac7a8f6.tar.gz
qmk_firmware-9d799aff97163a1cce24c2bd1551a085fac7a8f6.zip
[Bug][Core] Fix for Chordal Hold: stuck mods when mod-taps are pressed in a stuttered sequence. (#24878)
-rw-r--r--quantum/action_tapping.c2
-rw-r--r--tests/tap_hold_configurations/chordal_hold/hold_on_other_key_press/test_tap_hold.cpp43
-rw-r--r--tests/tap_hold_configurations/chordal_hold/permissive_hold/test_tap_hold.cpp45
3 files changed, 88 insertions, 2 deletions
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index 9171970702..e42a98554d 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -736,7 +736,7 @@ static void waiting_buffer_chordal_hold_taps_until(keypos_t key) {
while (waiting_buffer_tail != waiting_buffer_head) {
keyrecord_t *record = &waiting_buffer[waiting_buffer_tail];
ac_dprintf("waiting_buffer_chordal_hold_taps_until: processing [%u]\n", waiting_buffer_tail);
- if (is_tap_record(record)) {
+ if (record->event.pressed && is_tap_record(record)) {
record->tap.count = 1;
registered_taps_add(record->event.key);
}
diff --git a/tests/tap_hold_configurations/chordal_hold/hold_on_other_key_press/test_tap_hold.cpp b/tests/tap_hold_configurations/chordal_hold/hold_on_other_key_press/test_tap_hold.cpp
index e6852bbbb1..7691f226af 100644
--- a/tests/tap_hold_configurations/chordal_hold/hold_on_other_key_press/test_tap_hold.cpp
+++ b/tests/tap_hold_configurations/chordal_hold/hold_on_other_key_press/test_tap_hold.cpp
@@ -805,3 +805,46 @@ TEST_F(ChordalHoldHoldOnOtherKeyPress, roll_layer_tap_key_with_regular_key) {
run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
}
+
+TEST_F(ChordalHoldHoldOnOtherKeyPress, two_mod_tap_keys_stuttered_press) {
+ TestDriver driver;
+ InSequence s;
+
+ auto mod_tap_key1 = KeymapKey(0, 1, 0, LSFT_T(KC_A));
+ auto mod_tap_key2 = KeymapKey(0, 2, 0, LCTL_T(KC_B));
+
+ set_keymap({mod_tap_key1, mod_tap_key2});
+
+ // Hold first mod-tap key until the tapping term.
+ EXPECT_REPORT(driver, (KC_LSFT));
+ mod_tap_key1.press();
+ idle_for(TAPPING_TERM + 1);
+ VERIFY_AND_CLEAR(driver);
+
+ // Press the second mod-tap key, then quickly release and press the first.
+ EXPECT_NO_REPORT(driver);
+ mod_tap_key2.press();
+ run_one_scan_loop();
+ mod_tap_key1.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LSFT, KC_B));
+ EXPECT_REPORT(driver, (KC_B));
+ EXPECT_REPORT(driver, (KC_B, KC_A));
+ mod_tap_key1.press();
+ run_one_scan_loop();
+ EXPECT_EQ(get_mods(), 0); // Verify that Shift was released.
+ VERIFY_AND_CLEAR(driver);
+
+ // Release both keys.
+ EXPECT_REPORT(driver, (KC_A));
+ mod_tap_key2.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_key1.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
diff --git a/tests/tap_hold_configurations/chordal_hold/permissive_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/chordal_hold/permissive_hold/test_tap_hold.cpp
index 1f89ab3eae..19e73edb02 100644
--- a/tests/tap_hold_configurations/chordal_hold/permissive_hold/test_tap_hold.cpp
+++ b/tests/tap_hold_configurations/chordal_hold/permissive_hold/test_tap_hold.cpp
@@ -877,6 +877,7 @@ TEST_F(ChordalHoldPermissiveHold, roll_layer_tap_key_with_regular_key) {
VERIFY_AND_CLEAR(driver);
// Press regular key.
+ EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
@@ -885,7 +886,6 @@ TEST_F(ChordalHoldPermissiveHold, roll_layer_tap_key_with_regular_key) {
EXPECT_REPORT(driver, (KC_P));
EXPECT_REPORT(driver, (KC_P, KC_A));
EXPECT_REPORT(driver, (KC_A));
- EXPECT_NO_REPORT(driver);
layer_tap_hold_key.release();
run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
@@ -896,3 +896,46 @@ TEST_F(ChordalHoldPermissiveHold, roll_layer_tap_key_with_regular_key) {
run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
}
+
+TEST_F(ChordalHoldPermissiveHold, two_mod_tap_keys_stuttered_press) {
+ TestDriver driver;
+ InSequence s;
+
+ auto mod_tap_key1 = KeymapKey(0, 1, 0, LSFT_T(KC_A));
+ auto mod_tap_key2 = KeymapKey(0, 2, 0, LCTL_T(KC_B));
+
+ set_keymap({mod_tap_key1, mod_tap_key2});
+
+ // Hold first mod-tap key until the tapping term.
+ EXPECT_REPORT(driver, (KC_LSFT));
+ mod_tap_key1.press();
+ idle_for(TAPPING_TERM + 1);
+ VERIFY_AND_CLEAR(driver);
+
+ // Press the second mod-tap key, then quickly release and press the first.
+ EXPECT_NO_REPORT(driver);
+ mod_tap_key2.press();
+ run_one_scan_loop();
+ mod_tap_key1.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LSFT, KC_B));
+ EXPECT_REPORT(driver, (KC_B));
+ EXPECT_REPORT(driver, (KC_B, KC_A));
+ mod_tap_key1.press();
+ run_one_scan_loop();
+ EXPECT_EQ(get_mods(), 0); // Verify that Shift was released.
+ VERIFY_AND_CLEAR(driver);
+
+ // Release both keys.
+ EXPECT_REPORT(driver, (KC_A));
+ mod_tap_key2.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_key1.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}