Skip to content

Instantly share code, notes, and snippets.

@NullSense
Created April 22, 2021 11:07
Show Gist options
  • Save NullSense/da2846fcde7d4b1bb7395d5d197bb776 to your computer and use it in GitHub Desktop.
Save NullSense/da2846fcde7d4b1bb7395d5d197bb776 to your computer and use it in GitHub Desktop.
QMK Bilateral combinations patch
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index 2387f50dc8..4448ceae4b 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -51,6 +51,10 @@ int retro_tapping_counter = 0;
# include "fauxclicky.h"
#endif
+#if (BILATERAL_COMBINATIONS + 0)
+# include "quantum.h"
+#endif
+
#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; }
#endif
@@ -243,6 +247,68 @@ void process_record_handler(keyrecord_t *record) {
process_action(record, action);
}
+#ifdef BILATERAL_COMBINATIONS
+static struct {
+ bool active;
+ uint8_t code;
+ uint8_t tap;
+ uint8_t mods;
+ bool left;
+# if (BILATERAL_COMBINATIONS + 0)
+ uint16_t time;
+# endif
+} bilateral_combinations = { false };
+
+static bool bilateral_combinations_left(keypos_t key) {
+# ifdef SPLIT_KEYBOARD
+ return key.row < MATRIX_ROWS / 2;
+# else
+ if (MATRIX_COLS > MATRIX_ROWS) {
+ return key.col < MATRIX_COLS / 2;
+ } else {
+ return key.row < MATRIX_ROWS / 2;
+ }
+# endif
+}
+
+static void bilateral_combinations_hold(action_t action, keyevent_t event) {
+ dprint("BILATERAL_COMBINATIONS: hold\n");
+ bilateral_combinations.active = true;
+ bilateral_combinations.code = action.key.code;
+ bilateral_combinations.tap = action.layer_tap.code;
+ bilateral_combinations.mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4;
+ bilateral_combinations.left = bilateral_combinations_left(event.key);
+# if (BILATERAL_COMBINATIONS + 0)
+ bilateral_combinations.time = event.time;
+# endif
+}
+
+static void bilateral_combinations_release(uint8_t code) {
+ dprint("BILATERAL_COMBINATIONS: release\n");
+ if (bilateral_combinations.active && (code == bilateral_combinations.code)) {
+ bilateral_combinations.active = false;
+ }
+}
+
+static void bilateral_combinations_tap(keyevent_t event) {
+ dprint("BILATERAL_COMBINATIONS: tap\n");
+ if (bilateral_combinations.active) {
+ if (bilateral_combinations_left(event.key) == bilateral_combinations.left) {
+# if (BILATERAL_COMBINATIONS + 0)
+ if (TIMER_DIFF_16(event.time, bilateral_combinations.time) > BILATERAL_COMBINATIONS) {
+ dprint("BILATERAL_COMBINATIONS: timeout\n");
+ return;
+ }
+# endif
+ dprint("BILATERAL_COMBINATIONS: change\n");
+ unregister_mods(bilateral_combinations.mods);
+ tap_code(bilateral_combinations.tap);
+ }
+ bilateral_combinations.active = false;
+ }
+}
+#endif
+
#if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE)
void register_button(bool pressed, enum mouse_buttons button) {
# ifdef PS2_MOUSE_ENABLE
@@ -301,6 +367,12 @@ void process_action(keyrecord_t *record, action_t action) {
}
send_keyboard_report();
}
+ #ifdef BILATERAL_COMBINATIONS
+ if (!(IS_MOD(action.key.code) || action.key.code == KC_NO)) {
+ // regular keycode tap during mod-tap hold
+ bilateral_combinations_tap(event);
+ }
+ #endif
register_code(action.key.code);
} else {
unregister_code(action.key.code);
@@ -388,12 +460,20 @@ void process_action(keyrecord_t *record, action_t action) {
} else
# endif
{
+ # ifdef BILATERAL_COMBINATIONS
+ // mod-tap tap
+ bilateral_combinations_tap(event);
+ # endif
dprint("MODS_TAP: Tap: register_code\n");
register_code(action.key.code);
}
} else {
dprint("MODS_TAP: No tap: add_mods\n");
register_mods(mods);
+ # ifdef BILATERAL_COMBINATIONS
+ // mod-tap hold
+ bilateral_combinations_hold(action, event);
+ # endif
}
} else {
if (tap_count > 0) {
@@ -407,6 +487,10 @@ void process_action(keyrecord_t *record, action_t action) {
} else {
dprint("MODS_TAP: No tap: add_mods\n");
unregister_mods(mods);
+ # ifdef BILATERAL_COMBINATIONS
+ // mod-tap release
+ bilateral_combinations_release(action.key.code);
+ # endif
}
}
break;
@@ -614,6 +698,10 @@ void process_action(keyrecord_t *record, action_t action) {
/* tap key */
if (event.pressed) {
if (tap_count > 0) {
+ # ifdef BILATERAL_COMBINATIONS
+ // layer-tap tap
+ bilateral_combinations_tap(event);
+ # endif
dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
register_code(action.layer_tap.code);
} else {
@NullSense
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment