Ignore the Layer Lock key in Repeat Key and Caps Word. (#25171)

This commit is contained in:
Pascal Getreuer 2025-04-19 11:57:00 -07:00 committed by GitHub
parent 88453acc6a
commit ea85ace4a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 91 additions and 9 deletions

View File

@ -160,8 +160,13 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
case QK_TRI_LAYER_LOWER ... QK_TRI_LAYER_UPPER: case QK_TRI_LAYER_LOWER ... QK_TRI_LAYER_UPPER:
// Ignore AltGr. #endif // TRI_LAYER_ENABLE
#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key.
case QK_LAYER_LOCK:
#endif // LAYER_LOCK_ENABLE
// Ignore AltGr.
case KC_RALT: case KC_RALT:
case OSM(MOD_RALT): case OSM(MOD_RALT):
return true; return true;

View File

@ -41,7 +41,10 @@ static bool remember_last_key(uint16_t keycode, keyrecord_t* record, uint8_t* re
#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys. #ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
case QK_TRI_LAYER_LOWER: case QK_TRI_LAYER_LOWER:
case QK_TRI_LAYER_UPPER: case QK_TRI_LAYER_UPPER:
#endif // TRI_LAYER_ENABLE #endif // TRI_LAYER_ENABLE
#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key.
case QK_LAYER_LOCK:
#endif // LAYER_LOCK_ENABLE
return false; return false;
// Ignore hold events on tap-hold keys. // Ignore hold events on tap-hold keys.

View File

@ -15,5 +15,7 @@
CAPS_WORD_ENABLE = yes CAPS_WORD_ENABLE = yes
COMMAND_ENABLE = no COMMAND_ENABLE = no
LAYER_LOCK_ENABLE = yes
SPACE_CADET_ENABLE = yes SPACE_CADET_ENABLE = yes
TRI_LAYER_ENABLE = yes

View File

@ -156,21 +156,22 @@ TEST_F(CapsWord, IdleTimeout) {
// Turn on Caps Word and tap "A". // Turn on Caps Word and tap "A".
caps_word_on(); caps_word_on();
tap_key(key_a); tap_key(key_a);
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
EXPECT_EMPTY_REPORT(driver);
idle_for(CAPS_WORD_IDLE_TIMEOUT); idle_for(CAPS_WORD_IDLE_TIMEOUT);
run_one_scan_loop(); run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
// Caps Word should be off and mods should be clear. // Caps Word should be off and mods should be clear.
EXPECT_EQ(is_caps_word_on(), false); EXPECT_EQ(is_caps_word_on(), false);
EXPECT_EQ(get_mods() | get_weak_mods(), 0); EXPECT_EQ(get_mods() | get_weak_mods(), 0);
EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
// Expect unshifted "A". // Expect unshifted "A".
EXPECT_REPORT(driver, (KC_A)); EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
tap_key(key_a); tap_key(key_a);
run_one_scan_loop();
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
} }
@ -244,6 +245,7 @@ TEST_F(CapsWord, ShiftsAltGrSymbols) {
// clang-format off // clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf( EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(), KeyboardReport(),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_RALT), KeyboardReport(KC_RALT),
KeyboardReport(KC_LSFT, KC_RALT)))) KeyboardReport(KC_LSFT, KC_RALT))))
.Times(AnyNumber()); .Times(AnyNumber());
@ -259,6 +261,9 @@ TEST_F(CapsWord, ShiftsAltGrSymbols) {
tap_key(key_a); tap_key(key_a);
run_one_scan_loop(); run_one_scan_loop();
key_altgr.release(); key_altgr.release();
run_one_scan_loop();
idle_for(CAPS_WORD_IDLE_TIMEOUT);
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
} }
@ -274,6 +279,7 @@ TEST_F(CapsWord, ShiftsModTapAltGrSymbols) {
// clang-format off // clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf( EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(), KeyboardReport(),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_RALT), KeyboardReport(KC_RALT),
KeyboardReport(KC_LSFT, KC_RALT)))) KeyboardReport(KC_LSFT, KC_RALT))))
.Times(AnyNumber()); .Times(AnyNumber());
@ -289,8 +295,11 @@ TEST_F(CapsWord, ShiftsModTapAltGrSymbols) {
tap_key(key_a); tap_key(key_a);
run_one_scan_loop(); run_one_scan_loop();
key_altgr_t.release(); key_altgr_t.release();
run_one_scan_loop();
EXPECT_TRUE(is_caps_word_on()); EXPECT_TRUE(is_caps_word_on());
idle_for(CAPS_WORD_IDLE_TIMEOUT);
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
} }
@ -535,7 +544,11 @@ TEST_P(CapsWordDoubleTapShift, Activation) {
// machine at this point. This due to imperfect test isolation which can't // machine at this point. This due to imperfect test isolation which can't
// reset the caps word double shift timer on test case setup. // reset the caps word double shift timer on test case setup.
idle_for(CAPS_WORD_IDLE_TIMEOUT); idle_for(CAPS_WORD_IDLE_TIMEOUT);
EXPECT_REPORT(driver, (KC_ESC));
EXPECT_EMPTY_REPORT(driver);
tap_key(esc); tap_key(esc);
VERIFY_AND_CLEAR(driver);
} }
// Double tap doesn't count if another key is pressed between the taps. // Double tap doesn't count if another key is pressed between the taps.
@ -589,6 +602,7 @@ TEST_P(CapsWordDoubleTapShift, SlowTaps) {
EXPECT_EQ(is_caps_word_on(), false); // Caps Word is still off. EXPECT_EQ(is_caps_word_on(), false); // Caps Word is still off.
clear_oneshot_mods(); clear_oneshot_mods();
send_keyboard_report();
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
} }
@ -626,7 +640,7 @@ TEST_F(CapsWord, IgnoresOSLHold) {
run_one_scan_loop(); run_one_scan_loop();
tap_key(key_b); tap_key(key_b);
key_osl.release(); key_osl.release();
run_one_scan_loop(); idle_for(CAPS_WORD_IDLE_TIMEOUT + 1);
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
} }
@ -645,15 +659,39 @@ TEST_F(CapsWord, IgnoresOSLTap) {
KeyboardReport(), KeyboardReport(),
KeyboardReport(KC_LSFT)))) KeyboardReport(KC_LSFT))))
.Times(AnyNumber()); .Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LSFT, KC_B)); EXPECT_REPORT(driver, (KC_LSFT, KC_B));
caps_word_on(); caps_word_on();
tap_key(key_osl); tap_key(key_osl);
tap_key(key_b); tap_key(key_b);
run_one_scan_loop(); idle_for(CAPS_WORD_IDLE_TIMEOUT);
VERIFY_AND_CLEAR(driver);
}
TEST_F(CapsWord, IgnoresLayerLockKey) {
TestDriver driver;
KeymapKey key_llock(0, 1, 0, QK_LAYER_LOCK);
KeymapKey key_b(0, 0, 0, KC_B);
set_keymap({key_llock, key_b});
// Allow any number of reports with no keys or only modifiers.
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LSFT, KC_B));
caps_word_on();
tap_key(key_llock);
tap_key(key_b);
idle_for(CAPS_WORD_IDLE_TIMEOUT);
VERIFY_AND_CLEAR(driver); VERIFY_AND_CLEAR(driver);
} }
// clang-format on
} // namespace } // namespace

