From 75c04fc2b79bb922c325707132360ba9229711e6 Mon Sep 17 00:00:00 2001 From: Jari Meevis Date: Sun, 16 Feb 2025 17:08:32 +0100 Subject: [PATCH 1/5] fix oneshot keys sent to host when held after tapping --- quantum/action_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantum/action_util.c b/quantum/action_util.c index c0dc4f38228..9f2a30b7a78 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -267,8 +267,9 @@ static uint8_t get_mods_for_report(void) { clear_oneshot_mods(); } # endif - mods |= oneshot_mods; if (has_anykey()) { + // only send oneshots to host if used with a real key + mods |= oneshot_mods; clear_oneshot_mods(); } } From 3fbb770de36c4180bf3f952ad6ac81f29ae38452 Mon Sep 17 00:00:00 2001 From: Jari Meevis Date: Sat, 1 Mar 2025 01:58:09 +0100 Subject: [PATCH 2/5] Revert "fix oneshot keys sent to host when held after tapping" This reverts commit c2d4dd5333256437073780bdea9e223b3c5635d0. --- quantum/action_util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/quantum/action_util.c b/quantum/action_util.c index 9f2a30b7a78..c0dc4f38228 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -267,9 +267,8 @@ static uint8_t get_mods_for_report(void) { clear_oneshot_mods(); } # endif + mods |= oneshot_mods; if (has_anykey()) { - // only send oneshots to host if used with a real key - mods |= oneshot_mods; clear_oneshot_mods(); } } From e9d8d7734dfe274c0e1500e50e7537c24c53c1ea Mon Sep 17 00:00:00 2001 From: Jari Meevis Date: Sat, 1 Mar 2025 02:01:28 +0100 Subject: [PATCH 3/5] reset one shots when held --- quantum/action.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quantum/action.c b/quantum/action.c index be85192d25a..d76012226be 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -466,6 +466,8 @@ void process_action(keyrecord_t *record, action_t action) { // Not a tap, but a hold: register the held mod ac_dprintf("MODS_TAP: Oneshot: 0\n"); register_mods(mods); + del_oneshot_mods(mods); + del_oneshot_locked_mods(mods); } else if (tap_count == 1) { ac_dprintf("MODS_TAP: Oneshot: start\n"); add_oneshot_mods(mods); From b8be8cf9a90542164c9cc1bbc8461942618e22c8 Mon Sep 17 00:00:00 2001 From: Jari Meevis Date: Sat, 1 Mar 2025 02:02:59 +0100 Subject: [PATCH 4/5] [wip] add test --- tests/basic/test_one_shot_keys.cpp | 61 ++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp index 92db52f811e..1730d6cbb7d 100644 --- a/tests/basic/test_one_shot_keys.cpp +++ b/tests/basic/test_one_shot_keys.cpp @@ -15,8 +15,11 @@ */ #include "action_util.h" +#include "config.h" #include "keyboard_report_util.hpp" #include "test_common.hpp" +#include +#include using testing::_; using testing::InSequence; @@ -24,24 +27,19 @@ using testing::InSequence; class OneShot : public TestFixture {}; class OneShotParametrizedTestFixture : public ::testing::WithParamInterface>, public OneShot {}; -TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) { +TEST_F(OneShot, OSMWithoutAdditionalKeypressSetsOneShotModsButDoesNotSendReport) { TestDriver driver; auto osm_key = KeymapKey(0, 0, 0, OSM(MOD_LSFT), KC_LSFT); + auto a_key = KeymapKey(0, 0, 0, KC_A); set_keymap({osm_key}); - /* Press and release OSM key*/ + /* Press and release OSM key should set one shot mods*/ EXPECT_NO_REPORT(driver); tap_key(osm_key); + EXPECT_EQ(get_oneshot_mods(), MOD_LSFT); VERIFY_AND_CLEAR(driver); - - /* OSM are added when an actual report is send */ - EXPECT_REPORT(driver, (osm_key.report_code)); - send_keyboard_report(); - VERIFY_AND_CLEAR(driver); - - /* Make unit-test pass */ - clear_oneshot_mods(); + clear_oneshot_mods(); // reset state } #if defined(ONESHOT_TIMEOUT) @@ -277,6 +275,47 @@ TEST_F(OneShot, OSMHoldNotLockingOSMs) { VERIFY_AND_CLEAR(driver); } +TEST_F(OneShot, OSMTapThenHoldNotLockingOSMs) { + TestDriver driver; + InSequence s; + KeymapKey osm_key = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}; + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + + set_keymap({osm_key, regular_key}); + + /* Press and release OSM */ + EXPECT_NO_REPORT(driver); + tap_key(osm_key); + VERIFY_AND_CLEAR(driver); + + /* Press and hold OSM */ + EXPECT_REPORT(driver, (osm_key.report_code)).Times(1); + osm_key.press(); + run_one_scan_loop(); + idle_for(TAPPING_TERM); + // EXPECT_EQ(get_oneshot_mods(), b02); // one shot mods should be disabled + VERIFY_AND_CLEAR(driver); + + /* Release OSM1 */ + EXPECT_EMPTY_REPORT(driver); + osm_key.release(); + run_one_scan_loop(); + // EXPECT_EQ(get_oneshot_mods(), 0); // one shot mods should be disabled + VERIFY_AND_CLEAR(driver); + + /* Press regular key */ + EXPECT_REPORT(driver, (regular_key.report_code)).Times(1); // no mod + 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, OSLWithAdditionalKeypress) { TestDriver driver; InSequence s; @@ -686,4 +725,4 @@ TEST_F(OneShot, OSLWithLongModTapKeyAndRegularKey) { regular_key.release(); run_one_scan_loop(); VERIFY_AND_CLEAR(driver); -} \ No newline at end of file +} From 26a1fdafa67a08124415eb2078dabdcc9468294f Mon Sep 17 00:00:00 2001 From: Jari Meevis Date: Wed, 23 Apr 2025 22:12:15 +0200 Subject: [PATCH 5/5] wip(fix tests) --- quantum/action.c | 2 +- tests/basic/test_one_shot_keys.cpp | 33 ++++++++++++++++++------------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/quantum/action.c b/quantum/action.c index d76012226be..6e623a65f0d 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -463,7 +463,7 @@ void process_action(keyrecord_t *record, action_t action) { } else { if (event.pressed) { if (tap_count == 0) { - // Not a tap, but a hold: register the held mod + // Not a tap, but a hold: register the mods, replacing the oneshots ac_dprintf("MODS_TAP: Oneshot: 0\n"); register_mods(mods); del_oneshot_mods(mods); diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp index 1730d6cbb7d..83a878e2094 100644 --- a/tests/basic/test_one_shot_keys.cpp +++ b/tests/basic/test_one_shot_keys.cpp @@ -16,9 +16,7 @@ #include "action_util.h" #include "config.h" -#include "keyboard_report_util.hpp" #include "test_common.hpp" -#include #include using testing::_; @@ -275,7 +273,7 @@ TEST_F(OneShot, OSMHoldNotLockingOSMs) { VERIFY_AND_CLEAR(driver); } -TEST_F(OneShot, OSMTapThenHoldNotLockingOSMs) { +TEST_F(OneShot, OSMTapThenHoldShouldSendEmptyReport) { TestDriver driver; InSequence s; KeymapKey osm_key = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}; @@ -283,36 +281,45 @@ TEST_F(OneShot, OSMTapThenHoldNotLockingOSMs) { set_keymap({osm_key, regular_key}); + /* + * for some reason, none of the OSM keys are registered + * */ + /* Press and release OSM */ EXPECT_NO_REPORT(driver); tap_key(osm_key); + EXPECT_EQ(get_oneshot_mods(), 0x02); // verify oneshots are turned on VERIFY_AND_CLEAR(driver); - /* Press and hold OSM */ - EXPECT_REPORT(driver, (osm_key.report_code)).Times(1); + /* Press OSM */ + EXPECT_NO_REPORT(driver); osm_key.press(); - run_one_scan_loop(); - idle_for(TAPPING_TERM); - // EXPECT_EQ(get_oneshot_mods(), b02); // one shot mods should be disabled + run_one_scan_loop(); // not yet registered VERIFY_AND_CLEAR(driver); - /* Release OSM1 */ - EXPECT_EMPTY_REPORT(driver); + /* Hold OSM */ + EXPECT_REPORT(driver, (osm_key.report_code)).Times(1); // report should be send now + idle_for(TAPPING_TERM); + EXPECT_EQ(get_oneshot_mods(), 0x00); // key registered as hold, OSM should be disabled + VERIFY_AND_CLEAR(driver); + + /* Release OSM */ + EXPECT_EMPTY_REPORT(driver); // key released so we expect empty report (i.e. no key pressed) osm_key.release(); run_one_scan_loop(); - // EXPECT_EQ(get_oneshot_mods(), 0); // one shot mods should be disabled + EXPECT_EQ(get_oneshot_mods(), 0x00); // one shot mods should still be disabled VERIFY_AND_CLEAR(driver); /* Press regular key */ - EXPECT_REPORT(driver, (regular_key.report_code)).Times(1); // no mod regular_key.press(); run_one_scan_loop(); + EXPECT_REPORT(driver, (regular_key.report_code)).Times(1); // should not be modded VERIFY_AND_CLEAR(driver); /* Release regular key */ - EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); + EXPECT_EMPTY_REPORT(driver); VERIFY_AND_CLEAR(driver); }