diff options
Diffstat (limited to 'quantum/process_keycode/process_combo.c')
| -rw-r--r-- | quantum/process_keycode/process_combo.c | 39 | 
1 files changed, 38 insertions, 1 deletions
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index a050161edf..8040ede528 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -40,10 +40,18 @@ __attribute__((weak)) bool get_combo_must_tap(uint16_t index, combo_t *combo) {  __attribute__((weak)) uint16_t get_combo_term(uint16_t index, combo_t *combo) { return COMBO_TERM; }  #endif +#ifdef COMBO_MUST_PRESS_IN_ORDER_PER_COMBO +__attribute__((weak)) bool get_combo_must_press_in_order(uint16_t combo_index, combo_t *combo) { return true; } +#endif +  #ifdef COMBO_PROCESS_KEY_RELEASE  __attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode) { return false; }  #endif +#ifdef COMBO_SHOULD_TRIGGER +__attribute__((weak)) bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record) { return true; } +#endif +  #ifndef COMBO_NO_TIMER  static uint16_t timer = 0;  #endif @@ -350,6 +358,28 @@ combo_t *overlaps(combo_t *combo1, combo_t *combo2) {      return combo1;  } +#if defined(COMBO_MUST_PRESS_IN_ORDER) || defined(COMBO_MUST_PRESS_IN_ORDER_PER_COMBO) +static bool keys_pressed_in_order(uint16_t combo_index, combo_t *combo, uint16_t key_index, uint16_t keycode, keyrecord_t *record) { +#    ifdef COMBO_MUST_PRESS_IN_ORDER_PER_COMBO +    if (!get_combo_must_press_in_order(combo_index, combo)) { +        return true; +    } +#    endif +    if ( +        // The `state` bit for the key being pressed. +        (1 << key_index) == +        // The *next* combo key's bit. +        (COMBO_STATE(combo) + 1) +        // E.g. two keys already pressed: `state == 11`. +        // Next possible `state` is `111`. +        // So the needed bit is `100` which we get with `11 + 1`. +    ) { +        return true; +    } +    return false; +} +#endif +  static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) {      uint8_t  key_count = 0;      uint16_t key_index = -1; @@ -360,7 +390,14 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *          return false;      } -    bool key_is_part_of_combo = !COMBO_DISABLED(combo) && is_combo_enabled(); +    bool key_is_part_of_combo = (!COMBO_DISABLED(combo) && is_combo_enabled() +#if defined(COMBO_MUST_PRESS_IN_ORDER) || defined(COMBO_MUST_PRESS_IN_ORDER_PER_COMBO) +                                 && keys_pressed_in_order(combo_index, combo, key_index, keycode, record) +#endif +#ifdef COMBO_SHOULD_TRIGGER +                                 && combo_should_trigger(combo_index, combo, keycode, record) +#endif +    );      if (record->event.pressed && key_is_part_of_combo) {          uint16_t time = _get_combo_term(combo_index, combo);  | 
