I'm programming my new keyboard using qmk firmware. When writing a tap dance function that makes a key do different things when tapped, held, and double tapped, I need to call a method to send the keystrokes.
They examples I've found say to call register_code16(keycode);
and then unregister_code16(keycode);
. This works great for basic keycodes such as letters and numbers; even when modifier keys are included. However it doesn't work for advanced keycodes such as QK_CAPS_WORD_TOGGLE
to toggle caps word, or for keycodes for switching layers.
As a workaround, I'm handling those keycodes myself along with some custom keycodes that I've created just for my layout:
// handle key down for tap dances
void eztd_reg(uint16_t keycode){
if(!keycode) return;
switch (keycode) {
case QK_CAPS_WORD_TOGGLE:
caps_word_toggle();
break;
case KC_RIGHT_SHIFT:
case KC_LEFT_SHIFT:
register_mods(MOD_MASK_SHIFT);
break;
case MO_CTRL_KEY_AND_LAYOUT:
register_mods(MOD_MASK_CTRL);
layer_on(LAY_QWERTY_CONTROL);
break;
case MO_ALT_KEY_AND_LAYOUT:
register_mods(MOD_MASK_ALT);
layer_on(LAY_QWERTY_ALT);
break;
case MO_META_KEY_AND_LAYOUT:
register_mods(MOD_MASK_GUI);
layer_on(LAY_QWERTY_META);
break;
case MO_NUMFN_LAYOUT:
case TG_NUMFN_LAYOUT:
layer_invert(LAY_NUM_FN);
break;
case MO_BASE_LAYER:
case TG_BASE_LAYER:
layer_invert(LAY_DVORAK);
layer_invert(LAY_QWERTY);
break;
case QK_AUTO_SHIFT_TOGGLE:
autoshift_toggle();
break;
default:
register_code16(keycode);
}
}
// handle key up for tap dances
void eztd_unreg(uint16_t keycode){
if(!keycode) return;
switch (keycode) {
case QK_CAPS_WORD_TOGGLE:
break;
case KC_RIGHT_SHIFT:
case KC_LEFT_SHIFT:
unregister_mods(MOD_MASK_SHIFT);
break;
case MO_CTRL_KEY_AND_LAYOUT:
unregister_mods(MOD_MASK_CTRL);
layer_off(LAY_QWERTY_CONTROL);
break;
case MO_ALT_KEY_AND_LAYOUT:
unregister_mods(MOD_MASK_ALT);
layer_off(LAY_QWERTY_ALT);
break;
case MO_META_KEY_AND_LAYOUT:
unregister_mods(MOD_MASK_GUI);
layer_off(LAY_QWERTY_META);
break;
case MO_NUMFN_LAYOUT:
layer_invert(LAY_NUM_FN);
break;
case TG_NUMFN_LAYOUT:
break;
case MO_BASE_LAYER:
layer_invert(LAY_DVORAK);
layer_invert(LAY_QWERTY);
break;
case TG_BASE_LAYER:
break;
case QK_AUTO_SHIFT_TOGGLE:
break;
default:
unregister_code16(keycode);
}
}
I realize I will need custom code for my custom keycodes, but shouldn't there be something I can call that can handle the predefined advanced codes?
Looking through the qmk code, I see that lots of them are handled in process_record_quantum()
. However, I don't find any examples that call it from tap dance, and since it handles tap dancing itself, I suspect it would just cause tap dance to interrupt itself.
register_code16(keycode);
and unregister_code16(keycode);
support:
but do not support:
Bare modifier key support and layer functionality can be achieved by calling process_action()
instead of registering and unregistering codes. It is a little more difficult to call because its arguments are not just the keycode and whether or not it is registering or unregistering. You can create a key event to pass to it and convert the keycode to an action using action_for_keycode()
bool pressed = true; // true for key down, false for key up
keyrecord_t record = (keyrecord_t){.event = MAKE_KEYEVENT(0, 0, pressed)};
action_t action = action_for_keycode(keycode);
if (action.code != ACTION_NO) {
process_action(&record, action);
return;
}
There does not appear to be a good way to add support for all the advanced keycodes in one method call. Each module that powers advanced keycodes has a process_xxxxxxx(keycode, record)
method. There are a couple dozen of them and they can be called with the same record
that was created above. You could copy and paste this section from quantum.c
,