diff options
| -rw-r--r-- | docs/feature_combo.md | 50 | ||||
| -rw-r--r-- | keyboards/gboards/g/keymap_combo.h | 48 | ||||
| -rw-r--r-- | quantum/process_keycode/process_combo.c | 14 | 
3 files changed, 104 insertions, 8 deletions
| diff --git a/docs/feature_combo.md b/docs/feature_combo.md index c45e3fd0e4..75c78c4cd4 100644 --- a/docs/feature_combo.md +++ b/docs/feature_combo.md @@ -328,6 +328,51 @@ If you, for example, use multiple base layers for different key layouts, one for  With `#define COMBO_ONLY_FROM_LAYER 0` in config.h, the combos' keys are always checked from layer `0`, even if other layers are active. +### Combo reference layers by layer. + +If not using `COMBO_ONLY_FROM_LAYER` it is possible to specify a +combo reference layer for any layer using the `combo_ref_from_layer` hook.  +The combo macros automatically create this function from the `COMBO_REF_LAYER()` +entries given. + +This function returns the assigned reference layer for the current layer. +if there is no match, it returns the  default reference layer if set,  +or the current layer otherwise. A default layer can be set with +`DEFAULT_REF_LAYER(_MY_COMBO_REF_LAYER)` + +If not set, the default reference layer selection from the automatically generated  +`combo-ref-from-layer()` will be the current layer. + +The following `combo_ref_from_layer` function  +will give a reference layer of _QWERTY for the _DVORAK layer and +will give the _NAV layer as a reference to it's self. All other layers +will have the default for their combo reference layer. If the default +is not set, all other layers will reference themselves. + +    ```c +    #define COMBO_REF_DEFAULT _MY_COMBO_LAYER +    ... + +    uint8_t combo_ref_from_layer(uint8_t layer){ +        switch (get_highest_layer(layer_state)){ +            case _DVORAK: return _QWERTY; +            case _NAV: return _NAV; +            default: return _MY_COMBO_LAYER; +        } +        return layer;  // important if default is not in case. +    } + +    ``` +     +    The equivalent definition using the combo macros is this:  + +    ```c +    COMBO_REF_LAYER(_DVORAK, _QWERTY) +    COMBO_REF_LAYER(_NAV, _NAV) +    DEFAULT_REF_LAYER(_MY_COMBO_LAYER). +    ``` +     +  ## User callbacks  In addition to the keycodes, there are a few functions that you can use to set the status, or check it: @@ -350,6 +395,11 @@ First, you need to add `VPATH += keyboards/gboards` to your `rules.mk`. Next, in  Then, write your combos in `combos.def` file in the following manner:  ```c +// Alternate reference layers by layer +//               Layer     Reference layer +COMBO_REF_LAYER(_DVORAK, _QWERTY)  // reference the qwerty layer for dvorak. +COMBO_REF_LAYER(_NAV, _NAV) // explicit reference to self instead of the default. +  //   name     result    chord keys  COMB(AB_ESC,   KC_ESC,   KC_A, KC_B)  COMB(JK_TAB,   KC_TAB,   KC_J, KC_K) diff --git a/keyboards/gboards/g/keymap_combo.h b/keyboards/gboards/g/keymap_combo.h index b92b6a4bc4..68ea44b1b4 100644 --- a/keyboards/gboards/g/keymap_combo.h +++ b/keyboards/gboards/g/keymap_combo.h @@ -1,4 +1,10 @@  // Keymap helpers +// define reference layers per layer. +#define REF_LAYER_FOR_LAYER(LAYER, REF_LAYER)   \ +  case LAYER: return REF_LAYER; + +#define DEF_REF_LAYER(LAYER)                    \ +  default: return LAYER;  #define K_ENUM(name, key, ...) name,  #define K_DATA(name, key, ...) const uint16_t PROGMEM cmb_##name[] = {__VA_ARGS__, COMBO_END}; @@ -7,17 +13,22 @@  #define A_ENUM(name, string, ...) name,  #define A_DATA(name, string, ...) const uint16_t PROGMEM cmb_##name[] = {__VA_ARGS__, COMBO_END};  #define A_COMB(name, string, ...) [name] = COMBO_ACTION(cmb_##name), -#define A_ACTI(name, string, ...)         \ -    case name:                            \ -        if (pressed) SEND_STRING(string); \ +#define A_ACTI(name, string, ...)               \ +    case name:                                  \ +        if (pressed) SEND_STRING(string);           \          break; -#define A_TOGG(name, layer, ...)          \ -    case name:                            \ -        if (pressed) layer_invert(layer); \ +#define A_TOGG(name, layer, ...)                \ +    case name:                                    \ +        if (pressed) layer_invert(layer);             \          break;  #define BLANK(...) +#undef COMBO_REF_LAYER +#undef DEFAULT_REF_LAYER +#define COMBO_REF_LAYER BLANK +#define DEFAULT_REF_LAYER BLANK +  // Generate data needed for combos/actions  // Create Enum  #undef COMB @@ -66,10 +77,33 @@ void process_combo_event(uint16_t combo_index, bool pressed) {      }      // Allow user overrides per keymap -#if __has_include("inject.h")  +#if __has_include("inject.h")  # include "inject.h"  #endif  }  #undef COMB  #undef SUBS  #undef TOGG + +// Allow reference layers per layer. +#define COMB BLANK +#define SUBS BLANK +#define TOGG BLANK + +#undef DEFAULT_REF_LAYER +#undef COMBO_REF_LAYER +#define COMBO_REF_LAYER REF_LAYER_FOR_LAYER +#define DEFAULT_REF_LAYER DEF_REF_LAYER + +uint8_t combo_ref_from_layer(uint8_t current_layer){ +  switch (current_layer){ +#include "combos.def" +  } +  return current_layer; +} + +#undef COMB +#undef SUBS +#undef TOGG +#undef COMBO_REF_LAYER +#undef DEFAULT_REF_LAYER diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index d8b089db16..8597649c92 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -29,6 +29,12 @@ extern uint16_t COMBO_LEN;  __attribute__((weak)) void process_combo_event(uint16_t combo_index, bool pressed) {} +#ifndef COMBO_ONLY_FROM_LAYER +__attribute__((weak)) uint8_t combo_ref_from_layer(uint8_t layer) { +    return layer; +} +#endif +  #ifdef COMBO_MUST_HOLD_PER_COMBO  __attribute__((weak)) bool get_combo_must_hold(uint16_t index, combo_t *combo) {      return false; @@ -304,7 +310,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {  #if defined(EXTRA_EXTRA_LONG_COMBOS)      uint32_t state = 0;  #elif defined(EXTRA_LONG_COMBOS) -    uint16_t state = 0; +    uint16_t state         = 0;  #else      uint8_t state = 0;  #endif @@ -549,6 +555,12 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {  #ifdef COMBO_ONLY_FROM_LAYER      /* Only check keycodes from one layer. */      keycode = keymap_key_to_keycode(COMBO_ONLY_FROM_LAYER, record->event.key); +#else +    uint8_t  highest_layer = get_highest_layer(layer_state); +    uint8_t  ref_layer     = combo_ref_from_layer(highest_layer); +    if (ref_layer != highest_layer) { +        keycode = keymap_key_to_keycode(ref_layer, record->event.key); +    }  #endif      for (uint16_t idx = 0; idx < COMBO_LEN; ++idx) { | 
