Skip to content

Keymap: Custom Key Action

hasu@tmk edited this page Nov 17, 2021 · 6 revisions

Work in progress

Function action

You can define your custom Action using Function action.

ACTION_FUNCTION

You can define your own action.

ACTION_FUNCTION(id, opt)

  • id: ID of action(0-255)
  • opt: Optional value(0-15)

These parmeters actually can be used for any purpose in action_function() depending on you need.

ACTION_FUNCTION_TAP

You can define your own action using tapping feature.

ACTION_FUNCTION_TAP(id, opt)

Function

Custom actions are implemented in C function action_function().

action_function() is called with parameters when key is pressed and released.

Prototype: void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);

Key Record

record provides info for key event.

typedef struct {
    keyevent_t  event;
    uint8_t     tap_count;
} keyrecord_t;
  • tap_count indicates how many times key was tapped in total.
typedef struct {
    key_t    key;
    bool     pressed;
    uint16_t time;
} keyevent_t;
  • pressed is true when key is pressed.
  • time indicates when this key event occurred.(millisecond)
typedef struct {
    uint8_t col;
    uint8_t row;
} key_t;
  • col and row indicates key location in matrix.

Tap Function Example

  • Left Shift key registers left parenthesis '(' when it is tapped. See this.
  • Right Shift key toggle Layer1 when it is tapped twice.
Open
#include "action_layer.h"
#include "action_util.h"
#include "debug.h"
#include "unimap_trans.h"


/* id for user defined functions */
enum function_id {
    LSHIFT_LPAREN,
    RSHIFT_TOGGLE,
};

/*
 * user defined action function
 */
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
    if (record->event.pressed) dprint("P"); else dprint("R");
    dprintf("%d", record->tap.count);
    if (record->tap.interrupted) dprint("i");
    dprint("\n");

    switch (id) {
        case LSHIFT_LPAREN:
            // Shift parentheses example: LShft + tap '('
            // http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#shift-parentheses
            // http://geekhack.org/index.php?topic=41989.msg1304899#msg1304899
            if (record->event.pressed) {
                if (record->tap.count > 0 && !record->tap.interrupted) {
                    if (record->tap.interrupted) {
                        dprint("tap interrupted\n");
                        register_mods(MOD_BIT(KC_LSHIFT));
                    }
                } else {
                    register_mods(MOD_BIT(KC_LSHIFT));
                }
            } else {
                if (record->tap.count > 0 && !(record->tap.interrupted)) {
                    add_weak_mods(MOD_BIT(KC_LSHIFT));
                    send_keyboard_report();
                    register_code(KC_9);
                    unregister_code(KC_9);
                    del_weak_mods(MOD_BIT(KC_LSHIFT));
                    send_keyboard_report();
                    record->tap.count = 0;  // ad hoc: cancel tap
                } else {
                    unregister_mods(MOD_BIT(KC_LSHIFT));
                }
            }
            break;
        case RSHIFT_TOGGLE:
            // RShift with 2-tap toogle
            if (record->event.pressed) {
                // very short hold recognized as a tap && other key is pressed during that
                if (record->tap.count > 0 && !record->tap.interrupted) {
                    if (record->tap.interrupted) {
                        dprint("tap interrupted\n");
                        register_mods(MOD_BIT(KC_RSHIFT));
                    }
                } else {
                    register_mods(MOD_BIT(KC_RSHIFT));
                }
            } else {
                // taps && other key is not pressed during that
                if (record->tap.count >= 2 && !(record->tap.interrupted)) {
                    // toggle Layer 1
                    if (layer_state & (1<<1)) {
                        layer_off(1);
                    } else {
                        layer_on(1);
                    }
                } else {
                    unregister_mods(MOD_BIT(KC_RSHIFT));
                }
            }
            break;
    }
}


#define AC_LPRN     ACTION_FUNCTION_TAP(LSHIFT_LPAREN)
#define AC_RTGL     ACTION_FUNCTION_TAP(RSHIFT_TOGGLE)

#ifdef KEYMAP_SECTION_ENABLE
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
#endif
    UNIMAP(
              F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
    ESC,      F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,PAUS,         VOLD,VOLU,MUTE,
    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, JYEN,BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
    TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,     BSLS,     DEL, END, PGDN,    P7,  P8,  P9,  PPLS,
    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     NUHS,ENT,                         P4,  P5,  P6,  PCMM,
    LPRN,NUBS,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,     RO,  RTGL,          UP,           P1,  P2,  P3,  PENT,
    LCTL,LGUI,LALT,MHEN,          SPC,           HENK,KANA,RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PEQL
    ),

    UNIMAP(
              TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
    GRV,      TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,          TRNS,TRNS,BTLD,         TRNS,TRNS,TRNS,
    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL,      TRNS,TRNS,TRNS,    TRNS,TRNS,TRNS,TRNS,
    TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP,  INS,      TRNS,     TRNS,TRNS,TRNS,    TRNS,TRNS,TRNS,TRNS,
    TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT,     TRNS,TRNS,                        TRNS,TRNS,TRNS,TRNS,
    TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,DOWN,     TRNS,TRNS,          PGUP,         TRNS,TRNS,TRNS,TRNS,
    TRNS,TRNS,TRNS,TRNS,          TRNS,          TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,     HOME,PGDN,END,     TRNS,     TRNS,TRNS
    ),
};

Macro

Clone this wiki locally