Skip to content

Feature request: Automatically held/released mods for certain keycodes for Alt-Tab window switching #997

Description

@caksoylar

This is an attempt to formalize the discussion at https://discord.com/channels/719497620560543766/719565084208398406/900412989033828444 with @bcat and @dxmh.

There are a few use cases around tapping a sequence of keys while another key (usually a modifier) is being held that folks, especially working with small keyboards, have been using with custom code in other firmware like QMK:

  1. Having a single key to do window switching with Alt+Tab or Cmd+Tab. The usual way this is implemented is with a timer (out of scope here), or first press includes the mod, layer switching and/or pressing/releasing any other key releases the mod.
    The most popular implementation is probably swapper feature by Callum Oakley in their QMK workspace. There are other bespoke implementations that are independently developed or extension to multiple keys (Tab, Shift+Tab on separate keys). Another use case is switching keyboard layouts in Windows/Mac OS with Ctrl+Space or GUI+Space.
  2. Having a "text selection mode" similar to the visual mode in Vim. In this case usually arrows keys are pressed while Shift is automatically held. This is not a good example since shift doesn't need to stay held between key presses typically, see below comments.

In terms of implementation there can be two approaches:

  1. A behavior that can be assigned to a single key (like for Alt+Tab window switching). It can keep track of its own modifier state and listen to layer change or key press/release events to release it. It could look something like this in the keymap:
/ {
    behaviors {
        at: alt_tabber {
            compatible = "zmk,mod-holder";
            label = "ALT_TABBER";
            #binding-cells = <1>;
            mods = <MOD_LALT>;
        };
    };
    keymap {
    [...] &at TAB [...]
    }
};
  1. A keymap node similar to a combo where you specify the modifier, (a list of) layer(s) and a list of key positions. The first press on any of the positions on that layer would press the modifier key, along with triggering the usual behavior of that key. On layer change or another position press/release the modifier is released.
    This could look like:
/ {
    modholders {
        compatible = "zmk,mod-holder";
        window_switcher {
            layers = <0>;
            key-positions = <0 1>;
            mods = <MOD_LALT>;
        };
        visual_mode {
            layers = <1>;
            key-positions = <0 1 2 3>;
            mods = <MOD_LSHIFT>;
        };
    };
    keymap {
    [...] &kp TAB &kp LS(TAB) [...]
    [...] &kp LEFT &kp UP &kp DOWN &kp RIGHT [...]
    }
};

The first approach doesn't cover use case 2. above but arguably simpler and covers the most frequent one. The second approach would cover both, and also multiple keys for window switching.

It is also possible to extend all of the above to hold/release any behavior and not just modifier keycodes, if a useful scenario exists for that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    behaviorsenhancementNew feature or requestkeymapsPRs and issues related to keymaps

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions