feat: add slow release positions
This commit is contained in:
parent
df26967cc5
commit
016a77af71
4 changed files with 42 additions and 2 deletions
|
@ -20,6 +20,10 @@ child-binding:
|
|||
default: 50
|
||||
slow-release:
|
||||
type: boolean
|
||||
slow-release-positions:
|
||||
type: array
|
||||
required: false
|
||||
default: []
|
||||
layers:
|
||||
type: array
|
||||
default: [-1]
|
||||
|
|
|
@ -29,9 +29,12 @@ struct combo_cfg {
|
|||
int32_t key_positions[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO];
|
||||
int32_t key_position_len;
|
||||
int32_t timeout_ms;
|
||||
// if slow release is set, the combo releases when the last key is released.
|
||||
// otherwise, the combo releases when the first key is released.
|
||||
// if slow release is set, the combo releases when the last key in slow_release_positions is
|
||||
// released or all keys are released. otherwise, the combo releases when the first key is
|
||||
// released.
|
||||
bool slow_release;
|
||||
int32_t slow_release_positions[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO];
|
||||
int32_t slow_release_positions_len;
|
||||
int8_t layers[CONFIG_ZMK_COMBO_MAX_LAYERS_PER_COMBO];
|
||||
int32_t layers_len;
|
||||
// the virtual key position is a key position outside the range used by the keyboard.
|
||||
|
@ -47,6 +50,8 @@ struct active_combo {
|
|||
// The keys are removed from this array when they are released.
|
||||
// Once this array is empty, the behavior is released.
|
||||
const zmk_event_t *key_positions_pressed[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO];
|
||||
// keep track if the behavior has already been released (used for slow release)
|
||||
bool behavior_released;
|
||||
};
|
||||
|
||||
struct combo_candidate {
|
||||
|
@ -315,6 +320,7 @@ static struct active_combo *store_active_combo(struct combo_cfg *combo) {
|
|||
for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_PRESSED_COMBOS; i++) {
|
||||
if (active_combos[i].combo == NULL) {
|
||||
active_combos[i].combo = combo;
|
||||
active_combos[i].behavior_released = false;
|
||||
active_combo_count++;
|
||||
return &active_combos[i];
|
||||
}
|
||||
|
@ -374,6 +380,27 @@ static bool release_combo_key(int32_t position, int64_t timestamp, const zmk_eve
|
|||
}
|
||||
|
||||
if (key_released) {
|
||||
// slow release
|
||||
if (!active_combo->combo->slow_release && all_keys_pressed) {
|
||||
// if slow release is not enabled, release the behavior
|
||||
process_combo_behavior(active_combo->combo, timestamp, false);
|
||||
} else if (active_combo->combo->slow_release && !active_combo->behavior_released) {
|
||||
// if slow release is enabled and the behavior has not yet been released
|
||||
if (all_keys_released) {
|
||||
// if all keys are released, release the behavior
|
||||
process_combo_behavior(active_combo->combo, timestamp, false);
|
||||
active_combo->behavior_released = true;
|
||||
} else {
|
||||
// if the key being released is a slow release key, release the behavior,
|
||||
// otherwise ignore
|
||||
for (int i = 0; i < active_combo->combo->slow_release_positions_len; i++) {
|
||||
if (active_combo->combo->slow_release_positions[i] == position) {
|
||||
process_combo_behavior(active_combo->combo, timestamp, false);
|
||||
active_combo->behavior_released = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// partial holds
|
||||
for (int i = 1; i < active_combo->combo->behaviors_len; i++) {
|
||||
|
@ -539,6 +566,8 @@ ZMK_SUBSCRIPTION(combo, zmk_position_state_changed);
|
|||
.key_positions = DT_PROP(n, key_positions), \
|
||||
.key_position_len = DT_PROP_LEN(n, key_positions), \
|
||||
.slow_release = DT_PROP(n, slow_release), \
|
||||
.slow_release_positions = DT_PROP(n, slow_release_positions), \
|
||||
.slow_release_positions_len = DT_PROP_LEN(n, slow_release_positions), \
|
||||
.layers = DT_PROP(n, layers), \
|
||||
.layers_len = DT_PROP_LEN(n, layers), \
|
||||
.virtual_key_position = ZMK_VIRTUAL_KEY_POSITION_COMBO(__COUNTER__), \
|
||||
|
|
|
@ -38,6 +38,7 @@ Each child node can have the following properties:
|
|||
| `key-positions` | array | A list of key position indices for the keys which should trigger the combo | |
|
||||
| `timeout-ms` | int | All the keys in `key-positions` must be pressed within this time in milliseconds to trigger the combo | 50 |
|
||||
| `slow-release` | bool | Releases the combo when all keys are released instead of when any key is released | false |
|
||||
| `slow-release-positions` | array | A list of key position indices for the keys that must be held during `slow-release`. If any key in `slow-release-positions` is released, the combo is released. | |
|
||||
| `layers` | array | A list of layers on which the combo may be triggered. `-1` allows all layers. | `<-1>` |
|
||||
|
||||
The `key-positions` array must not be longer than the `CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO` setting, which defaults to 4. If you want a combo that triggers when pressing 5 keys, then you must change the setting to 5.
|
||||
|
|
|
@ -50,6 +50,12 @@ Invoking a source-specific behavior such as one of the [reset behaviors](behavio
|
|||
|
||||
See [combo configuration](/docs/config/combos) for advanced configuration options.
|
||||
|
||||
### Slow Release
|
||||
|
||||
If you want the combo binding to be released when all positions are released, instead of when any position is released, enable `slow-release`. This is useful for combos that are used to toggle a layer, for example.
|
||||
|
||||
However, you may want to continue to hold the combo when one position is held but not the other. For example, if the keys corresponding to the combo positions 0 and 1 are `&mo NAV` and `&kp A`, and the combo behavior is `&kp LEFT`, you may want to continue holding `LEFT` while you hold `A` and release `NAV`, but not if you hold `NAV` and release `A`. To solve this, you can specify `slow-release-positions` to select which keys must be held to maintain `slow-release`. In this example, you would specify `slow-release-positions = <1>`. In other words, the combo will be held as long _all_ keys in `slow-release-positions` are held, and released when _any_ key in `slow-release-positions` is released.
|
||||
|
||||
### Partial Holds
|
||||
|
||||
After pressing a combo, you may want to specify the behavior that is activated when the combo is partially released. For example, if the keys corresponding to the combo positions 0, 1, and 2 are `&tog NAV`, `&kp A`, and `&kp LSFT` and the combo behavior is `&kp LEFT`, you may want to activate `&mo NAV` when you release `A` or `LSFT` but continue to hold `NAV`, or activate `LSFT` when you release `NAV` or `A` but continue to hold `LSFT`.
|
||||
|
|
Loading…
Add table
Reference in a new issue