summaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
authorQMK Bot <hello@qmk.fm>2023-04-03 22:43:55 +0000
committerQMK Bot <hello@qmk.fm>2023-04-03 22:43:55 +0000
commitb67bdf222e0bc98b846f20e22152cd0a007fb9f7 (patch)
treef0bc182baac4da3b7f25630ef788f1ab0f6c5021 /users
parent49ac29fa09cbd770f5983f0d1c3ec9b5ce2e0c51 (diff)
parent246cf99b4b029b6d36e82a0c4c3aed11abb2ff5e (diff)
Merge remote-tracking branch 'origin/master' into develop
Diffstat (limited to 'users')
-rw-r--r--users/cameronjlarsen/features/oneshot.c66
-rw-r--r--users/cameronjlarsen/features/oneshot.h41
-rw-r--r--users/cameronjlarsen/rules.mk5
3 files changed, 112 insertions, 0 deletions
diff --git a/users/cameronjlarsen/features/oneshot.c b/users/cameronjlarsen/features/oneshot.c
new file mode 100644
index 0000000000..799b7c1aa2
--- /dev/null
+++ b/users/cameronjlarsen/features/oneshot.c
@@ -0,0 +1,66 @@
1/* Copyright 2022 Cameron Larsen <camjlarsen@gmail.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "oneshot.h"
17
18void update_oneshot(oneshot_state *state, uint16_t mod, uint16_t trigger, uint16_t keycode, keyrecord_t *record) {
19 if (keycode == trigger) {
20 if (record->event.pressed) {
21 // Trigger keydown
22 if (*state == os_up_unqueued) {
23 register_code(mod);
24 }
25 *state = os_down_unused;
26 } else {
27 // Trigger keyup
28 switch (*state) {
29 case os_down_unused:
30 // If we didn't use the mod while trigger was held, queue it.
31 *state = os_up_queued;
32 break;
33 case os_down_used:
34 // If we did use the mod while trigger was held, unregister it.
35 *state = os_up_unqueued;
36 unregister_code(mod);
37 break;
38 default:
39 break;
40 }
41 }
42 } else {
43 if (record->event.pressed) {
44 if (is_oneshot_cancel_key(keycode) && *state != os_up_unqueued) {
45 // Cancel oneshot on designated cancel keydown.
46 *state = os_up_unqueued;
47 unregister_code(mod);
48 }
49 } else {
50 if (!is_oneshot_ignored_key(keycode)) {
51 // On non-ignored keyup, consider the oneshot used.
52 switch (*state) {
53 case os_down_unused:
54 *state = os_down_used;
55 break;
56 case os_up_queued:
57 *state = os_up_unqueued;
58 unregister_code(mod);
59 break;
60 default:
61 break;
62 }
63 }
64 }
65 }
66}
diff --git a/users/cameronjlarsen/features/oneshot.h b/users/cameronjlarsen/features/oneshot.h
new file mode 100644
index 0000000000..7fac7b5d58
--- /dev/null
+++ b/users/cameronjlarsen/features/oneshot.h
@@ -0,0 +1,41 @@
1// The GPLv2 License (GPLv2)
2//
3// Copyright (c) 2022 Cameron Larsen
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17#pragma once
18
19#include QMK_KEYBOARD_H
20
21// Represents the four states a oneshot key can be in
22typedef enum {
23 os_up_unqueued,
24 os_up_queued,
25 os_down_unused,
26 os_down_used,
27} oneshot_state;
28
29// Custom oneshot mod implementation that doesn't rely on timers. If a mod is
30// used while it is held it will be unregistered on keyup as normal, otherwise
31// it will be queued and only released after the next non-mod keyup.
32void update_oneshot(oneshot_state *state, uint16_t mod, uint16_t trigger, uint16_t keycode, keyrecord_t *record);
33
34// To be implemented by the consumer. Defines keys to cancel oneshot mods.
35bool is_oneshot_cancel_key(uint16_t keycode);
36
37// To be implemented by the consumer. Defines keys to ignore when determining
38// whether a oneshot mod has been used. Setting this to modifiers and layer
39// change keys allows stacking multiple oneshot modifiers, and carrying them
40// between layers.
41bool is_oneshot_ignored_key(uint16_t keycode);
diff --git a/users/cameronjlarsen/rules.mk b/users/cameronjlarsen/rules.mk
new file mode 100644
index 0000000000..59d14ca61f
--- /dev/null
+++ b/users/cameronjlarsen/rules.mk
@@ -0,0 +1,5 @@
1CUSTOM_ONESHOT_ENABLE ?= no
2ifeq ($(strip $(CUSTOM_ONESHOT_ENABLE)), yes)
3 SRC += $(USER_PATH)/features/oneshot.c
4 OPT_DEFS += -DCUSTOM_ONESHOT_ENABLE
5endif