diff options
author | Drashna Jaelre <drashna@live.com> | 2020-03-22 06:29:05 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-23 00:29:05 +1100 |
commit | 5117dff6a26aec4eca04fb9787b4f428884739bc (patch) | |
tree | ecc94acb888c3ed330c11008fa6324b1d73b12cc | |
parent | e5d34fd084a7bdde0867749470b27c50e8144eb8 (diff) |
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
-rw-r--r-- | docs/feature_macros.md | 40 | ||||
-rw-r--r-- | docs/understanding_qmk.md | 9 | ||||
-rw-r--r-- | quantum/quantum.c | 20 | ||||
-rw-r--r-- | quantum/quantum.h | 2 | ||||
-rw-r--r-- | tmk_core/common/action.c | 8 | ||||
-rw-r--r-- | 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 99dd564bf8..1bd2d74e7d 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 81cedfcf53..9396424258 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)`]() + <!-- #### Mouse Handling diff --git a/quantum/quantum.c b/quantum/quantum.c index 49767819df..d7dbc49dc1 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -120,6 +120,14 @@ __attribute__((weak)) bool process_record_kb(uint16_t keycode, keyrecord_t *reco __attribute__((weak)) bool process_record_user(uint16_t keycode, keyrecord_t *record) { return true; } +__attribute__ ((weak)) +void post_process_record_kb(uint16_t keycode, keyrecord_t *record) { + post_process_record_user(keycode, record); +} + +__attribute__ ((weak)) +void post_process_record_user(uint16_t keycode, keyrecord_t *record) {} + void reset_keyboard(void) { clear_keyboard(); #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) @@ -172,9 +180,15 @@ uint16_t get_event_keycode(keyevent_t event) { return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key); } -/* Main keycode processing function. Hands off handling to other functions, - * then processes internal Quantum keycodes, then processes ACTIONs. - */ +/* Get keycode, and then call keyboard function */ +void post_process_record_quantum(keyrecord_t *record) { + uint16_t keycode = get_record_keycode(record); + post_process_record_kb(keycode, record); +} + +/* Core keycode function, hands off handling to other functions, + then processes internal quantum keycodes, and then processes + ACTIONs. */ bool process_record_quantum(keyrecord_t *record) { uint16_t keycode = get_record_keycode(record); diff --git a/quantum/quantum.h b/quantum/quantum.h index 191407fabb..4b94ebcc05 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -257,6 +257,8 @@ uint16_t get_event_keycode(keyevent_t event); bool process_action_kb(keyrecord_t *record); bool process_record_kb(uint16_t keycode, keyrecord_t *record); bool process_record_user(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); #ifndef BOOTMAGIC_LITE_COLUMN # define BOOTMAGIC_LITE_COLUMN 0 diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index 174faf856a..19c3569d55 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -151,6 +151,8 @@ void process_record_nocache(keyrecord_t *record) { process_record(record); } __attribute__((weak)) bool process_record_quantum(keyrecord_t *record) { return true; } +__attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {} + #ifndef NO_ACTION_TAPPING /** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. * @@ -185,6 +187,11 @@ void process_record(keyrecord_t *record) { if (!process_record_quantum(record)) return; + process_record_handler(record); + post_process_record_quantum(record); +} + +void process_record_handler(keyrecord_t *record) { action_t action = store_or_get_action(record->event.pressed, record->event.key); dprint("ACTION: "); debug_action(action); @@ -988,7 +995,6 @@ bool is_tap_action(action_t action) { * FIXME: Needs documentation. */ void debug_event(keyevent_t event) { dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); } - /** \brief Debug print (FIXME: Needs better description) * * FIXME: Needs documentation. diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 15f4ce15c0..dd22023f9b 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -84,6 +84,8 @@ void process_hand_swap(keyevent_t *record); void process_record_nocache(keyrecord_t *record); void process_record(keyrecord_t *record); +void process_record_handler(keyrecord_t *record); +void post_process_record_quantum(keyrecord_t *record); void process_action(keyrecord_t *record, action_t action); void register_code(uint8_t code); void unregister_code(uint8_t code); |