main
  1// Numword layer implementation
  2// Based on https://github.com/treeman/qmk_firmware/blob/master/keyboards/ferris/keymaps/treeman/layermodes.c
  3// and https://www.jonashietala.se/blog/2022/09/06/the_current_t-34_keyboard_layout/#Numbers
  4
  5#include QMK_KEYBOARD_H
  6#include "layermodes.h"
  7
  8static uint16_t num_word_timer;
  9static bool _num_word_enabled = false;
 10static uint8_t _num_word_layer = 0;
 11
 12void enable_num_word(uint8_t layer) {
 13    _num_word_enabled = true;
 14    _num_word_layer = layer;
 15    layer_on(layer);
 16}
 17
 18void disable_num_word(uint8_t layer) {
 19    _num_word_enabled = false;
 20    layer_off(layer);
 21}
 22
 23bool is_num_word_enabled(void) {
 24    return _num_word_enabled;
 25}
 26
 27void process_num_word_activation(uint8_t layer, const keyrecord_t *record) {
 28    if (record->event.pressed) {
 29        layer_on(layer);
 30        num_word_timer = timer_read();
 31    } else {
 32        if (timer_elapsed(num_word_timer) < TAPPING_TERM) {
 33            // Tapped, enable numword
 34            _num_word_enabled = true;
 35            _num_word_layer = layer;
 36        } else {
 37            // Held, just turn off the layer
 38            layer_off(layer);
 39        }
 40    }
 41}
 42
 43// Returns true if numword should remain active after pressing this key
 44// Note: F-keys (F1-F15) are intentionally NOT in this list, so they will
 45// send from the NUMB layer and then automatically disable numword
 46static bool is_num_word_key(uint16_t keycode) {
 47    // Extract base keycode from layer-tap, mod-tap, etc.
 48    // This handles cases like LT(NAVI,KC_BSPC) -> KC_BSPC
 49    switch (keycode) {
 50        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
 51            keycode = keycode & 0xFF;  // Extract the base keycode
 52            break;
 53        case QK_MOD_TAP ... QK_MOD_TAP_MAX:
 54            keycode = keycode & 0xFF;  // Extract the base keycode
 55            break;
 56    }
 57
 58    switch (keycode) {
 59        // Numbers
 60        case KC_1 ... KC_0:
 61        case KC_P1 ... KC_P0:
 62        // Numpad operators
 63        case KC_PAST:  // *
 64        case KC_PSLS:  // /
 65        case KC_PMNS:  // -
 66        case KC_PPLS:  // +
 67        case KC_PDOT:  // .
 68        case KC_PCMM:  // ,
 69        case KC_PEQL:  // =
 70        // Other operators and symbols commonly used with numbers
 71        case KC_PLUS:
 72        case KC_MINS:
 73        case KC_EQL:
 74        case KC_PERC:
 75        case KC_DOT:
 76        case KC_COMM:
 77        case KC_COLN:
 78        case KC_UNDS:
 79        // Special keys
 80        case KC_BSPC:
 81        case KC_DEL:
 82        case KC_ENT:
 83        case KC_SPC:
 84        case QK_REP:   // Repeat key
 85        case QK_AREP:  // Alternate repeat key
 86        // x for hexadecimal
 87        case KC_X:
 88        // Modifiers (so they don't disable numword)
 89        case KC_LSFT ... KC_RGUI:
 90        case OS_LSFT ... OS_RGUI:
 91            return true;
 92        default:
 93            return false;
 94    }
 95}
 96
 97bool process_num_word(uint16_t keycode, const keyrecord_t *record) {
 98    if (!_num_word_enabled) {
 99        return true;
100    }
101
102    // Only check on key press to determine if we should disable
103    if (record->event.pressed) {
104        // Check if this key should keep numword active
105        // If not, we'll disable on the RELEASE so the key sends from the layer first
106        if (!is_num_word_key(keycode)) {
107            // Mark for disable, but don't disable yet - let the key send first
108        }
109    } else {
110        // On key release, check if we should disable numword
111        if (!is_num_word_key(keycode)) {
112            disable_num_word(_num_word_layer);
113        }
114    }
115
116    return true;
117}