From 9d6db95f0b1675d4781171df6c75e909d04ebd63 Mon Sep 17 00:00:00 2001 From: bluepython508 Date: Thu, 7 Mar 2024 16:14:05 +0000 Subject: [PATCH] Timer on oneshot mods: held for one second doesn't queue modifiers --- .../kyria/rev3/keymaps/bluepython508/keymap.c | 75 +++++++++++-------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/keyboards/splitkb/kyria/rev3/keymaps/bluepython508/keymap.c b/keyboards/splitkb/kyria/rev3/keymaps/bluepython508/keymap.c index 7e69c15..4e8f6bd 100644 --- a/keyboards/splitkb/kyria/rev3/keymaps/bluepython508/keymap.c +++ b/keyboards/splitkb/kyria/rev3/keymaps/bluepython508/keymap.c @@ -14,6 +14,7 @@ * along with this program. If not, see . */ #include "action.h" +#include "timer.h" #include QMK_KEYBOARD_H enum keycodes { @@ -205,10 +206,21 @@ typedef enum { os_down_unused, os_down_used, os_locked +} oneshot_mode_t; + +typedef struct { + uint16_t time; + uint16_t mod; + uint16_t trigger; + oneshot_mode_t mode; } oneshot_state_t; -oneshot_state_t oneshot_state[4] = {0}; -uint16_t mods[] = {KC_LSFT, KC_LCTL, KC_LALT, KC_LGUI}; +oneshot_state_t oneshot_state[4] = { + { 0, KC_LSFT, OS_LSFT, os_up_unqueued }, + { 0, KC_LCTL, OS_LCTL, os_up_unqueued }, + { 0, KC_LALT, OS_LALT, os_up_unqueued }, + { 0, KC_LGUI, OS_LGUI, os_up_unqueued } +}; bool is_oneshot_ignored_key(uint16_t keycode) { switch (keycode) { @@ -228,11 +240,6 @@ bool is_oneshot_ignored_key(uint16_t keycode) { bool is_oneshot_cancel_key(uint16_t keycode) { switch (keycode) { - // case NAV: - // case SYM: - // case NUM: - // case FUN: - // return true; case KC_NO: return true; default: @@ -243,40 +250,44 @@ bool is_oneshot_cancel_key(uint16_t keycode) { // Based on https://github.com/qmk/qmk_firmware/blob/user-keymaps-still-present/users/callum/oneshot.c void update_oneshot( oneshot_state_t *state, - uint16_t mod, - uint16_t trigger, uint16_t keycode, keyrecord_t *record ) { - if (keycode == trigger) { + if (keycode == state->trigger) { if (record->event.pressed) { // Trigger keydown - switch (*state) { + switch (state->mode) { case os_up_queued: - *state = os_locked; + state->mode = os_locked; break; case os_up_unqueued: - register_code(mod); - *state = os_down_unused; + register_code(state->mod); + state->time = timer_read(); + state->mode = os_down_unused; break; case os_locked: - *state = os_down_used; + state->mode = os_down_used; break; default: - *state = os_down_unused; + state->mode = os_down_unused; break; } } else { // Trigger keyup - switch (*state) { + switch (state->mode) { case os_down_unused: // If we didn't use the mod while trigger was held, queue it. - *state = os_up_queued; + if (timer_elapsed(state->time) < 1000) { + state->mode = os_up_queued; + } else { + state->mode = os_up_unqueued; + unregister_code(state->mod); + } break; case os_down_used: // If we did use the mod while trigger was held, unregister it. - *state = os_up_unqueued; - unregister_code(mod); + state->mode = os_up_unqueued; + unregister_code(state->mod); break; default: break; @@ -284,21 +295,21 @@ void update_oneshot( } } else { if (record->event.pressed) { - if (is_oneshot_cancel_key(keycode) && *state != os_up_unqueued) { + if (is_oneshot_cancel_key(keycode) && state->mode != os_up_unqueued) { // Cancel oneshot on designated cancel keydown. - *state = os_up_unqueued; - unregister_code(mod); + state->mode = os_up_unqueued; + unregister_code(state->mod); } } else { if (!is_oneshot_ignored_key(keycode)) { // On non-ignored keyup, consider the oneshot used. - switch (*state) { + switch (state->mode) { case os_down_unused: - *state = os_down_used; + state->mode = os_down_used; break; case os_up_queued: - *state = os_up_unqueued; - unregister_code(mod); + state->mode = os_up_unqueued; + unregister_code(state->mod); break; default: break; @@ -309,12 +320,12 @@ void update_oneshot( } bool process_record_user(uint16_t keycode, keyrecord_t *record) { - update_oneshot(&oneshot_state[0], mods[0], OS_LSFT, keycode, record); - update_oneshot(&oneshot_state[1], mods[1], OS_LCTL, keycode, record); - update_oneshot(&oneshot_state[2], mods[2], OS_LALT, keycode, record); - update_oneshot(&oneshot_state[3], mods[3], OS_LGUI, keycode, record); + update_oneshot(&oneshot_state[0], keycode, record); + update_oneshot(&oneshot_state[1], keycode, record); + update_oneshot(&oneshot_state[2], keycode, record); + update_oneshot(&oneshot_state[3], keycode, record); - if (oneshot_state[0] == os_locked && keycode == KC_SPACE) { + if (oneshot_state[0].mode == os_locked && keycode == KC_SPACE) { if (record->event.pressed) { register_code(KC_MINUS); } else {