aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quantum/action.c4
-rw-r--r--tests/basic/test_one_shot_keys.cpp336
2 files changed, 339 insertions, 1 deletions
diff --git a/quantum/action.c b/quantum/action.c
index a39631ba3e..395340d9d7 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -817,6 +817,10 @@ void process_action(keyrecord_t *record, action_t action) {
case ACT_LAYER_TAP_EXT:
# endif
led_set(host_keyboard_leds());
+# ifndef NO_ACTION_ONESHOT
+ // don't release the key
+ do_release_oneshot = false;
+# endif
break;
default:
break;
diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp
index 64a8673a5c..92db52f811 100644
--- a/tests/basic/test_one_shot_keys.cpp
+++ b/tests/basic/test_one_shot_keys.cpp
@@ -168,7 +168,7 @@ TEST_F(OneShot, OSMChainingTwoOSMs) {
tap_key(osm_key1);
VERIFY_AND_CLEAR(driver);
- /* Press and relesea OSM2 */
+ /* Press and release OSM2 */
EXPECT_NO_REPORT(driver);
tap_key(osm_key2);
VERIFY_AND_CLEAR(driver);
@@ -353,3 +353,337 @@ TEST_F(OneShot, OSLWithOsmAndAdditionalKeypress) {
run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
}
+
+TEST_F(OneShot, OSLWithMoAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey mo_key = KeymapKey{1, 1, 0, MO(2)};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl_key, mo_key, regular_key});
+
+ /* Press OSL key */
+ EXPECT_NO_REPORT(driver);
+ osl_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release OSL key */
+ EXPECT_NO_REPORT(driver);
+ osl_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press MO */
+ EXPECT_NO_REPORT(driver);
+ mo_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release MO */
+ EXPECT_NO_REPORT(driver);
+ mo_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ VERIFY_AND_CLEAR(driver);
+}
+
+class OneShotLayerParametrizedTestFixture : public ::testing::WithParamInterface<uint16_t>, public OneShot {};
+
+TEST_P(OneShotLayerParametrizedTestFixture, OSLWithActionAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey action_key = KeymapKey{1, 1, 0, GetParam()};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl_key, action_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Tag Action key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(action_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+INSTANTIATE_TEST_CASE_P(OneShotLayerTests, OneShotLayerParametrizedTestFixture, ::testing::Values(TG(2), TO(2)));
+
+TEST_F(OneShot, OSLWithDFAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey df_key = KeymapKey{1, 1, 0, DF(2)};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl_key, df_key, regular_key});
+
+ layer_state_t default_layer_state_bak = default_layer_state;
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press DF key */
+ EXPECT_NO_REPORT(driver);
+ df_key.press();
+ run_one_scan_loop();
+ EXPECT_EQ(default_layer_state, 0b001);
+
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release DF key */
+ EXPECT_NO_REPORT(driver);
+ df_key.release();
+ run_one_scan_loop();
+ EXPECT_EQ(default_layer_state, 0b100);
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ default_layer_state = default_layer_state_bak;
+}
+
+TEST_F(OneShot, OSLChainingTwoOSLsAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl1_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey osl2_key = KeymapKey{1, 1, 0, OSL(2)};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl1_key, osl2_key, regular_key});
+
+ /* Press and release first OSL key */
+ EXPECT_NO_REPORT(driver);
+ osl1_key.press();
+ run_one_scan_loop();
+ osl1_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press and release second OSL */
+ EXPECT_NO_REPORT(driver);
+ osl2_key.press();
+ run_one_scan_loop();
+ osl2_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_NO_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithShortLT) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey lt_key = KeymapKey(1, 1, 0, LT(2, KC_A));
+
+ set_keymap({osl_key, lt_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Tap LT key. */
+ EXPECT_REPORT(driver, (lt_key.report_code)).Times(1);
+ EXPECT_EMPTY_REPORT(driver);
+ tap_key(lt_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithLongLTAndRegularKey) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey lt_key = KeymapKey(1, 1, 0, LT(2, KC_A));
+ KeymapKey regular_key = KeymapKey(2, 1, 1, KC_B);
+
+ set_keymap({osl_key, lt_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press LT key. */
+ EXPECT_NO_REPORT(driver);
+ lt_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Idle for tapping term of mod tap hold key. */
+ EXPECT_NO_REPORT(driver);
+ idle_for(TAPPING_TERM + 1);
+ VERIFY_AND_CLEAR(driver);
+ EXPECT_TRUE(layer_state_is(2));
+
+ /* Press regular key. */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key. */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithShortModTapKeyAndRegularKey) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey mod_tap_hold_key = KeymapKey(1, 1, 0, SFT_T(KC_P));
+ KeymapKey regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({osl_key, mod_tap_hold_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press mod-tap-hold key. */
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key. */
+ EXPECT_REPORT(driver, (regular_key.report_code));
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key. */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithLongModTapKeyAndRegularKey) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey mod_tap_hold_key = KeymapKey(1, 1, 0, SFT_T(KC_P));
+ KeymapKey regular_key = KeymapKey(1, 2, 0, KC_A);
+
+ set_keymap({osl_key, mod_tap_hold_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press mod-tap-hold key. */
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Idle for tapping term of mod tap hold key. */
+ EXPECT_REPORT(driver, (KC_LSFT));
+ idle_for(TAPPING_TERM + 1);
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key. */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key. */
+ EXPECT_NO_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+} \ No newline at end of file