zmkfirmware / zmk

ZMK Firmware Repository
https://zmk.dev/
MIT License
2.64k stars 2.7k forks source link

Feature: Grave Escape #85

Closed Nicell closed 3 years ago

Nicell commented 4 years ago

Grave escape is an extremely common feature used by keyboards without an F-row. We should be able to implement this neatly with a new behavior.

QMK docs for reference: https://beta.docs.qmk.fm/using-qmk/advanced-keycodes/feature_grave_esc

okke-formsma commented 3 years ago

Two possible approaches:

/ {
    behaviors {
        gresc: grave_escape {
            compatible = "zmk,behavior-mod-morph";
            label = "GRAVE_ESCAPE";
            #binding-cells = <0>;
            bindings = <&kp ESC>, <&kp GRAVE>;
            mods = <(MOD_LGUI | MOD_LSFT)>;
            deactivate-mods;
        };
    };
};

usage: &gresc

/ {
    behaviors {
        morph: morph {
            compatible = "zmk,behavior-mod-morph";
            label = "GRAVE_ESCAPE";
            #binding-cells = <2>;
            bindings = <&kp>, <&kp>;
            mods = <(MOD_LGUI | MOD_LSFT)>;
            deactivate-mods;
        };
    };
};

usage: &morph ESC GRAVE

This could potentially both be supported by the same behavior implementation.

The deactivate-mods boolean would be most easily implemented by adding a complement to "implicit modifiers" like "implicit-disabled-modifiers" which would disable some modifiers until the next keypress/release.

okke-formsma commented 3 years ago

The following config would make grave-escape work better in windows & macos, where lgui+` is a shortcut:

/ {
    behaviors {
        gresc_shift: gresc_shift {
            compatible = "zmk,behavior-mod-morph";
            label = "GRAVE_ESCAPE";
            #binding-cells = <0>;
            bindings = <&kp ESC>, <&kp GRAVE>;
            mods = <(MOD_LSHIFT)>;
        };
        gresc: grave_escape {
            compatible = "zmk,behavior-mod-morph";
            label = "GRAVE_ESCAPE";
            #binding-cells = <0>;
            bindings = <&gresc_shift>, <&kp GRAVE>;
            mods = <(MOD_LGUI)>;
            deactivate-mods;
        };
    };
};

usage: &gresc
presses ESC normally, LGUI+key = grave, shift + key = ~
okke-formsma commented 3 years ago

I made an implementation of grave-escape like QMK has. The deactivate-mods idea discussed above is not yet implemented. If people want that kind of behavior maybe they're better off using layers.

tominabox1 commented 3 years ago

Tested a generalized behavior in my keymap and had the expected behavior ` ccln: ctrl_colon { compatible = "zmk,behavior-mod-morph"; label = "CTRL_COLON";

binding-cells = <0>;

        bindings = <&kp COMMA>, <&kp SEMI>;
        mods = <(MOD_LCTL|MOD_LSFT)>;
    };`

macOS Big Sur interpreted all keys as expected. Nice work Okke!