qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

test_tap_hold.cpp (16923B)


      1 // Copyright 2025 Google LLC
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <functional>
     16 
     17 #include "keyboard_report_util.hpp"
     18 #include "keycode.h"
     19 #include "test_common.hpp"
     20 #include "action_tapping.h"
     21 #include "test_fixture.hpp"
     22 #include "test_keymap_key.hpp"
     23 
     24 using testing::_;
     25 using testing::AnyNumber;
     26 using testing::InSequence;
     27 
     28 namespace {
     29 
     30 bool process_record_user_default(uint16_t keycode, keyrecord_t *record) {
     31     return true;
     32 }
     33 
     34 // Indirection so that process_record_user() can be
     35 // replaced with other functions in the test cases below.
     36 std::function<bool(uint16_t, keyrecord_t *)> process_record_user_fun = process_record_user_default;
     37 
     38 extern "C" bool process_record_user(uint16_t keycode, keyrecord_t *record) {
     39     return process_record_user_fun(keycode, record);
     40 }
     41 
     42 class SpeculativeHoldDefault : public TestFixture {
     43    public:
     44     void SetUp() override {
     45         process_record_user_fun = process_record_user_default;
     46     }
     47 };
     48 
     49 TEST_F(SpeculativeHoldDefault, get_speculative_hold) {
     50     keyrecord_t record = {};
     51 
     52     // With the default definition of get_speculative_hold(), Speculative Hold
     53     // is enabled for Ctrl and Shift.
     54     EXPECT_TRUE(get_speculative_hold(MT(MOD_LCTL, KC_NO), &record));
     55     EXPECT_TRUE(get_speculative_hold(MT(MOD_LSFT, KC_NO), &record));
     56     EXPECT_TRUE(get_speculative_hold(MT(MOD_LCTL | MOD_LSFT, KC_NO), &record));
     57     EXPECT_TRUE(get_speculative_hold(MT(MOD_RCTL, KC_NO), &record));
     58     EXPECT_TRUE(get_speculative_hold(MT(MOD_RSFT, KC_NO), &record));
     59     EXPECT_TRUE(get_speculative_hold(MT(MOD_RCTL | MOD_RSFT, KC_NO), &record));
     60 
     61     EXPECT_FALSE(get_speculative_hold(MT(MOD_LALT, KC_NO), &record));
     62     EXPECT_FALSE(get_speculative_hold(MT(MOD_LGUI, KC_NO), &record));
     63     EXPECT_FALSE(get_speculative_hold(MT(MOD_RALT, KC_NO), &record));
     64     EXPECT_FALSE(get_speculative_hold(MT(MOD_RGUI, KC_NO), &record));
     65     EXPECT_FALSE(get_speculative_hold(MT(MOD_MEH, KC_NO), &record));
     66     EXPECT_FALSE(get_speculative_hold(MT(MOD_HYPR, KC_NO), &record));
     67 }
     68 
     69 TEST_F(SpeculativeHoldDefault, tap_mod_tap) {
     70     TestDriver driver;
     71     InSequence s;
     72     static int process_record_user_calls = 0;
     73     auto       mod_tap_key               = KeymapKey(0, 1, 0, SFT_T(KC_P));
     74 
     75     set_keymap({mod_tap_key});
     76 
     77     process_record_user_fun = [](uint16_t keycode, keyrecord_t *record) {
     78         ++process_record_user_calls;
     79         return true;
     80     };
     81 
     82     // Press mod-tap-hold key. Mod is held speculatively.
     83     EXPECT_REPORT(driver, (KC_LSFT));
     84     mod_tap_key.press();
     85     idle_for(10);
     86     VERIFY_AND_CLEAR(driver);
     87     EXPECT_EQ(get_speculative_mods(), MOD_BIT_LSHIFT);
     88     // Speculative mod holds and releases are made directly, bypassing regular
     89     // event processing. No calls have been made yet to process_record_user().
     90     EXPECT_EQ(process_record_user_calls, 0);
     91 
     92     // Release mod-tap-hold key.
     93     EXPECT_EMPTY_REPORT(driver); // Speculative mod canceled.
     94     EXPECT_REPORT(driver, (KC_P));
     95     EXPECT_EMPTY_REPORT(driver);
     96     mod_tap_key.release();
     97     run_one_scan_loop();
     98     VERIFY_AND_CLEAR(driver);
     99     // All mods are released.
    100     EXPECT_EQ(get_speculative_mods(), 0);
    101     EXPECT_EQ(get_mods(), 0);
    102     // Two calls have now been made, for pressing and releasing KC_P.
    103     EXPECT_EQ(process_record_user_calls, 2);
    104 
    105     // Idle for tapping term of mod tap hold key.
    106     idle_for(TAPPING_TERM - 10);
    107     VERIFY_AND_CLEAR(driver);
    108 }
    109 
    110 TEST_F(SpeculativeHoldDefault, key_overrides) {
    111     TestDriver driver;
    112     InSequence s;
    113     auto       mod_tap_key = KeymapKey(0, 1, 0, LSFT_T(KC_A));
    114     auto       esc_key     = KeymapKey(0, 3, 0, KC_ESC);
    115 
    116     set_keymap({mod_tap_key, esc_key});
    117 
    118     // Press mod-tap Shift key.
    119     EXPECT_REPORT(driver, (KC_LSFT));
    120     mod_tap_key.press();
    121     run_one_scan_loop();
    122     VERIFY_AND_CLEAR(driver);
    123 
    124     // Press Esc key.
    125     EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
    126     EXPECT_REPORT(driver, (KC_HOME));
    127     esc_key.press();
    128     idle_for(TAPPING_TERM + 1);
    129     VERIFY_AND_CLEAR(driver);
    130 
    131     // Release Esc key.
    132     EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
    133     EXPECT_REPORT(driver, (KC_LSFT));
    134     esc_key.release();
    135     run_one_scan_loop();
    136     VERIFY_AND_CLEAR(driver);
    137 
    138     // Release mod-tap Shift key.
    139     EXPECT_EMPTY_REPORT(driver);
    140     mod_tap_key.release();
    141     run_one_scan_loop();
    142     VERIFY_AND_CLEAR(driver);
    143 }
    144 
    145 TEST_F(SpeculativeHoldDefault, tap_regular_key_while_mod_tap_key_is_held) {
    146     TestDriver driver;
    147     InSequence s;
    148     auto       mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
    149     auto       regular_key = KeymapKey(0, 2, 0, KC_A);
    150 
    151     set_keymap({mod_tap_key, regular_key});
    152 
    153     // Press mod-tap-hold key.
    154     EXPECT_REPORT(driver, (KC_LSFT));
    155     mod_tap_key.press();
    156     run_one_scan_loop();
    157     VERIFY_AND_CLEAR(driver);
    158 
    159     // Tap regular key.
    160     EXPECT_NO_REPORT(driver);
    161     regular_key.press();
    162     run_one_scan_loop();
    163     regular_key.release();
    164     run_one_scan_loop();
    165     VERIFY_AND_CLEAR(driver);
    166 
    167     // Release mod-tap-hold key.
    168     EXPECT_EMPTY_REPORT(driver);
    169     EXPECT_REPORT(driver, (KC_P));
    170     EXPECT_REPORT(driver, (KC_P, KC_A));
    171     EXPECT_REPORT(driver, (KC_P));
    172     EXPECT_EMPTY_REPORT(driver);
    173     mod_tap_key.release();
    174     run_one_scan_loop();
    175     VERIFY_AND_CLEAR(driver);
    176 
    177     // Idle for tapping term of mod tap hold key.
    178     idle_for(TAPPING_TERM - 3);
    179     VERIFY_AND_CLEAR(driver);
    180 }
    181 
    182 TEST_F(SpeculativeHoldDefault, tap_mod_tap_key_two_times) {
    183     TestDriver driver;
    184     InSequence s;
    185     auto       mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
    186 
    187     set_keymap({mod_tap_key});
    188 
    189     // Press mod-tap-hold key.
    190     EXPECT_REPORT(driver, (KC_LSFT));
    191     mod_tap_key.press();
    192     run_one_scan_loop();
    193     VERIFY_AND_CLEAR(driver);
    194 
    195     // Release mod-tap-hold key.
    196     EXPECT_EMPTY_REPORT(driver);
    197     EXPECT_REPORT(driver, (KC_P));
    198     EXPECT_EMPTY_REPORT(driver);
    199     mod_tap_key.release();
    200     run_one_scan_loop();
    201     VERIFY_AND_CLEAR(driver);
    202 
    203     // Press mod-tap-hold key again.
    204     EXPECT_REPORT(driver, (KC_P));
    205     mod_tap_key.press();
    206     idle_for(TAPPING_TERM);
    207     VERIFY_AND_CLEAR(driver);
    208 
    209     // Release mod-tap-hold key.
    210     EXPECT_EMPTY_REPORT(driver);
    211     mod_tap_key.release();
    212     run_one_scan_loop();
    213     VERIFY_AND_CLEAR(driver);
    214 }
    215 
    216 TEST_F(SpeculativeHoldDefault, tap_mod_tap_key_twice_and_hold_on_second_time) {
    217     TestDriver driver;
    218     InSequence s;
    219     auto       mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
    220 
    221     set_keymap({mod_tap_key});
    222 
    223     // Press mod-tap-hold key.
    224     EXPECT_REPORT(driver, (KC_LSFT));
    225     mod_tap_key.press();
    226     run_one_scan_loop();
    227     VERIFY_AND_CLEAR(driver);
    228 
    229     // Release mod-tap-hold key.
    230     EXPECT_EMPTY_REPORT(driver);
    231     EXPECT_REPORT(driver, (KC_P));
    232     EXPECT_EMPTY_REPORT(driver);
    233     mod_tap_key.release();
    234     run_one_scan_loop();
    235     VERIFY_AND_CLEAR(driver);
    236 
    237     // Press mod-tap-hold key again.
    238     EXPECT_REPORT(driver, (KC_P));
    239     mod_tap_key.press();
    240     idle_for(TAPPING_TERM);
    241     VERIFY_AND_CLEAR(driver);
    242 
    243     // Release mod-tap-hold key.
    244     EXPECT_EMPTY_REPORT(driver);
    245     mod_tap_key.release();
    246     run_one_scan_loop();
    247     VERIFY_AND_CLEAR(driver);
    248 }
    249 
    250 TEST_F(SpeculativeHoldDefault, tap_and_hold_mod_tap_key) {
    251     TestDriver driver;
    252     InSequence s;
    253     static int process_record_user_calls = 0;
    254     auto       mod_tap_key               = KeymapKey(0, 1, 0, SFT_T(KC_P));
    255 
    256     set_keymap({mod_tap_key});
    257 
    258     process_record_user_fun = [](uint16_t keycode, keyrecord_t *record) {
    259         ++process_record_user_calls;
    260         return true;
    261     };
    262 
    263     // Press mod-tap-hold key.
    264     EXPECT_REPORT(driver, (KC_LSFT));
    265     mod_tap_key.press();
    266     idle_for(TAPPING_TERM - 1);
    267     EXPECT_EQ(get_speculative_mods(), MOD_BIT_LSHIFT);
    268     EXPECT_EQ(get_mods(), 0);
    269     // Speculative mod holds and releases are made directly, bypassing regular
    270     // event processing. No calls have been made yet to process_record_user().
    271     EXPECT_EQ(process_record_user_calls, 0);
    272     idle_for(2);
    273     // Now that the key has settled, one call has been made for the hold event.
    274     EXPECT_EQ(process_record_user_calls, 1);
    275     EXPECT_EQ(get_speculative_mods(), 0);
    276     EXPECT_EQ(get_mods(), MOD_BIT_LSHIFT);
    277     VERIFY_AND_CLEAR(driver);
    278 
    279     // Release mod-tap-hold key.
    280     EXPECT_EMPTY_REPORT(driver);
    281     mod_tap_key.release();
    282     run_one_scan_loop();
    283     EXPECT_EQ(process_record_user_calls, 2);
    284     VERIFY_AND_CLEAR(driver);
    285 }
    286 
    287 // Test with layer tap and speculative mod tap keys on the same layer,
    288 // rolling from LT to MT key:
    289 // "LT down, MT down, (wait out tapping term), LT up, MT up."
    290 TEST_F(SpeculativeHoldDefault, lt_mt_same_layer_roll) {
    291     TestDriver driver;
    292     InSequence s;
    293     auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    294     auto       mod_tap_key   = KeymapKey(0, 1, 0, SFT_T(KC_B));
    295     auto       regular_key   = KeymapKey(1, 1, 0, KC_C);
    296 
    297     set_keymap({layer_tap_key, mod_tap_key, regular_key});
    298 
    299     // Press layer tap key.
    300     EXPECT_NO_REPORT(driver);
    301     layer_tap_key.press();
    302     run_one_scan_loop();
    303     VERIFY_AND_CLEAR(driver);
    304 
    305     // Press mod-tap key, after flow tap term but within tapping term. The
    306     // speculative mod activates.
    307     EXPECT_REPORT(driver, (KC_LSFT));
    308     mod_tap_key.press();
    309     run_one_scan_loop();
    310     VERIFY_AND_CLEAR(driver);
    311 
    312     // Wait for the layer tap key to settle.
    313     EXPECT_EMPTY_REPORT(driver);
    314     EXPECT_REPORT(driver, (KC_C));
    315     idle_for(TAPPING_TERM);
    316     VERIFY_AND_CLEAR(driver);
    317 
    318     // Release keys.
    319     EXPECT_EMPTY_REPORT(driver);
    320     layer_tap_key.release();
    321     run_one_scan_loop();
    322     mod_tap_key.release();
    323     run_one_scan_loop();
    324     VERIFY_AND_CLEAR(driver);
    325     // All mods are released.
    326     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    327 }
    328 
    329 // Test with layer tap and speculative mod tap keys on the same layer, trying a
    330 // nested press:
    331 // "LT down, MT down, (wait out tapping term), MT up, LT up."
    332 TEST_F(SpeculativeHoldDefault, lt_mt_same_layer_nested_press) {
    333     TestDriver driver;
    334     InSequence s;
    335     auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    336     auto       mod_tap_key   = KeymapKey(0, 1, 0, SFT_T(KC_B));
    337     auto       regular_key   = KeymapKey(1, 1, 0, KC_C);
    338 
    339     set_keymap({layer_tap_key, mod_tap_key, regular_key});
    340 
    341     EXPECT_NO_REPORT(driver);
    342     layer_tap_key.press();
    343     run_one_scan_loop();
    344     VERIFY_AND_CLEAR(driver);
    345 
    346     EXPECT_REPORT(driver, (KC_LSFT));
    347     mod_tap_key.press();
    348     run_one_scan_loop();
    349     VERIFY_AND_CLEAR(driver);
    350 
    351     EXPECT_EMPTY_REPORT(driver);
    352     EXPECT_REPORT(driver, (KC_C));
    353     run_one_scan_loop();
    354     idle_for(TAPPING_TERM);
    355     VERIFY_AND_CLEAR(driver);
    356 
    357     // Release keys: MT first, LT second.
    358     EXPECT_EMPTY_REPORT(driver);
    359     mod_tap_key.release();
    360     run_one_scan_loop();
    361     layer_tap_key.release();
    362     run_one_scan_loop();
    363     VERIFY_AND_CLEAR(driver);
    364     // All mods are released.
    365     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    366 }
    367 
    368 // Test with layer tap and speculative mod tap keys on the same layer, trying a
    369 // nested press with the MT first:
    370 // "MT down, LT down, (wait out tapping term), LT up, MT up."
    371 TEST_F(SpeculativeHoldDefault, mt_lt_same_layer_nested_press) {
    372     TestDriver driver;
    373     InSequence s;
    374     auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    375     auto       mod_tap_key   = KeymapKey(0, 1, 0, SFT_T(KC_B));
    376     auto       regular_key   = KeymapKey(1, 1, 0, KC_C);
    377 
    378     set_keymap({layer_tap_key, mod_tap_key, regular_key});
    379 
    380     EXPECT_REPORT(driver, (KC_LSFT));
    381     mod_tap_key.press();
    382     run_one_scan_loop();
    383 
    384     EXPECT_NO_REPORT(driver);
    385     layer_tap_key.press();
    386     idle_for(TAPPING_TERM + 1);
    387     VERIFY_AND_CLEAR(driver);
    388 
    389     EXPECT_EMPTY_REPORT(driver);
    390     layer_tap_key.release();
    391     run_one_scan_loop();
    392     mod_tap_key.release();
    393     run_one_scan_loop();
    394     VERIFY_AND_CLEAR(driver);
    395     // All mods are released.
    396     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    397 }
    398 
    399 // Test with a speculative mod tap key reached by a layer tap key, rolling from
    400 // LT to MT key:
    401 // "LT down, MT down, (wait out tapping term), LT up, MT up."
    402 TEST_F(SpeculativeHoldDefault, lt_mt_different_layer_roll) {
    403     TestDriver driver;
    404     InSequence s;
    405     auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    406     auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    407     auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    408     auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));
    409 
    410     set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});
    411 
    412     // Press layer tap key.
    413     EXPECT_NO_REPORT(driver);
    414     layer_tap_key.press();
    415     run_one_scan_loop();
    416     // Press mod tap key.
    417     mod_tap_key.press();
    418     idle_for(TAPPING_TERM);
    419     VERIFY_AND_CLEAR(driver);
    420 
    421     // Release keys.
    422     EXPECT_REPORT(driver, (KC_LSFT));
    423     layer_tap_key.release();
    424     idle_for(TAPPING_TERM);
    425     VERIFY_AND_CLEAR(driver);
    426 
    427     EXPECT_EMPTY_REPORT(driver);
    428     mod_tap_key.release();
    429     run_one_scan_loop();
    430     VERIFY_AND_CLEAR(driver);
    431     // All mods are released.
    432     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    433 }
    434 
    435 // Test with a speculative mod tap key reached by a layer tap key, slowly
    436 // rolling from LT to MT key:
    437 // "LT down, (wait), MT down, (wait), LT up, MT up."
    438 TEST_F(SpeculativeHoldDefault, lt_mt_different_layer_slow_roll) {
    439     TestDriver driver;
    440     InSequence s;
    441     auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    442     auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    443     auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    444     auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));
    445 
    446     set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});
    447 
    448     EXPECT_NO_REPORT(driver);
    449     layer_tap_key.press();
    450     idle_for(TAPPING_TERM + 1);
    451 
    452     EXPECT_REPORT(driver, (KC_LSFT));
    453     mod_tap_key.press();
    454     run_one_scan_loop();
    455     VERIFY_AND_CLEAR(driver);
    456 
    457     EXPECT_EMPTY_REPORT(driver);
    458     EXPECT_REPORT(driver, (KC_B));
    459     EXPECT_EMPTY_REPORT(driver);
    460     layer_tap_key.release();
    461     run_one_scan_loop();
    462     mod_tap_key.release();
    463     run_one_scan_loop();
    464     VERIFY_AND_CLEAR(driver);
    465     // All mods are released.
    466     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    467 }
    468 
    469 // Test with a speculative mod tap key reached by a layer tap key, trying a
    470 // nested press:
    471 // "LT down, MT down, (wait out tapping term), MT up, LT up."
    472 TEST_F(SpeculativeHoldDefault, lt_mt_different_layer_nested_press) {
    473     TestDriver driver;
    474     InSequence s;
    475     auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    476     auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    477     auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    478     auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));
    479 
    480     set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});
    481 
    482     EXPECT_NO_REPORT(driver);
    483     layer_tap_key.press();
    484     run_one_scan_loop();
    485     mod_tap_key.press();
    486     idle_for(TAPPING_TERM);
    487     VERIFY_AND_CLEAR(driver);
    488 
    489     // Release keys.
    490     EXPECT_REPORT(driver, (KC_LSFT));
    491     EXPECT_EMPTY_REPORT(driver);
    492     mod_tap_key.release();
    493     run_one_scan_loop();
    494     layer_tap_key.release();
    495     run_one_scan_loop();
    496     VERIFY_AND_CLEAR(driver);
    497     // All mods are released.
    498     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    499 }
    500 
    501 // Test with a speculative mod tap key reached by a layer tap key, trying a
    502 // slow nested press:
    503 // "LT down, (wait), MT down, MT up, LT up."
    504 TEST_F(SpeculativeHoldDefault, lt_mt_different_layer_slow_nested_press) {
    505     TestDriver driver;
    506     InSequence s;
    507     auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    508     auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    509     auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    510     auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));
    511 
    512     set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});
    513 
    514     EXPECT_NO_REPORT(driver);
    515     layer_tap_key.press();
    516     idle_for(TAPPING_TERM + 1);
    517 
    518     EXPECT_REPORT(driver, (KC_LSFT));
    519     mod_tap_key.press();
    520     run_one_scan_loop();
    521     VERIFY_AND_CLEAR(driver);
    522 
    523     EXPECT_EMPTY_REPORT(driver);
    524     EXPECT_REPORT(driver, (KC_C));
    525     EXPECT_EMPTY_REPORT(driver);
    526     mod_tap_key.release();
    527     run_one_scan_loop();
    528     layer_tap_key.release();
    529     run_one_scan_loop();
    530     VERIFY_AND_CLEAR(driver);
    531     // All mods are released.
    532     EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
    533 }
    534 
    535 } // namespace