From 5117dff6a26aec4eca04fb9787b4f428884739bc Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sun, 22 Mar 2020 06:29:05 -0700 Subject: [PATCH] Add Post Processing to process_record (#4892) * Improve process_record system Code based on @colinta's * Rename and better handle functions * Fix incorrect function call to process_record_user * Add documentation for post_process_record * Add both get_event_keycode and get_record_keycode functions And add some comments about these functions * Update code format * Cleanup merge artifacts --- docs/feature_macros.md | 40 +++++++++++++++++++++++++++++++++++++++ docs/understanding_qmk.md | 9 +++++++++ quantum/quantum.c | 20 +++++++++++++++++--- quantum/quantum.h | 2 ++ tmk_core/common/action.c | 8 +++++++- tmk_core/common/action.h | 2 ++ 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/docs/feature_macros.md b/docs/feature_macros.md index 99dd564bf..1bd2d74e7 100644 --- a/docs/feature_macros.md +++ b/docs/feature_macros.md @@ -88,6 +88,46 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; ``` +### Advanced Macros + +In addition to the `process_record_user()` function, is the `post_process_record_user()` function. This runs after `process_record` and can be used to do things after a keystroke has been sent. This is useful if you want to have a key pressed before and released after a normal key, for instance. + +In this example, we modify most normal keypresses so that `F22` is pressed before the keystroke is normally sent, and release it __only after__ it's been released. + +```c +static uint8_t f22_tracker; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case KC_A ... KC_F21: //notice how it skips over F22 + case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys + if (record->event.pressed) { + register_code(KC_F22); //this means to send F22 down + f22_tracker++; + register_code(keycode); + return false; + } + break; + } + return true; +} + +void post_process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case KC_A ... KC_F21: //notice how it skips over F22 + case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys + if (!record->event.pressed) { + f22_tracker--; + if (!f22_tracker) { + unregister_code(KC_F22); //this means to send F22 up + } + } + break; + } +} +``` + + ### TAP, DOWN and UP You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`. diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md index 81cedfcf5..939642425 100644 --- a/docs/understanding_qmk.md +++ b/docs/understanding_qmk.md @@ -162,6 +162,15 @@ The `process_record()` function itself is deceptively simple, but hidden within At any step during this chain of events a function (such as `process_record_kb()`) can `return false` to halt all further processing. +After this is called, `post_process_record()` is called, which can be used to handle additional cleanup that needs to be run after the keycode is normally handled. + +* [`void post_process_record(keyrecord_t *record)`]() + * [`void post_process_record_quantum(keyrecord_t *record)`]() + * [Map this record to a keycode]() + * [`void post_process_clicky(uint16_t keycode, keyrecord_t *record)`]() + * [`void post_process_record_kb(uint16_t keycode, keyrecord_t *record)`]() + * [`void post_process_record_user(uint16_t keycode, keyrecord_t *record)`]() +