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
This commit is contained in:
Drashna Jaelre 2020-03-22 06:29:05 -07:00 committed by GitHub
parent e5d34fd084
commit 5117dff6a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 4 deletions

View file

@ -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 ### TAP, DOWN and UP
You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`. You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`.

View file

@ -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. 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 #### Mouse Handling

View file

@ -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)) 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) { void reset_keyboard(void) {
clear_keyboard(); clear_keyboard();
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC) #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); return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key);
} }
/* Main keycode processing function. Hands off handling to other functions, /* Get keycode, and then call keyboard function */
* then processes internal Quantum keycodes, then processes ACTIONs. 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) { bool process_record_quantum(keyrecord_t *record) {
uint16_t keycode = get_record_keycode(record); uint16_t keycode = get_record_keycode(record);

View file

@ -257,6 +257,8 @@ uint16_t get_event_keycode(keyevent_t event);
bool process_action_kb(keyrecord_t *record); bool process_action_kb(keyrecord_t *record);
bool process_record_kb(uint16_t keycode, keyrecord_t *record); bool process_record_kb(uint16_t keycode, keyrecord_t *record);
bool process_record_user(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 #ifndef BOOTMAGIC_LITE_COLUMN
# define BOOTMAGIC_LITE_COLUMN 0 # define BOOTMAGIC_LITE_COLUMN 0

View file

@ -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)) bool process_record_quantum(keyrecord_t *record) { return true; }
__attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {}
#ifndef NO_ACTION_TAPPING #ifndef NO_ACTION_TAPPING
/** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. /** \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; 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); action_t action = store_or_get_action(record->event.pressed, record->event.key);
dprint("ACTION: "); dprint("ACTION: ");
debug_action(action); debug_action(action);
@ -988,7 +995,6 @@ bool is_tap_action(action_t action) {
* FIXME: Needs documentation. * 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); } 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) /** \brief Debug print (FIXME: Needs better description)
* *
* FIXME: Needs documentation. * FIXME: Needs documentation.

View file

@ -84,6 +84,8 @@ void process_hand_swap(keyevent_t *record);
void process_record_nocache(keyrecord_t *record); void process_record_nocache(keyrecord_t *record);
void process_record(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 process_action(keyrecord_t *record, action_t action);
void register_code(uint8_t code); void register_code(uint8_t code);
void unregister_code(uint8_t code); void unregister_code(uint8_t code);