summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--docs/feature_macros.md40
-rw-r--r--docs/understanding_qmk.md9
-rw-r--r--quantum/quantum.c20
-rw-r--r--quantum/quantum.h2
-rw-r--r--tmk_core/common/action.c8
-rw-r--r--tmk_core/common/action.h2
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);