Yep!
Event hooks are normal functions. They will be called for every key on the keymap, and the hooks decide if they want to do something with it or not. If not, they just return the same key they got. If yes, they can either return a different key (and in that case the hooks after it will receive that key instead of the original); or they can do pretty much anything (light up LEDs, play a macro, etc), and return Key_NoKey
to signal the end of processing.
You can put the hook function anywhere in your sketch, just put it before the setup
function.
The event hook itself can decide which keys it wants to act on. As such, you do not need separate hooks for different keys, just code the hook in a way that it does something for all keys you want it to.
For example:
static Key exampleHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
// We only want to act on K, B, D, I, and O. If we see anything else, return.
if (mapped_key != Key_K && mapped_key != Key_B && mapped_key != Key_D &&
mapped_key != Key_I && mapped_key != Key_O)
return mapped_key;
// For K, B, and D, we want to change them to the next char in the alphabet.
// This is silly, but demonstrates how to return a different key.
if (mapped_key == Key_K || mapped_key = Key_B || mapped_key == Key_D) {
return (Key) { mapped_key.keyCode +1, mapped_key.flags };
}
// For I, we want to toggle the LED under it, and stop I from being input
// We want to toggle the LED on key press
if (mapped_key == Key_I) {
static bool i_LED = false;
if (keyToggledOn(key_state)) {
if (i_LED) {
LEDControl.setCrgbAt(row, col, CRGB(0, 0, 0));
} else {
LEDControl.setCrgbAt(row, col, CRGB(160, 0, 0));
}
i_LED = !i_LED;
}
return Key_NoKey;
}
// For O, we want to type "Keyboardio!", on key release.
if (Key == Key_O) {
if (keyToggledOff(key_state)) {
Macro.type(PSTR("Keyboardio!"));
}
return Key_NoKey;
}
}
And in the setup()
method of the sketch: Kaleidoscope.useEventHandlerHook(exampleHook)
.
Hope this makes it clearer.