summaryrefslogtreecommitdiffstats
path: root/users/ericgebhart/extensions/tap_hold.c
diff options
context:
space:
mode:
authorDrashna Jael're <drashna@live.com>2022-11-12 17:10:04 -0800
committerDrashna Jael're <drashna@live.com>2022-11-12 17:10:04 -0800
commit731633e133de428408cd313fbd65fb0a36145672 (patch)
treeb788a9fe150a353ce20d338848d3dab2bbc42879 /users/ericgebhart/extensions/tap_hold.c
parent6cc9513ab0cd5e21354c51ab83a89af9f2eb517e (diff)
parent2e39647618295e4a2ba685cfb8e3ab36622e92ee (diff)
Merge remote-tracking branch 'origin/master' into develop
Diffstat (limited to 'users/ericgebhart/extensions/tap_hold.c')
-rw-r--r--users/ericgebhart/extensions/tap_hold.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/users/ericgebhart/extensions/tap_hold.c b/users/ericgebhart/extensions/tap_hold.c
new file mode 100644
index 0000000000..041b961e11
--- /dev/null
+++ b/users/ericgebhart/extensions/tap_hold.c
@@ -0,0 +1,165 @@
+/*
+ Copyright 2022 Eric Gebhart <e.a.gebhart@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* This is variations on custom tap hold functionality. It makes it easy */
+/* to maintain tap_hold keys and combinations. These combinations go into */
+/* the file "tap_hold.def". Here are two examples. */
+/* */
+/* This example is tap or tap for TAP_HOLD_TERM, It defines a key */
+/* KC_CCCV, which sends Control-c on tap, and Control-v on hold. */
+/* */
+/* TP_TPL(KC_CCCV, LCTL(KC_C), LCTL(KC_V)) */
+/* */
+/* This is an example of Open - Open and Close. */
+/* It defines a key, KC_OCPRN which when tapped gives an '(' and */
+/* when held gives '()' followed by a backarrow. */
+/* Which places the cursor between them.*/
+/* */
+/* OPEN_OCL(KC_OCPRN, KC_LPRN, KC_RPRN) */
+/* */
+/* To use this, add it to your src in rules.mk, and include */
+/* tap_hold.h in your code above process_record_user. */
+/* */
+/* Add a call like this to use it. */
+/* process_tap_hold_user(keycode, record); */
+/* */
+/* Note: You must add any custom keycodes to your keycodes enum */
+/* otherwise they will not exist. */
+
+
+#include USERSPACE_H
+#include "stdint.h"
+#include "tap_hold.h"
+void update_smart_lock(uint16_t keycode);
+
+
+void tap_taplong(uint16_t kc1, uint16_t kc2, keyrecord_t *record) {
+ if (record->event.pressed) {
+ tap_taplong_timer = timer_read();
+ } else {
+ if (timer_elapsed(tap_taplong_timer) > TAP_HOLD_TERM) {
+ tap_code16(kc2);
+ } else {
+ tap_code16(kc1);
+ }
+ }
+}
+
+void tap_sml(uint16_t kc1, uint16_t kc2, keyrecord_t *record) {
+ if (record->event.pressed) {
+ tap_taplong_timer = timer_read();
+ } else {
+ if (timer_elapsed(tap_taplong_timer) > TAP_HOLD_TERM) {
+ update_smart_lock(kc2);
+ } else {
+ tap_code16(kc1);
+ }
+ }
+}
+
+/* for (){}[]""''<>``. tap for open. Hold for open and close, ending inbetween. */
+/* Assumes a one character length. */
+void open_openclose(uint16_t kc1, uint16_t kc2, keyrecord_t *record) {
+ if (record->event.pressed) {
+ tap_taplong_timer = timer_read();
+ }else{
+ if (timer_elapsed(tap_taplong_timer) > TAP_HOLD_TERM) {
+ tap_code16(kc1);
+ tap_code16(kc2);
+ tap_code16(KC_LEFT);
+
+ } else {
+ // is shifted
+ uint16_t mod_state = get_mods();
+ if ((mod_state & MOD_MASK_SHIFT) ||
+ (get_oneshot_mods() & MOD_MASK_SHIFT)){
+ del_mods(MOD_MASK_SHIFT);
+ del_oneshot_mods(MOD_MASK_SHIFT);
+
+ tap_code16(kc1);
+ tap_code16(kc1);
+ tap_code16(kc1);
+
+ set_mods(mod_state);
+ }else{
+ tap_code16(kc1);
+ }
+ }
+ }
+}
+
+// open and open close for dead keys.
+void open_openclose_not_dead(uint16_t kc1, uint16_t kc2, keyrecord_t *record) {
+ if (record->event.pressed) {
+ tap_taplong_timer = timer_read();
+ }else{
+ if (timer_elapsed(tap_taplong_timer) > TAP_HOLD_TERM) {
+ tap_code16(kc1);
+ tap_code16(KC_SPACE);
+ tap_code16(kc2);
+ tap_code16(KC_SPACE);
+ tap_code16(KC_LEFT);
+ } else {
+ // is shifted - give a triple
+ uint16_t mod_state = get_mods();
+ if ((mod_state & MOD_MASK_SHIFT) ||
+ (get_oneshot_mods() & MOD_MASK_SHIFT)){
+ del_mods(MOD_MASK_SHIFT);
+ del_oneshot_mods(MOD_MASK_SHIFT);
+
+ tap_code16(kc1);
+ tap_code16(KC_SPACE);
+ tap_code16(kc1);
+ tap_code16(KC_SPACE);
+ tap_code16(kc1);
+ tap_code16(KC_SPACE);
+
+ set_mods(mod_state);
+ }else{
+ tap_code16(kc1);
+ tap_code16(KC_SPACE);
+ }
+ }
+ }
+}
+
+// macros for use in tap_hold.defs.
+#define TP_TPL(KCKEY, KC01, KC02) \
+ case KCKEY: \
+ tap_taplong(KC01, KC02, record); \
+ break;
+
+#define TP_SML(KCKEY, KC01, KC02) \
+ case KCKEY: \
+ tap_sml(KC01, KC02, record); \
+ break;
+
+#define OPEN_OCL(KCKEY, KC01, KC02) \
+ case KCKEY: \
+ open_openclose(KC01, KC02, record); \
+ break;
+
+#define OPEN_OCL_ND(KCKEY, KC01, KC02) \
+ case KCKEY: \
+ open_openclose_not_dead(KC01, KC02, record); \
+ break;
+
+void process_tap_hold_user(uint16_t keycode, keyrecord_t *record) {
+ switch(keycode){
+#include "tap_hold.def"
+ }
+}