From 46844347c4f4b5f8b50ea22dd06c7555a86fc94b Mon Sep 17 00:00:00 2001 From: Kasimir Pihlasviita Date: Mon, 3 Apr 2023 08:38:44 +0300 Subject: Fix OSMs getting stuck (#20034) --- tests/basic/test_one_shot_keys.cpp | 144 +++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) (limited to 'tests/basic') diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp index 2401c2c837..2a3434bf16 100644 --- a/tests/basic/test_one_shot_keys.cpp +++ b/tests/basic/test_one_shot_keys.cpp @@ -160,6 +160,150 @@ INSTANTIATE_TEST_CASE_P( )); // clang-format on +TEST_F(OneShot, OSMChainingTwoOSMs) { + TestDriver driver; + InSequence s; + KeymapKey osm_key1 = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}; + KeymapKey osm_key2 = KeymapKey{0, 0, 1, OSM(MOD_LCTL), KC_LCTL}; + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + + set_keymap({osm_key1, osm_key2, regular_key}); + + /* Press and release OSM1 */ + EXPECT_NO_REPORT(driver); + osm_key1.press(); + run_one_scan_loop(); + osm_key1.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Press and relesea OSM2 */ + EXPECT_NO_REPORT(driver); + osm_key2.press(); + run_one_scan_loop(); + osm_key2.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Press regular key */ + EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code, 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, OSMDoubleTapNotLockingOSMs) { + TestDriver driver; + InSequence s; + KeymapKey osm_key1 = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}; + KeymapKey osm_key2 = KeymapKey{0, 0, 1, OSM(MOD_LCTL), KC_LCTL}; + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + + set_keymap({osm_key1, osm_key2, regular_key}); + + /* Press and release OSM1 */ + EXPECT_NO_REPORT(driver); + osm_key1.press(); + run_one_scan_loop(); + osm_key1.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Press and release OSM2 twice */ + EXPECT_NO_REPORT(driver); + osm_key2.press(); + run_one_scan_loop(); + osm_key2.release(); + run_one_scan_loop(); + osm_key2.press(); + run_one_scan_loop(); + osm_key2.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Press regular key */ + EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code, 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); + + /* 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, OSMHoldNotLockingOSMs) { + TestDriver driver; + InSequence s; + KeymapKey osm_key1 = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}; + KeymapKey osm_key2 = KeymapKey{0, 0, 1, OSM(MOD_LCTL), KC_LCTL}; + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + + set_keymap({osm_key1, osm_key2, regular_key}); + + /* Press and release OSM1 */ + EXPECT_NO_REPORT(driver); + osm_key1.press(); + run_one_scan_loop(); + osm_key1.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Press and hold OSM2 */ + EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code)).Times(1); + osm_key2.press(); + run_one_scan_loop(); + idle_for(TAPPING_TERM); + VERIFY_AND_CLEAR(driver); + + /* Press and release regular key */ + EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code, regular_key.report_code)).Times(1); + EXPECT_REPORT(driver, (osm_key2.report_code)).Times(1); + regular_key.press(); + run_one_scan_loop(); + regular_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Release OSM2 */ + EXPECT_EMPTY_REPORT(driver); + osm_key2.release(); + run_one_scan_loop(); + 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); +} + TEST_F(OneShot, OSLWithAdditionalKeypress) { TestDriver driver; InSequence s; -- cgit 1.4.1 From 128f808496cf7800fde3c7508388745bd99e8016 Mon Sep 17 00:00:00 2001 From: Albert Y <76888457+filterpaper@users.noreply.github.com> Date: Sat, 13 May 2023 15:42:06 +0800 Subject: Add a user callback for pre process record (#20584) --- docs/understanding_qmk.md | 2 ++ quantum/action.c | 5 +---- quantum/quantum.c | 17 ++++++++++++----- quantum/quantum.h | 3 +++ tests/basic/test_action_layer.cpp | 3 ++- 5 files changed, 20 insertions(+), 10 deletions(-) (limited to 'tests/basic') diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md index 7b436a45be..9c5f0419a1 100644 --- a/docs/understanding_qmk.md +++ b/docs/understanding_qmk.md @@ -130,6 +130,8 @@ The `process_record()` function itself is deceptively simple, but hidden within * [`void action_exec(keyevent_t event)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/action.c#L78-L140) * [`void pre_process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/quantum.c#L204) * [`bool process_combo(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/process_keycode/process_combo.c#L521) + * [`bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/27119fa77e8a1b95fff80718d3db4f3e32849298/quantum/quantum.c#L117) + * [`bool pre_process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/27119fa77e8a1b95fff80718d3db4f3e32849298/quantum/quantum.c#L121) * [`void process_record(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/action.c#L254) * [`bool process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/quantum.c#L224) * [Map this record to a keycode](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/quantum.c#L225) diff --git a/quantum/action.c b/quantum/action.c index a683ff1130..59bfefc495 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -30,6 +30,7 @@ along with this program. If not, see . #include "wait.h" #include "keycode_config.h" #include "debug.h" +#include "quantum.h" #ifdef BACKLIGHT_ENABLE # include "backlight.h" @@ -65,10 +66,6 @@ __attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *reco } #endif -__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { - return true; -} - /** \brief Called to execute an action. * * FIXME: Needs documentation. diff --git a/quantum/quantum.c b/quantum/quantum.c index 0587f215fe..950be3182e 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -114,6 +114,14 @@ __attribute__((weak)) void tap_code16(uint16_t code) { tap_code16_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } +__attribute__((weak)) bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record) { + return pre_process_record_user(keycode, record); +} + +__attribute__((weak)) bool pre_process_record_user(uint16_t keycode, keyrecord_t *record) { + return true; +} + __attribute__((weak)) bool process_action_kb(keyrecord_t *record) { return true; } @@ -202,14 +210,13 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) { /* Get keycode, and then process pre tapping functionality */ bool pre_process_record_quantum(keyrecord_t *record) { - if (!( + uint16_t keycode = get_record_keycode(record, true); #ifdef COMBO_ENABLE - process_combo(get_record_keycode(record, true), record) && -#endif - true)) { + if (!(process_combo(keycode, record))) { return false; } - return true; // continue processing +#endif + return pre_process_record_kb(keycode, record); } /* Get keycode, and then call keyboard function */ diff --git a/quantum/quantum.h b/quantum/quantum.h index 38186a48a3..fec92a5244 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -261,6 +261,9 @@ void set_single_persistent_default_layer(uint8_t default_layer); uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache); uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); +bool pre_process_record_quantum(keyrecord_t *record); +bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record); +bool pre_process_record_user(uint16_t keycode, keyrecord_t *record); bool process_action_kb(keyrecord_t *record); bool process_record_kb(uint16_t keycode, keyrecord_t *record); bool process_record_user(uint16_t keycode, keyrecord_t *record); diff --git a/tests/basic/test_action_layer.cpp b/tests/basic/test_action_layer.cpp index b7ecfa52ef..0aa4b78007 100644 --- a/tests/basic/test_action_layer.cpp +++ b/tests/basic/test_action_layer.cpp @@ -365,9 +365,10 @@ TEST_F(ActionLayer, LayerTapReleasedBeforeKeypressReleaseWithModifiers) { InSequence s; KeymapKey layer_0_key_0 = KeymapKey{0, 0, 0, LT(1, KC_T)}; + KeymapKey layer_0_key_1 = KeymapKey{0, 1, 0, KC_X}; KeymapKey layer_1_key_1 = KeymapKey{1, 1, 0, RALT(KC_9)}; - set_keymap({layer_0_key_0, layer_1_key_1}); + set_keymap({layer_0_key_0, layer_0_key_1, layer_1_key_1}); /* Press layer tap and wait for tapping term to switch to layer 1 */ EXPECT_NO_REPORT(driver); -- cgit 1.4.1