View File

@ -16,3 +16,4 @@
REPEAT_KEY_ENABLE = yes REPEAT_KEY_ENABLE = yes
AUTO_SHIFT_ENABLE = yes AUTO_SHIFT_ENABLE = yes
LAYER_LOCK_ENABLE = yes

View File

@ -751,4 +751,37 @@ TEST_F(RepeatKey, RepeatKeyInvoke) {
testing::Mock::VerifyAndClearExpectations(&driver); testing::Mock::VerifyAndClearExpectations(&driver);
} }
// Check that mods and Layer Lock are not remembered.
TEST_F(RepeatKey, IgnoredKeys) {
TestDriver driver;
KeymapKey regular_key(0, 0, 0, KC_A);
KeymapKey key_repeat(0, 1, 0, QK_REP);
KeymapKey key_lsft(0, 2, 0, KC_LSFT);
KeymapKey key_lctl(0, 3, 0, KC_LCTL);
KeymapKey key_llck(0, 4, 0, QK_LAYER_LOCK);
set_keymap({regular_key, key_repeat, key_lsft, key_lctl, key_llck});
// Allow any number of empty reports.
EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
{
InSequence seq;
EXPECT_REPORT(driver, (KC_A));
EXPECT_REPORT(driver, (KC_LSFT));
EXPECT_REPORT(driver, (KC_LCTL));
EXPECT_REPORT(driver, (KC_A));
EXPECT_REPORT(driver, (KC_A));
}
tap_key(regular_key); // Taps the KC_A key.
// Tap Shift, Ctrl, and Layer Lock keys, which should not be remembered.
tap_keys(key_lsft, key_lctl, key_llck);
EXPECT_KEYCODE_EQ(get_last_keycode(), KC_A);
// Tapping the Repeat Key should still reproduce KC_A.
tap_keys(key_repeat, key_repeat);
testing::Mock::VerifyAndClearExpectations(&driver);
}
} // namespace } // namespace