Contents

Custom QMK Layers

Contents

I’ve been using the Ergodox EZ for a while, but I’ve never liked the different layer options. I always found they did half of what I wanted. The closest layer behavior is the One shot keys, in particular the OSL(N) one shot layer functionality. Unfortunately it still relies a lot on timeouts and does not have immediate application or cancelation in many scenarios. Below is how I wish the one shot layer functionality worked:

  • Tap to toggle oneshot, tap again to cancel
  • Tap + press another key for one-shot behavior
  • Hold for momentary access, upon release reset layer
  • Long hold without pressing others keys cancels on release
  • Triple-tap for locked mode, tap again to unlock
#include "../custom_keys.h"
#include <assert.h>

// State tracking for each layer
typedef struct {
    bool key_held;
    bool oneshot;
    bool locked;
    bool other_key_pressed;
    int layer_num;
    uint16_t keycode;
    uint16_t hold_timer;
    uint8_t tap_count;
    uint16_t last_tap_time;
} custom_oneshot_layer_state_t;

static custom_oneshot_layer_state_t layer_states[4] = {
    {.keycode = CUSTOM_OSL1, .layer_num = 1},
    {.keycode = CUSTOM_OSL2, .layer_num = 2},
    {.keycode = CUSTOM_OSL3, .layer_num = 3},
    {.keycode = CUSTOM_OSL4, .layer_num = 4},
};

#define LAYER_HOLD_TIMEOUT 500 // ms
#define TAP_TIMEOUT 300 // ms

static const int NUM_ENTRIES = sizeof(layer_states) / sizeof(layer_states[0]);
_Static_assert((sizeof(layer_states) / sizeof(layer_states[0])) == 4, "mismatch of entries");

int get_keycode_index(uint16_t keycode) {
    for (int i = 0; i < NUM_ENTRIES; ++i) {
        if (layer_states[i].keycode == keycode) {
            return i;
        }
    }

    return -1;
}

bool process_custom_oneshot_layers(uint16_t keycode, keyrecord_t *record) {
    const int layer_idx = get_keycode_index(keycode);

    if (layer_idx >= 0) {
       custom_oneshot_layer_state_t *state = &layer_states[layer_idx];

        if (record->event.pressed) {
            // Key down
            state->key_held = true;
            state->other_key_pressed = false;
            state->hold_timer = timer_read();
            layer_on(state->layer_num);
        } else {
            // Key up
            if (!state->other_key_pressed) {
                // No other keys pressed while holding
                uint16_t hold_duration = timer_elapsed(state->hold_timer);
                if (hold_duration > LAYER_HOLD_TIMEOUT) {
                    // Held too long - cancel
                    layer_off(state->layer_num);
                    state->tap_count = 0;
                } else {
                    // This was a quick tap
                    if (state->locked) {
                        // In locked mode - unlock and exit
                        state->locked = false;
                        state->oneshot = false;
                        layer_off(state->layer_num);
                        state->tap_count = 0;
                    } else {
                        // Not locked - handle tap counting (whether oneshot or not)
                        if (timer_elapsed(state->last_tap_time) > TAP_TIMEOUT) {
                            state->tap_count = 1;
                        } else {
                            state->tap_count++;
                        }
                        state->last_tap_time = timer_read();

                        // Handle based on tap count
                        if (state->tap_count == 1) {
                            if (state->oneshot) {
                                state->oneshot = false;
                                layer_off(state->layer_num);
                            } else {
                                // First tap - enter oneshot
                                state->oneshot = true;
                            }
                        } else if (state->tap_count == 2) {
                            // Second tap - exit oneshot
                            state->oneshot = false;
                            layer_off(state->layer_num);
                        } else if (state->tap_count >= 3) {
                            // Third tap - enter locked mode
                            state->oneshot = false;
                            state->locked = true;
                            layer_on(state->layer_num);
                            state->tap_count = 0;
                        }
                    }
                }
            } else {
                // This was a hold - turn off layer unless in oneshot mode
                if (!state->locked && !state->oneshot) {
                    layer_off(state->layer_num);
                }
                state->tap_count = 0;
            }
            state->key_held = false;
        }
        return false;
    }

    // Handle all other keys
    if (record->event.pressed) {
        // Key down - just mark that another key was pressed if layer key is held
        for (int i = 0; i < NUM_ENTRIES; i++) {
            custom_oneshot_layer_state_t *state = &layer_states[i];
            if (state->key_held) {
                state->other_key_pressed = true;
            }
        }

        // Reset tap counts when other keys are pressed
        for (int i = 0; i < NUM_ENTRIES; i++) {
            custom_oneshot_layer_state_t *state = &layer_states[i];
            if (!state->locked && !state->key_held) {
                state->tap_count = 0;
            }
        }
    } else {
        // Key up - now turn off the layer if in oneshot mode
        for (int i = 0; i < NUM_ENTRIES; i++) {
            custom_oneshot_layer_state_t *state = &layer_states[i];
            if (state->oneshot && !state->key_held) {
                state->oneshot = false;
                layer_off(state->layer_num);
            }
        }
    }

    return true;
}