mirror of
https://github.com/qmk/qmk_userspace.git
synced 2025-06-19 03:57:57 -04:00
put features to separate files
This commit is contained in:
parent
568e2f86ad
commit
1c39a28ca0
8 changed files with 440 additions and 94 deletions
|
@ -15,4 +15,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||
[_NUM] = LAYOUT_wrapper(NUM_LAYER),
|
||||
|
||||
[_WOW] = LAYOUT_wrapper(WOW_LAYER),
|
||||
|
||||
[_MOD] = LAYOUT_wrapper(MOD_LAYER),
|
||||
};
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
#include "ncsibra.h"
|
||||
|
||||
// Tap hold keys
|
||||
static taphold_t th_events[] = {
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_ESC, .kc_hold = KC_F11 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_1, .kc_hold = KC_F1 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_2, .kc_hold = KC_F2 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_3, .kc_hold = KC_F3 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_4, .kc_hold = KC_F4 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_5, .kc_hold = KC_F5 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_6, .kc_hold = KC_F6 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_7, .kc_hold = KC_F7 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_8, .kc_hold = KC_F8 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_9, .kc_hold = KC_F9 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_0, .kc_hold = KC_F10 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_BSPC, .kc_hold = KC_F12 },
|
||||
};
|
||||
#include "osl.h"
|
||||
#include "tap_hold.h"
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
// if keycode is ESC or at least contains ESC(in case of Mod Tap etc) and one shot modifier or one shot layer is active, then cancel
|
||||
|
@ -25,62 +11,10 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|||
return false;
|
||||
}
|
||||
|
||||
return process_record_user_taphold(keycode, record);
|
||||
return process_record_user_taphold(keycode, record) &&
|
||||
process_record_user_osl(keycode, record);
|
||||
};
|
||||
|
||||
static uint16_t prev_th_key = KC_NO;
|
||||
static uint16_t prev_th_time = 0;
|
||||
|
||||
bool process_record_user_taphold(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
matrix_scan_tap_hold(TAPPED);
|
||||
}
|
||||
|
||||
if (keycode < TH_FIRST || keycode > TH_LAST) { return true; }
|
||||
|
||||
taphold_t *th_event = &th_events[keycode - TH_FIRST];
|
||||
|
||||
// if pressed twice fast, hold KC_TAP instead of usual logic, Mod Tap functionality works similarly
|
||||
if (record->event.pressed) {
|
||||
if (keycode == prev_th_key && timer_elapsed(prev_th_time) < TH_DELAY) {
|
||||
register_code16(th_event->kc_tap);
|
||||
th_event->is_double = true;
|
||||
return false;
|
||||
} else {
|
||||
prev_th_key = keycode;
|
||||
prev_th_time = timer_read();
|
||||
}
|
||||
}
|
||||
|
||||
if (record->event.pressed) {
|
||||
th_event->timer = timer_read();
|
||||
th_event->is_pressed = true;
|
||||
} else if (th_event->is_pressed) {
|
||||
register_code16(th_event->kc_tap);
|
||||
unregister_code16(th_event->kc_tap);
|
||||
th_event->is_pressed = false;
|
||||
} else if (th_event->is_double) {
|
||||
unregister_code16(th_event->kc_tap);
|
||||
th_event->is_double = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void matrix_scan_tap_hold(taphold_state state) {
|
||||
for (uint8_t index = 0 ; index < TH_EVENTS_COUNT ; ++index ) {
|
||||
taphold_t *th_event = &th_events[index];
|
||||
if (!th_event->is_pressed) { continue; }
|
||||
if (state == TAPPED || timer_elapsed(th_event->timer) > TH_DELAY) {
|
||||
uint16_t code = state == HELD ? th_event->kc_hold : th_event->kc_tap;
|
||||
register_code16(code);
|
||||
unregister_code16(code);
|
||||
th_event->is_pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void matrix_scan_user(void) {
|
||||
matrix_scan_tap_hold(HELD);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ enum layers {
|
|||
_LOWER,
|
||||
_RAISE,
|
||||
_NUM,
|
||||
_WOW
|
||||
_WOW,
|
||||
_MOD,
|
||||
};
|
||||
|
||||
enum keycodes {
|
||||
|
@ -41,6 +42,15 @@ enum keycodes {
|
|||
TH_0,
|
||||
TH_BSPC,
|
||||
|
||||
// Custom oneshot layer implementation.
|
||||
OSL_MOD_LAYER,
|
||||
|
||||
// Custom oneshot mods implementation.
|
||||
OSM_SHFT,
|
||||
OSM_CTRL,
|
||||
OSM_ALT,
|
||||
OSM_GUI,
|
||||
|
||||
NEW_SAFE_RANGE
|
||||
};
|
||||
|
||||
|
@ -81,7 +91,7 @@ enum keycodes {
|
|||
#define RAISE_LAYER \
|
||||
QK_BOOT, XXXXXXX, XXXXXXX, XXXXXXX, DF(_QWERTY), XXXXXXX, XXXXXXX, DF(_COLEMAK), XXXXXXX, XXXXXXX, XXXXXXX, TO(_WOW), \
|
||||
DB_TOGG, XXXXXXX, XXXXXXX, KC_LSFT, XXXXXXX, XXXXXXX, XXXXXXX, KC_HOME, KC_UP, KC_END, XXXXXXX, KC_DEL, \
|
||||
_______, KC_LGUI, KC_LALT, XXXXXXX, KC_LCTL, XXXXXXX, XXXXXXX, KC_LEFT, KC_DOWN, KC_RIGHT, XXXXXXX, _______, \
|
||||
_______, KC_LGUI, KC_LALT, KC_LSFT, KC_LCTL, XXXXXXX, XXXXXXX, KC_LEFT, KC_DOWN, KC_RIGHT, XXXXXXX, _______, \
|
||||
KC_CAPS, _______, _______, _______, _______, _______, XXXXXXX, KC_PGUP, XXXXXXX, KC_PGDN, XXXXXXX, _______, \
|
||||
_______, _______, _______, _______, _______, LCTL(KC_SPC), _______, _______, _______, TG(_RAISE), _______, _______
|
||||
|
||||
|
@ -101,25 +111,10 @@ enum keycodes {
|
|||
KC_LSFT, KC_Z, KC_X, KC_N, KC_C, KC_V, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \
|
||||
KC_M, KC_Y, KC_LALT, KC_LCTL, KC_SPC, KC_P, KC_BSPC, KC_DEL, KC_DEL, KC_LGUI, KC_PSCR, TO(_COLEMAK)
|
||||
|
||||
// tap-hold settings
|
||||
#define TH_DELAY 300
|
||||
|
||||
#define TH_EVENTS_COUNT 12
|
||||
#define TH_FIRST TH_ESC
|
||||
#define TH_LAST TH_BSPC
|
||||
|
||||
typedef struct {
|
||||
bool is_pressed;
|
||||
bool is_double;
|
||||
uint16_t timer;
|
||||
uint16_t kc_tap;
|
||||
uint16_t kc_hold;
|
||||
} taphold_t;
|
||||
|
||||
typedef enum {
|
||||
TAPPED,
|
||||
HELD,
|
||||
} taphold_state;
|
||||
|
||||
void matrix_scan_tap_hold(taphold_state state);
|
||||
bool process_record_user_taphold(uint16_t keycode, keyrecord_t *record);
|
||||
#define MOD_LAYER \
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
_______, _______, _______, OSM_SHFT, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
_______, OSM_GUI, OSM_ALT, OSM_SHFT, OSM_CTRL, _______, _______, _______, _______, _______, _______, _______, \
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, OSL_MOD_LAYER
|
||||
|
|
318
users/ncsibra/osl.c
Normal file
318
users/ncsibra/osl.c
Normal file
|
@ -0,0 +1,318 @@
|
|||
#include QMK_KEYBOARD_H
|
||||
#include "ncsibra.h"
|
||||
|
||||
// copied from https://github.com/Exidex/qmk_firmware/blob/custom/keyboards/beekeeb/piantor_pro/readme.md
|
||||
|
||||
// ================ mostly callum's oneshot mods
|
||||
|
||||
typedef enum {
|
||||
osl_up_unqueued, // default, waiting for layer to be pressed
|
||||
osl_up_queued, // layer pressed and released without pressing mod key, next modifier press will have layer enabled, on all mod release layer will be disabled
|
||||
osl_up_pending_used, // layer was pressed but released when some mods were still held, on all mod release layer will be disabled
|
||||
osl_down_unused, // layer pressed and held, all mod presses will have layer enabled, until all mods are released
|
||||
osl_down_pending_used, // layer pressed and held, some mods are still pressed
|
||||
osl_down_used, // mods were pressed but layer is still held, on layer release layer will be disabled
|
||||
} oneshot_layer_state;
|
||||
|
||||
typedef enum {
|
||||
osm_up_unqueued, // default, waiting for mod to be pressed
|
||||
osm_down_unused, // mod pressed and held, all other presses will be with this modifier enabled, until mod released
|
||||
osm_down_used, // other key pressed while mod is held, on mod release modifier will be disabled
|
||||
osm_up_queued, // mod pressed and released without pressing other key, next press will have modifier enabled
|
||||
osm_up_queued_with_layer, // other key pressed abd released while layer and mod are active, next presses will have modifier enabled until layer is released
|
||||
} oneshot_mod_state;
|
||||
|
||||
oneshot_mod_state osm_shift_state = osm_up_unqueued;
|
||||
oneshot_mod_state osm_ctrl_state = osm_up_unqueued;
|
||||
oneshot_mod_state osm_alt_state = osm_up_unqueued;
|
||||
oneshot_mod_state osm_gui_state = osm_up_unqueued;
|
||||
|
||||
bool is_oneshot_cancel_key(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case MO(_LOWER):
|
||||
case TT(_RAISE):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_oneshot_ignored_key(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case OSL_MOD_LAYER:
|
||||
case OSM_SHFT:
|
||||
case OSM_CTRL:
|
||||
case OSM_ALT:
|
||||
case OSM_GUI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void update_oneshot_mod(
|
||||
oneshot_layer_state *layer_state,
|
||||
oneshot_mod_state *mod_state,
|
||||
uint16_t mod,
|
||||
uint16_t trigger,
|
||||
uint16_t keycode,
|
||||
keyrecord_t *record
|
||||
) {
|
||||
if (keycode == trigger) {
|
||||
if (record->event.pressed) {
|
||||
// Trigger keydown
|
||||
if (*mod_state == osm_up_unqueued) {
|
||||
register_code(mod);
|
||||
}
|
||||
*mod_state = osm_down_unused;
|
||||
} else {
|
||||
// Trigger keyup
|
||||
switch (*mod_state) {
|
||||
case osm_down_unused:
|
||||
// If we didn't use the mod while trigger was held, queue it.
|
||||
*mod_state = osm_up_queued;
|
||||
break;
|
||||
case osm_down_used:
|
||||
// If we did use the mod while trigger was held, unregister it.
|
||||
*mod_state = osm_up_unqueued;
|
||||
unregister_code(mod);
|
||||
// uprintf("0x%04X unregister_code up trigger\n", keycode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (record->event.pressed) {
|
||||
if (is_oneshot_cancel_key(keycode) && *mod_state != osm_up_unqueued) {
|
||||
// Cancel oneshot on designated cancel keydown.
|
||||
*mod_state = osm_up_unqueued;
|
||||
unregister_code(mod);
|
||||
// uprintf("0x%04X unregister_code down non-trigger\n", keycode);
|
||||
}
|
||||
} else {
|
||||
if (!is_oneshot_ignored_key(keycode)) {
|
||||
// On non-ignored keyup, mark the oneshot as used.
|
||||
switch (*mod_state) {
|
||||
case osm_down_unused:
|
||||
*mod_state = osm_down_used;
|
||||
break;
|
||||
case osm_up_queued:
|
||||
switch (*layer_state) {
|
||||
case osl_up_pending_used: // because some other mod is still pressed
|
||||
case osl_down_unused:
|
||||
case osl_down_pending_used:
|
||||
case osl_down_used:
|
||||
*mod_state = osm_up_queued_with_layer;
|
||||
break;
|
||||
default:
|
||||
*mod_state = osm_up_unqueued;
|
||||
unregister_code(mod);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ================ my oneshot layers
|
||||
|
||||
oneshot_layer_state osl_mod_state = osl_up_unqueued;
|
||||
|
||||
uint16_t pressed_one_shot_mods = 0;
|
||||
|
||||
#define CUSTOM_ONE_SHOT_MOD_GET_MODS(kc) ((kc)&0x1F)
|
||||
|
||||
bool is_oneshot_mod_key(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case OSM_SHFT:
|
||||
case OSM_CTRL:
|
||||
case OSM_ALT:
|
||||
case OSM_GUI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void update_oneshot_layer(
|
||||
oneshot_layer_state *layer_state,
|
||||
oneshot_mod_state *shift_state,
|
||||
oneshot_mod_state *ctrl_state,
|
||||
oneshot_mod_state *alt_state,
|
||||
oneshot_mod_state *gui_state,
|
||||
uint16_t trigger,
|
||||
uint16_t layer,
|
||||
uint16_t keycode,
|
||||
keyrecord_t *record
|
||||
) {
|
||||
if (keycode == trigger) {
|
||||
if (record->event.pressed) {
|
||||
if (*layer_state == osl_up_unqueued) {
|
||||
layer_on(layer);
|
||||
}
|
||||
*layer_state = osl_down_unused;
|
||||
} else {
|
||||
switch (*layer_state) {
|
||||
case osl_down_unused:
|
||||
*layer_state = osl_up_queued;
|
||||
break;
|
||||
case osl_down_used:
|
||||
*layer_state = osl_up_unqueued;
|
||||
layer_off(layer);
|
||||
|
||||
{
|
||||
if (*shift_state == osm_up_queued_with_layer) {
|
||||
*shift_state = osm_up_unqueued;
|
||||
unregister_code(KC_LSFT);
|
||||
}
|
||||
if (*ctrl_state == osm_up_queued_with_layer) {
|
||||
*ctrl_state = osm_up_unqueued;
|
||||
unregister_code(KC_LCTL);
|
||||
}
|
||||
if (*alt_state == osm_up_queued_with_layer) {
|
||||
*alt_state = osm_up_unqueued;
|
||||
unregister_code(KC_LALT);
|
||||
}
|
||||
if (*gui_state == osm_up_queued_with_layer) {
|
||||
*gui_state = osm_up_unqueued;
|
||||
unregister_code(KC_LGUI);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case osl_down_pending_used:
|
||||
*layer_state = osl_up_pending_used;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (record->event.pressed) {
|
||||
if (is_oneshot_mod_key(keycode)) {
|
||||
pressed_one_shot_mods |= CUSTOM_ONE_SHOT_MOD_GET_MODS(keycode);
|
||||
}
|
||||
} else {
|
||||
if (is_oneshot_mod_key(keycode)) {
|
||||
pressed_one_shot_mods &= CUSTOM_ONE_SHOT_MOD_GET_MODS(~(CUSTOM_ONE_SHOT_MOD_GET_MODS(keycode)));
|
||||
}
|
||||
|
||||
switch (*layer_state) {
|
||||
case osl_down_pending_used:
|
||||
case osl_down_unused:
|
||||
if (is_oneshot_mod_key(keycode)) {
|
||||
if (pressed_one_shot_mods) {
|
||||
*layer_state = osl_down_pending_used;
|
||||
} else {
|
||||
*layer_state = osl_down_used;
|
||||
layer_off(layer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case osl_up_queued:
|
||||
case osl_up_pending_used:
|
||||
if (is_oneshot_mod_key(keycode)) {
|
||||
if (pressed_one_shot_mods) {
|
||||
*layer_state = osl_up_pending_used;
|
||||
} else {
|
||||
*layer_state = osl_up_unqueued;
|
||||
layer_off(layer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==============
|
||||
|
||||
//const char* oneshot_layer_state_string(oneshot_layer_state value) {
|
||||
// switch (value) {
|
||||
// case osl_up_unqueued: return "osl_up_unqueued";
|
||||
// case osl_up_queued: return "osl_up_queued";
|
||||
// case osl_up_pending_used: return "osl_up_pending_used";
|
||||
// case osl_down_unused: return "osl_down_unused";
|
||||
// case osl_down_pending_used: return "osl_down_pending_used";
|
||||
// case osl_down_used: return "osl_down_used";
|
||||
// default: return "-----";
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//const char* oneshot_mod_state_string(oneshot_mod_state value) {
|
||||
// switch (value) {
|
||||
// case osm_up_unqueued: return "osm_up_unqueued";
|
||||
// case osm_down_unused: return "osm_down_unused";
|
||||
// case osm_down_used: return "osm_down_used";
|
||||
// case osm_up_queued: return "osm_up_queued";
|
||||
// case osm_up_queued_with_layer: return "osm_up_queued_with_layer";
|
||||
// default: return "-----";
|
||||
// }
|
||||
//}
|
||||
|
||||
bool process_record_user_osl(uint16_t keycode, keyrecord_t *record) {
|
||||
// uprintf("\n");
|
||||
// uprintf("\n");
|
||||
//
|
||||
// uprintf("%s %s %s %s %s \n", oneshot_layer_state_string(osl_mod_state), oneshot_mod_state_string(osm_shift_state), oneshot_mod_state_string(osm_ctrl_state), oneshot_mod_state_string(osm_alt_state), oneshot_mod_state_string(osm_gui_state));
|
||||
|
||||
update_oneshot_mod(
|
||||
&osl_mod_state,
|
||||
&osm_shift_state,
|
||||
KC_LSFT,
|
||||
OSM_SHFT,
|
||||
keycode,
|
||||
record
|
||||
);
|
||||
|
||||
update_oneshot_mod(
|
||||
&osl_mod_state,
|
||||
&osm_ctrl_state,
|
||||
KC_LCTL,
|
||||
OSM_CTRL,
|
||||
keycode,
|
||||
record
|
||||
);
|
||||
|
||||
update_oneshot_mod(
|
||||
&osl_mod_state,
|
||||
&osm_alt_state,
|
||||
KC_LALT,
|
||||
OSM_ALT,
|
||||
keycode,
|
||||
record
|
||||
);
|
||||
|
||||
update_oneshot_mod(
|
||||
&osl_mod_state,
|
||||
&osm_gui_state,
|
||||
KC_LGUI,
|
||||
OSM_GUI,
|
||||
keycode,
|
||||
record
|
||||
);
|
||||
|
||||
|
||||
update_oneshot_layer(
|
||||
&osl_mod_state,
|
||||
&osm_shift_state,
|
||||
&osm_ctrl_state,
|
||||
&osm_alt_state,
|
||||
&osm_gui_state,
|
||||
OSL_MOD_LAYER,
|
||||
_MOD,
|
||||
keycode,
|
||||
record
|
||||
);
|
||||
|
||||
// uprintf("%s %s %s %s %s \n", oneshot_layer_state_string(osl_mod_state), oneshot_mod_state_string(osm_shift_state), oneshot_mod_state_string(osm_ctrl_state), oneshot_mod_state_string(osm_alt_state), oneshot_mod_state_string(osm_gui_state));
|
||||
|
||||
return true;
|
||||
}
|
3
users/ncsibra/osl.h
Normal file
3
users/ncsibra/osl.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
bool process_record_user_osl(uint16_t keycode, keyrecord_t *record);
|
|
@ -1,4 +1,6 @@
|
|||
SRC += ncsibra.c
|
||||
SRC += ncsibra.c \
|
||||
osl.c \
|
||||
tap_hold.c
|
||||
|
||||
CONSOLE_ENABLE = yes
|
||||
NKRO_ENABLE = yes
|
||||
|
|
83
users/ncsibra/tap_hold.c
Normal file
83
users/ncsibra/tap_hold.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include QMK_KEYBOARD_H
|
||||
#include "ncsibra.h"
|
||||
#include "tap_hold.h"
|
||||
|
||||
#define TH_DELAY 300
|
||||
#define TH_EVENTS_COUNT 12
|
||||
#define TH_FIRST TH_ESC
|
||||
#define TH_LAST TH_BSPC
|
||||
|
||||
typedef struct {
|
||||
bool is_pressed;
|
||||
bool is_double;
|
||||
uint16_t timer;
|
||||
uint16_t kc_tap;
|
||||
uint16_t kc_hold;
|
||||
} taphold_t;
|
||||
|
||||
static uint16_t prev_th_key = KC_NO;
|
||||
static uint16_t prev_th_time = 0;
|
||||
|
||||
static taphold_t th_events[] = {
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_ESC, .kc_hold = KC_F11 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_1, .kc_hold = KC_F1 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_2, .kc_hold = KC_F2 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_3, .kc_hold = KC_F3 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_4, .kc_hold = KC_F4 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_5, .kc_hold = KC_F5 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_6, .kc_hold = KC_F6 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_7, .kc_hold = KC_F7 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_8, .kc_hold = KC_F8 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_9, .kc_hold = KC_F9 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_0, .kc_hold = KC_F10 },
|
||||
{ .is_pressed = false, .is_double = false, .timer = 0, .kc_tap = KC_BSPC, .kc_hold = KC_F12 },
|
||||
};
|
||||
|
||||
bool process_record_user_taphold(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
matrix_scan_tap_hold(TAPPED);
|
||||
}
|
||||
|
||||
if (keycode < TH_FIRST || keycode > TH_LAST) { return true; }
|
||||
|
||||
taphold_t *th_event = &th_events[keycode - TH_FIRST];
|
||||
|
||||
// if pressed twice fast, hold KC_TAP instead of usual logic, Mod Tap functionality works similarly
|
||||
if (record->event.pressed) {
|
||||
if (keycode == prev_th_key && timer_elapsed(prev_th_time) < TH_DELAY) {
|
||||
register_code16(th_event->kc_tap);
|
||||
th_event->is_double = true;
|
||||
return false;
|
||||
} else {
|
||||
prev_th_key = keycode;
|
||||
prev_th_time = timer_read();
|
||||
}
|
||||
}
|
||||
|
||||
if (record->event.pressed) {
|
||||
th_event->timer = timer_read();
|
||||
th_event->is_pressed = true;
|
||||
} else if (th_event->is_pressed) {
|
||||
register_code16(th_event->kc_tap);
|
||||
unregister_code16(th_event->kc_tap);
|
||||
th_event->is_pressed = false;
|
||||
} else if (th_event->is_double) {
|
||||
unregister_code16(th_event->kc_tap);
|
||||
th_event->is_double = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void matrix_scan_tap_hold(taphold_state state) {
|
||||
for (uint8_t index = 0 ; index < TH_EVENTS_COUNT ; ++index ) {
|
||||
taphold_t *th_event = &th_events[index];
|
||||
if (!th_event->is_pressed) { continue; }
|
||||
if (state == TAPPED || timer_elapsed(th_event->timer) > TH_DELAY) {
|
||||
uint16_t code = state == HELD ? th_event->kc_hold : th_event->kc_tap;
|
||||
register_code16(code);
|
||||
unregister_code16(code);
|
||||
th_event->is_pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
9
users/ncsibra/tap_hold.h
Normal file
9
users/ncsibra/tap_hold.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
TAPPED,
|
||||
HELD,
|
||||
} taphold_state;
|
||||
|
||||
void matrix_scan_tap_hold(taphold_state state);
|
||||
bool process_record_user_taphold(uint16_t keycode, keyrecord_t *record);
|
Loading…
Add table
Add a link
Reference in a new issue