Skip to content

Commit

Permalink
feat(behaviors): Custom Retro Tap Behavior zmkfirmware#1289
Browse files Browse the repository at this point in the history
  • Loading branch information
frnmjn committed Dec 8, 2024
1 parent 0820991 commit e67ddb4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
9 changes: 9 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ properties:
type: boolean
retro-tap:
type: boolean
retro-tap-behavior:
type: string
default: ""
retro-tap-param1:
type: int
default: 0
retro-tap-param2:
type: int
default: 0
hold-trigger-key-positions:
type: array
required: false
Expand Down
22 changes: 21 additions & 1 deletion app/src/behaviors/behavior_hold_tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum flavor {
enum status {
STATUS_UNDECIDED,
STATUS_TAP,
STATUS_RETRO_TAP,
STATUS_HOLD_INTERRUPT,
STATUS_HOLD_TIMER,
};
Expand All @@ -62,6 +63,9 @@ struct behavior_hold_tap_config {
bool hold_while_undecided;
bool hold_while_undecided_linger;
bool retro_tap;
char *retro_tap_behavior;
uint32_t retro_tap_param1;
uint32_t retro_tap_param2;
bool hold_trigger_on_release;
int32_t hold_trigger_key_positions_len;
int32_t hold_trigger_key_positions[];
Expand Down Expand Up @@ -470,6 +474,11 @@ static int press_binding(struct active_hold_tap *hold_tap) {
} else {
return press_hold_binding(hold_tap);
}
} else if (hold_tap->status == STATUS_RETRO_TAP) {
binding.behavior_dev = hold_tap->config->retro_tap_behavior;
binding.param1 = hold_tap->config->retro_tap_param1;
binding.param2 = hold_tap->config->retro_tap_param2;
store_last_hold_tapped(hold_tap);
} else {
if (hold_tap->config->hold_while_undecided &&
!hold_tap->config->hold_while_undecided_linger) {
Expand All @@ -487,6 +496,10 @@ static int release_binding(struct active_hold_tap *hold_tap) {

if (hold_tap->status == STATUS_HOLD_TIMER || hold_tap->status == STATUS_HOLD_INTERRUPT) {
return release_hold_binding(hold_tap);
} else if (hold_tap->status == STATUS_RETRO_TAP) {
binding.behavior_dev = hold_tap->config->retro_tap_behavior;
binding.param1 = hold_tap->config->retro_tap_param1;
binding.param2 = hold_tap->config->retro_tap_param2;
} else {
return release_tap_binding(hold_tap);
}
Expand Down Expand Up @@ -581,7 +594,11 @@ static void decide_retro_tap(struct active_hold_tap *hold_tap) {
if (hold_tap->status == STATUS_HOLD_TIMER) {
release_binding(hold_tap);
LOG_DBG("%d retro tap", hold_tap->position);
hold_tap->status = STATUS_TAP;
if (strcmp(hold_tap->config->retro_tap_behavior, "") == 0) {
hold_tap->status = STATUS_TAP;
} else {
hold_tap->status = STATUS_RETRO_TAP;
}
press_binding(hold_tap);
return;
}
Expand Down Expand Up @@ -870,6 +887,9 @@ static int behavior_hold_tap_init(const struct device *dev) {
.hold_while_undecided = DT_INST_PROP(n, hold_while_undecided), \
.hold_while_undecided_linger = DT_INST_PROP(n, hold_while_undecided_linger), \
.retro_tap = DT_INST_PROP(n, retro_tap), \
.retro_tap_behavior = DT_INST_PROP(n, retro_tap_behavior), \
.retro_tap_param1 = DT_INST_PROP(n, retro_tap_param1), \
.retro_tap_param2 = DT_INST_PROP(n, retro_tap_param2), \
.hold_trigger_on_release = DT_INST_PROP(n, hold_trigger_on_release), \
.hold_trigger_key_positions = DT_INST_PROP(n, hold_trigger_key_positions), \
.hold_trigger_key_positions_len = DT_INST_PROP_LEN(n, hold_trigger_key_positions), \
Expand Down
26 changes: 26 additions & 0 deletions docs/docs/keymaps/behaviors/hold-tap.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,32 @@ For example, if you press `&mt LEFT_SHIFT A` and then release it without pressin
};
```

To define a behavior to use instead of the tap behavior, include `retro-tap-behavior`, `retro-tap-param1`, and/or `retro-tap-param2` in your hold-tap definition.

- `retro-tap-behavior` refers to the label string of the desired behavior. See below for a list of these label strings for built-in behaviors.
- `retro-tap-param1` refers to the first thing that comes after the behavior in your keymap. e.g. for `&mt LSHFT A`, LSHFT will be param1.
- `retro-tap-param2` refers to the second thing that comes after the behavior in your keymap. e.g. for `&mt LSHFT A`, A will be param2.

List of built-in behaviors and their corresponding label strings:

- &bl - "BCKLGHT"
- &bt - "BLUETOOTH"
- &caps_word - "CAPS_WORD"
- &ext_power - "EXTPOWER"
- &gresc - "GRAVE_ESCAPE"
- &kp - "KEY_PRESS"
- &key_repeat - "KEY_REPEAT"
- &none - "NONE"
- &out - "OUTPUTS"
- &reset - "RESET"
- &bootloader - "BOOTLOAD"
- &rgb_ug - "RGB_UG"
- &sk - "STICKY_KEY"
- &sl - "STICKY_LAYER"
- &to - "TO_LAYER"
- &tog - "TOGGLE_LAYER"
- &trans - "TRANS"

#### `hold-while-undecided`

If enabled, the hold behavior will immediately be held on hold-tap press, and will release before the behavior is sent in the event the hold-tap resolves into a tap. With most modifiers this will not affect typing, and is useful for using modifiers with the mouse.
Expand Down

0 comments on commit e67ddb4

Please sign in to comment.