mirror of
https://github.com/qmk/qmk_firmware.git
synced 2024-11-24 12:22:57 +00:00
Fix OSMs getting stuck (#20034)
This commit is contained in:
parent
1899793f27
commit
46844347c4
@ -435,39 +435,32 @@ void process_action(keyrecord_t *record, action_t action) {
|
|||||||
} else {
|
} else {
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
if (tap_count == 0) {
|
if (tap_count == 0) {
|
||||||
|
// Not a tap, but a hold: register the held mod
|
||||||
ac_dprintf("MODS_TAP: Oneshot: 0\n");
|
ac_dprintf("MODS_TAP: Oneshot: 0\n");
|
||||||
register_mods(mods | get_oneshot_mods());
|
register_mods(mods);
|
||||||
} else if (tap_count == 1) {
|
} else if (tap_count == 1) {
|
||||||
ac_dprintf("MODS_TAP: Oneshot: start\n");
|
ac_dprintf("MODS_TAP: Oneshot: start\n");
|
||||||
set_oneshot_mods(mods | get_oneshot_mods());
|
add_oneshot_mods(mods);
|
||||||
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
|
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
|
||||||
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
|
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
|
||||||
ac_dprintf("MODS_TAP: Toggling oneshot");
|
ac_dprintf("MODS_TAP: Toggling oneshot");
|
||||||
register_mods(mods);
|
register_mods(mods);
|
||||||
clear_oneshot_mods();
|
del_oneshot_mods(mods);
|
||||||
set_oneshot_locked_mods(mods | get_oneshot_locked_mods());
|
add_oneshot_locked_mods(mods);
|
||||||
# endif
|
# endif
|
||||||
} else {
|
|
||||||
register_mods(mods | get_oneshot_mods());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tap_count == 0) {
|
if (tap_count == 0) {
|
||||||
clear_oneshot_mods();
|
// Release hold: unregister the held mod and its variants
|
||||||
unregister_mods(mods);
|
unregister_mods(mods);
|
||||||
} else if (tap_count == 1) {
|
del_oneshot_mods(mods);
|
||||||
// Retain Oneshot mods
|
del_oneshot_locked_mods(mods);
|
||||||
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
|
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
|
||||||
if (mods & get_mods()) {
|
} else if (tap_count == 1 && (mods & get_mods())) {
|
||||||
unregister_mods(mods);
|
|
||||||
clear_oneshot_mods();
|
|
||||||
set_oneshot_locked_mods(~mods & get_oneshot_locked_mods());
|
|
||||||
}
|
|
||||||
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
|
|
||||||
// Toggle Oneshot Layer
|
|
||||||
# endif
|
|
||||||
} else {
|
|
||||||
unregister_mods(mods);
|
unregister_mods(mods);
|
||||||
clear_oneshot_mods();
|
del_oneshot_mods(mods);
|
||||||
|
del_oneshot_locked_mods(mods);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,12 @@ static uint8_t oneshot_locked_mods = 0;
|
|||||||
uint8_t get_oneshot_locked_mods(void) {
|
uint8_t get_oneshot_locked_mods(void) {
|
||||||
return oneshot_locked_mods;
|
return oneshot_locked_mods;
|
||||||
}
|
}
|
||||||
|
void add_oneshot_locked_mods(uint8_t mods) {
|
||||||
|
if ((oneshot_locked_mods & mods) != mods) {
|
||||||
|
oneshot_locked_mods |= mods;
|
||||||
|
oneshot_locked_mods_changed_kb(oneshot_locked_mods);
|
||||||
|
}
|
||||||
|
}
|
||||||
void set_oneshot_locked_mods(uint8_t mods) {
|
void set_oneshot_locked_mods(uint8_t mods) {
|
||||||
if (mods != oneshot_locked_mods) {
|
if (mods != oneshot_locked_mods) {
|
||||||
oneshot_locked_mods = mods;
|
oneshot_locked_mods = mods;
|
||||||
@ -58,6 +64,12 @@ void clear_oneshot_locked_mods(void) {
|
|||||||
oneshot_locked_mods_changed_kb(oneshot_locked_mods);
|
oneshot_locked_mods_changed_kb(oneshot_locked_mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void del_oneshot_locked_mods(uint8_t mods) {
|
||||||
|
if (oneshot_locked_mods & mods) {
|
||||||
|
oneshot_locked_mods &= ~mods;
|
||||||
|
oneshot_locked_mods_changed_kb(oneshot_locked_mods);
|
||||||
|
}
|
||||||
|
}
|
||||||
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
|
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
|
||||||
static uint16_t oneshot_time = 0;
|
static uint16_t oneshot_time = 0;
|
||||||
bool has_oneshot_mods_timed_out(void) {
|
bool has_oneshot_mods_timed_out(void) {
|
||||||
|
@ -65,8 +65,10 @@ void clear_oneshot_mods(void);
|
|||||||
bool has_oneshot_mods_timed_out(void);
|
bool has_oneshot_mods_timed_out(void);
|
||||||
|
|
||||||
uint8_t get_oneshot_locked_mods(void);
|
uint8_t get_oneshot_locked_mods(void);
|
||||||
|
void add_oneshot_locked_mods(uint8_t mods);
|
||||||
void set_oneshot_locked_mods(uint8_t mods);
|
void set_oneshot_locked_mods(uint8_t mods);
|
||||||
void clear_oneshot_locked_mods(void);
|
void clear_oneshot_locked_mods(void);
|
||||||
|
void del_oneshot_locked_mods(uint8_t mods);
|
||||||
|
|
||||||
typedef enum { ONESHOT_PRESSED = 0b01, ONESHOT_OTHER_KEY_PRESSED = 0b10, ONESHOT_START = 0b11, ONESHOT_TOGGLED = 0b100 } oneshot_fullfillment_t;
|
typedef enum { ONESHOT_PRESSED = 0b01, ONESHOT_OTHER_KEY_PRESSED = 0b10, ONESHOT_START = 0b11, ONESHOT_TOGGLED = 0b100 } oneshot_fullfillment_t;
|
||||||
void set_oneshot_layer(uint8_t layer, uint8_t state);
|
void set_oneshot_layer(uint8_t layer, uint8_t state);
|
||||||
|
@ -160,6 +160,150 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
));
|
));
|
||||||
// clang-format on
|
// 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) {
|
TEST_F(OneShot, OSLWithAdditionalKeypress) {
|
||||||
TestDriver driver;
|
TestDriver driver;
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
Loading…
Reference in New Issue
Block a user