Skip to content

bug: hold-preferred on first hold-tap does not work when second key is hold-tap with hold-while-undecided #3443

Description

@rmpurp

For some motivation for this bug, I have a thumb key that is a hold-tap with gui hold and esc tap (hold-preferred), with the rest of the modifiers as home-row mods.

// thumb key
ht1: hold_tap_1 {
    compatible = "zmk,behavior-hold-tap";
    #binding-cells = <2>;
    flavor = "hold-preferred";
    tapping-term-ms = <150>;
    bindings = <&kp>, <&kp>;
};

// home row mods
ht2: hold_tap_2 {
    compatible = "zmk,behavior-hold-tap";
    #binding-cells = <2>;
    flavor = "balanced";
    tapping-term-ms = <150>;
    bindings = <&kp>, <&kp>;
    hold-while-undecided;
};

When I do the following key sequence in quick succession (e.g. typical cmd+s to save a document):

  1. &ht1 LGUI ESC down
  2. &ht2 LALT S down
  3. &ht1 LGUI ESC up
  4. &ht2 LALT S up

I would expect it to send gui+s due to the hold-preferred flavor of HT1. What actually does is release cmd before pressing s. This only occurs if the second hold tap has hold-while-undecided; otherwise, it correctly sends gui+s.

I pointed fable at it and it suggested the issue is behavior_hold_tap.c (L806-L810):

    // hold-while-undecided can produce a mod, but we don't want to capture it.
    if (undecided_hold_tap->config->hold_while_undecided &&
        undecided_hold_tap->status == STATUS_UNDECIDED) {
        return ZMK_EV_EVENT_BUBBLE;
    }

basically in keycode_state_changed_listener, we're not capturing the &ht1 LGUI ESC up event and bubbling it instead.

Fable suggested updating the condition to

    if (undecided_hold_tap->config->hold_while_undecided &&
        undecided_hold_tap->status == STATUS_UNDECIDED && 
        ev->state) {

to only bubble key-down events. This does appear to solve the problem, though I'm not an expert in the hold-tap code so I'm not sure if this might cause other issues.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions