parent
d5cc504b3a
commit
8e4d916ed1
28 changed files with 269 additions and 6 deletions
|
@ -45,6 +45,7 @@ struct behavior_hold_tap_config {
|
||||||
int tapping_term_ms;
|
int tapping_term_ms;
|
||||||
struct behavior_hold_tap_behaviors *behaviors;
|
struct behavior_hold_tap_behaviors *behaviors;
|
||||||
enum flavor flavor;
|
enum flavor flavor;
|
||||||
|
bool ignore_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// this data is specific for each hold-tap
|
// this data is specific for each hold-tap
|
||||||
|
@ -234,8 +235,8 @@ static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decisio
|
||||||
hold_tap->is_hold = 0;
|
hold_tap->is_hold = 0;
|
||||||
hold_tap->is_decided = true;
|
hold_tap->is_decided = true;
|
||||||
break;
|
break;
|
||||||
case HT_OTHER_KEY_DOWN:
|
|
||||||
case HT_TIMER_EVENT:
|
case HT_TIMER_EVENT:
|
||||||
|
case HT_OTHER_KEY_DOWN:
|
||||||
hold_tap->is_hold = 1;
|
hold_tap->is_hold = 1;
|
||||||
hold_tap->is_decided = true;
|
hold_tap->is_decided = true;
|
||||||
break;
|
break;
|
||||||
|
@ -345,7 +346,8 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
|
||||||
// If these events were queued, the timer event may be queued too late or not at all.
|
// If these events were queued, the timer event may be queued too late or not at all.
|
||||||
// We insert a timer event before the TH_KEY_UP event to verify.
|
// We insert a timer event before the TH_KEY_UP event to verify.
|
||||||
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
|
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
|
||||||
if (event.timestamp > (hold_tap->timestamp + hold_tap->config->tapping_term_ms)) {
|
if (hold_tap->config->tapping_term_ms > 0 &&
|
||||||
|
event.timestamp > (hold_tap->timestamp + hold_tap->config->tapping_term_ms)) {
|
||||||
decide_hold_tap(hold_tap, HT_TIMER_EVENT);
|
decide_hold_tap(hold_tap, HT_TIMER_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +410,8 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) {
|
||||||
// If these events were queued, the timer event may be queued too late or not at all.
|
// If these events were queued, the timer event may be queued too late or not at all.
|
||||||
// We make a timer decision before the other key events are handled if the timer would
|
// We make a timer decision before the other key events are handled if the timer would
|
||||||
// have run out.
|
// have run out.
|
||||||
if (ev->timestamp >
|
if (undecided_hold_tap->config->tapping_term_ms > 0 &&
|
||||||
|
ev->timestamp >
|
||||||
(undecided_hold_tap->timestamp + undecided_hold_tap->config->tapping_term_ms)) {
|
(undecided_hold_tap->timestamp + undecided_hold_tap->config->tapping_term_ms)) {
|
||||||
decide_hold_tap(undecided_hold_tap, HT_TIMER_EVENT);
|
decide_hold_tap(undecided_hold_tap, HT_TIMER_EVENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
ht_decide: 0 decided tap (hold-preferred event 0)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
ht_decide: 0 decided tap (hold-preferred event 0)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0xe4 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
|
||||||
|
ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
|
||||||
|
ZMK_MOCK_RELEASE(1,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
ht_decide: 0 decided tap (hold-preferred event 0)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(1,0,10) /*d*/
|
||||||
|
ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
ht_decide: 0 decided hold (hold-preferred event 1)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
/* timer */
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
ht_hold: behavior_hold_hold_tap {
|
||||||
|
compatible = "zmk,behavior-hold-tap";
|
||||||
|
label = "hold_hold_tap";
|
||||||
|
#binding-cells = <2>;
|
||||||
|
flavor = "hold-preferred";
|
||||||
|
tapping_term_ms = <0>;
|
||||||
|
bindings = <&kp>, <&kp>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&ht_hold LEFT_SHIFT F &ht_hold LEFT_CONTROL J
|
||||||
|
&kp D &kp RIGHT_CONTROL>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
ht_decide: 0 decided tap (hold-preferred event 0)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
ht_decide: 0 decided tap (hold-preferred event 0)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0xe4 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
|
||||||
|
ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
|
||||||
|
ZMK_MOCK_RELEASE(1,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
ht_decide: 0 decided tap (hold-preferred event 0)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x09 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(1,0,10) /*d*/
|
||||||
|
ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*on_hold_tap_binding/ht_binding/p
|
||||||
|
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
||||||
|
ht_binding_pressed: 0 new undecided hold_tap
|
||||||
|
ht_decide: 0 decided hold (hold-preferred event 1)
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x07 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0xe1 mods 0x00
|
||||||
|
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
/* timer */
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
ht_hold: behavior_hold_hold_tap {
|
||||||
|
compatible = "zmk,behavior-hold-tap";
|
||||||
|
label = "hold_hold_tap";
|
||||||
|
#binding-cells = <2>;
|
||||||
|
flavor = "hold-preferred";
|
||||||
|
tapping_term_ms = <0>;
|
||||||
|
bindings = <&kp>, <&kp>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&ht_hold LEFT_SHIFT F &ht_hold LEFT_CONTROL J
|
||||||
|
&kp D &kp RIGHT_CONTROL>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -21,6 +21,14 @@ By default, the hold-tap is configured to also select the 'hold' functionality i
|
||||||
|
|
||||||
We call this the 'hold-preferred' flavor of hold-taps. While this flavor may work very well for a ctrl/escape key, it's not very well suited for home-row mods or layer-taps. That's why there are two more flavors to choose from: 'tap-preferred' and 'balanced'.
|
We call this the 'hold-preferred' flavor of hold-taps. While this flavor may work very well for a ctrl/escape key, it's not very well suited for home-row mods or layer-taps. That's why there are two more flavors to choose from: 'tap-preferred' and 'balanced'.
|
||||||
|
|
||||||
|
#### Flavors
|
||||||
|
|
||||||
|
- The 'hold-preferred' flavor triggers the hold behavior when the tapping_term_ms has expired or another key is pressed.
|
||||||
|
- The 'balanced' flavor will trigger the hold behavior when the tapping_term_ms has expired or another key is pressed and released.
|
||||||
|
- The 'tap-preferred' flavor triggers the hold behavior when the tapping_term_ms has expired. It triggers the tap behavior when another key is pressed.
|
||||||
|
|
||||||
|
When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Basic usage
|
### Basic usage
|
||||||
|
@ -29,7 +37,7 @@ For basic usage, please see [mod-tap](./mod-tap.md) and [layer-tap](./layers.md)
|
||||||
|
|
||||||
### Advanced Configuration
|
### Advanced Configuration
|
||||||
|
|
||||||
A code example which configures a mod-tap setting that works with homerow mods:
|
This example configures a hold-tap setting that works well with homerow mods:
|
||||||
|
|
||||||
```
|
```
|
||||||
#include <behaviors.dtsi>
|
#include <behaviors.dtsi>
|
||||||
|
@ -62,8 +70,16 @@ A code example which configures a mod-tap setting that works with homerow mods:
|
||||||
|
|
||||||
If this config does not work for you, try the flavor "tap-preferred" and a short tapping_term_ms such as 120ms.
|
If this config does not work for you, try the flavor "tap-preferred" and a short tapping_term_ms such as 120ms.
|
||||||
|
|
||||||
If you want to use a tap-hold with a keycode from a different code page, you have to define another behavior with another "bindings" parameter.For example, if you want to use SHIFT and volume up, define the bindings like `bindings = <&kp>, <&kp>;`. Only single-argument behaviors are supported at the moment.
|
#### Disabling the timer
|
||||||
|
|
||||||
|
If you set the tapping_term_ms to `0`, the timer is disabled for this hold-tap:
|
||||||
|
|
||||||
|
- The 'hold-preferred' flavor with tapping_term_ms `0` triggers the hold behavior when another key is pressed.
|
||||||
|
- The 'balanced' flavor with tapping_term_ms `0` triggers the hold behavior when another key is pressed and released.
|
||||||
|
- The 'tap-preferred' flavor with tapping_term_ms `0` never triggers the hold behavior (so don't set the tapping_term for these to 0)!
|
||||||
|
|
||||||
#### Comparison to QMK
|
#### Comparison to QMK
|
||||||
|
|
||||||
The hold-preferred flavor works similar to the `HOLD_ON_OTHER_KEY_PRESS` setting in QMK. The 'balanced' flavor is similar to the `PERMISSIVE_HOLD` setting, and the `tap-preferred` flavor is similar to `IGNORE_MOD_TAP_INTERRUPT`.
|
The hold-preferred flavor works similar to the `HOLD_ON_OTHER_KEY_PRESS` setting in QMK. The 'balanced' flavor is similar to the `PERMISSIVE_HOLD` setting, and the `tap-preferred` flavor is similar to `IGNORE_MOD_TAP_INTERRUPT`.
|
||||||
|
|
||||||
|
Setting the `tapping_term_ms` to `0` is equivalent to `RETRO_TAPPING` in QMK.
|
||||||
|
|
Loading…
Add table
Reference in a new issue