qmk_firmware

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

test_tapping.cpp (5781B)


      1 /* Copyright 2017 Fred Sundvik
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include "keyboard_report_util.hpp"
     18 #include "keycode.h"
     19 #include "test_common.hpp"
     20 #include "action_tapping.h"
     21 #include "test_keymap_key.hpp"
     22 
     23 using testing::_;
     24 using testing::InSequence;
     25 
     26 class Tapping : public TestFixture {};
     27 
     28 TEST_F(Tapping, TapA_SHFT_T_KeyReportsKey) {
     29     TestDriver driver;
     30     InSequence s;
     31     auto       key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
     32 
     33     set_keymap({key_shift_hold_p_tap});
     34 
     35     // Tapping keys does nothing on press
     36     key_shift_hold_p_tap.press();
     37     EXPECT_NO_REPORT(driver);
     38     run_one_scan_loop();
     39 
     40     // First we get the key press
     41     key_shift_hold_p_tap.release();
     42     EXPECT_REPORT(driver, (KC_P));
     43 
     44     // Then the release
     45     EXPECT_EMPTY_REPORT(driver);
     46     run_one_scan_loop();
     47 }
     48 
     49 TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) {
     50     TestDriver driver;
     51     InSequence s;
     52     auto       mod_tap_hold_key = KeymapKey(0, 7, 0, SFT_T(KC_P));
     53 
     54     set_keymap({mod_tap_hold_key});
     55 
     56     mod_tap_hold_key.press();
     57 
     58     // Tapping keys does nothing on press
     59     EXPECT_NO_REPORT(driver);
     60     idle_for(TAPPING_TERM);
     61 
     62     EXPECT_REPORT(driver, (KC_LSFT));
     63     run_one_scan_loop();
     64 
     65     EXPECT_EMPTY_REPORT(driver);
     66     mod_tap_hold_key.release();
     67     run_one_scan_loop();
     68 }
     69 
     70 TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
     71     // See issue #1478 for more information
     72     TestDriver driver;
     73     InSequence s;
     74     auto       key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
     75 
     76     set_keymap({key_shift_hold_p_tap});
     77 
     78     // Tapping keys does nothing on press
     79     key_shift_hold_p_tap.press();
     80     EXPECT_NO_REPORT(driver);
     81     run_one_scan_loop();
     82     key_shift_hold_p_tap.release();
     83 
     84     // First we get the key press
     85     EXPECT_REPORT(driver, (KC_P));
     86     // Then the release
     87     EXPECT_EMPTY_REPORT(driver);
     88     run_one_scan_loop();
     89 
     90     // This sends KC_P, even if it should do nothing
     91     key_shift_hold_p_tap.press();
     92     // This test should not succed if everything works correctly
     93     EXPECT_REPORT(driver, (KC_P));
     94     run_one_scan_loop();
     95 
     96     key_shift_hold_p_tap.release();
     97     EXPECT_EMPTY_REPORT(driver);
     98     idle_for(TAPPING_TERM + 1);
     99 
    100     // On the other hand, nothing is sent if we are outside the tapping term
    101     key_shift_hold_p_tap.press();
    102     EXPECT_NO_REPORT(driver);
    103     run_one_scan_loop();
    104     key_shift_hold_p_tap.release();
    105 
    106     // First we get the key press
    107     EXPECT_REPORT(driver, (KC_P));
    108     // Then the release
    109     EXPECT_EMPTY_REPORT(driver);
    110     idle_for(TAPPING_TERM + 1);
    111 
    112     // Now we are geting into strange territory, as the hold registers too early here
    113     // But the stranges part is:
    114     // If TAPPING_TERM + 1 above is changed to TAPPING_TERM or TAPPING_TERM + 2 it doesn't
    115     key_shift_hold_p_tap.press();
    116     // Shouldn't be called here really
    117     EXPECT_REPORT(driver, (KC_LEFT_SHIFT)).Times(1);
    118     idle_for(TAPPING_TERM);
    119 
    120     EXPECT_EMPTY_REPORT(driver);
    121     key_shift_hold_p_tap.release();
    122     run_one_scan_loop();
    123 }
    124 
    125 TEST_F(Tapping, TapA_CTL_T_KeyWhileReleasingShift) {
    126     TestDriver driver;
    127     InSequence s;
    128     auto       shift_key        = KeymapKey(0, 7, 0, KC_LSFT);
    129     auto       mod_tap_hold_key = KeymapKey(0, 8, 0, CTL_T(KC_P));
    130 
    131     set_keymap({shift_key, mod_tap_hold_key});
    132 
    133     shift_key.press();
    134     // Shift is reported
    135     EXPECT_REPORT(driver, (KC_LSFT));
    136     run_one_scan_loop();
    137     VERIFY_AND_CLEAR(driver);
    138 
    139     mod_tap_hold_key.press();
    140     // Tapping keys does nothing on press
    141     EXPECT_NO_REPORT(driver);
    142     run_one_scan_loop();
    143 
    144     shift_key.release();
    145     // Releasing shift is delayed while tapping is in progress
    146     EXPECT_NO_REPORT(driver);
    147     run_one_scan_loop();
    148     VERIFY_AND_CLEAR(driver);
    149 
    150     mod_tap_hold_key.release();
    151     // Releasing mod-tap key reports the tap and releases shift
    152     EXPECT_REPORT(driver, (KC_LSFT, KC_P));
    153     EXPECT_REPORT(driver, (KC_P));
    154     EXPECT_EMPTY_REPORT(driver);
    155     run_one_scan_loop();
    156     VERIFY_AND_CLEAR(driver);
    157 }
    158 
    159 TEST_F(Tapping, TapA_CTL_T_KeyWhileReleasingLayer) {
    160     TestDriver driver;
    161     InSequence s;
    162     auto       layer_key         = KeymapKey(0, 7, 0, MO(1));
    163     auto       trans_key         = KeymapKey(1, 7, 0, KC_TRNS);
    164     auto       mod_tap_hold_key0 = KeymapKey(0, 8, 0, CTL_T(KC_P));
    165     auto       mod_tap_hold_key1 = KeymapKey(1, 8, 0, CTL_T(KC_Q));
    166 
    167     set_keymap({layer_key, trans_key, mod_tap_hold_key0, mod_tap_hold_key1});
    168 
    169     layer_key.press();
    170     // Pressing the layer key does nothing
    171     EXPECT_NO_REPORT(driver);
    172     run_one_scan_loop();
    173 
    174     mod_tap_hold_key1.press();
    175     // Tapping layer 1 mod-tap key does nothing on press
    176     EXPECT_NO_REPORT(driver);
    177     run_one_scan_loop();
    178 
    179     layer_key.release();
    180     // Releasing layer is delayed while tapping is in progress
    181     EXPECT_NO_REPORT(driver);
    182     run_one_scan_loop();
    183     VERIFY_AND_CLEAR(driver);
    184 
    185     mod_tap_hold_key1.release();
    186     // Releasing mod-tap key reports the tap of the layer 1 key
    187     // If delayed layer release is broken, this reports the layer 0 key
    188     EXPECT_REPORT(driver, (KC_Q));
    189     EXPECT_EMPTY_REPORT(driver);
    190     run_one_scan_loop();
    191     VERIFY_AND_CLEAR(driver);
    192 }