zmkfirmware/zmk

Feature Request: New &df layer behaviour

manna-harbour opened this issue · 3 comments

I'd like to be able to lock a momentary layer. That is, while holding &mo or &lt, tap the layer lock key then release the layer hold but stay on the layer.

&to can not be used as the layer is deactivated when the layer hold is released. &tog can not be used as it deactivates the layer immediately.

QMK has DF, and KMonad has layer-switch, that can be used for this purpose.

I propose adding a new &df layer behaviour to change the default layer.

See the discord comment thread starting here for an earlier discussion on this topic.

Could you make use of the example behaviour shown in the "Toggle-on-Tap, Momentary-on-Hold Layers" example found on the Hold-Tap Behaviour page?

I set my keymap up to allow a 'Fn' key that will toggle the F1..F12 keys layer on when tapped, but allow Fn+F1..F12 to be used without then having to un-toggle the layer. A note of caution though, the documentation currently has the <&tog>, <&mo> bindings reversed so you'll want to switch them. (I put in a PR for it earlier today).

I suppose you might not want to dedicate a key to this behaviour, such as the &lt use case, where the tap might be a character entry key.

Below is an example of how to achieve a layer lock using Conditional Layers. By allowing two separate layers to each control the state of the layer you want to lock, you can avoid the layer deactivating when you release &mo after pressing &tog (or &to).

The key points here are:

  • You are not limited to a single Conditional Layer condition
  • Conditional Layer conditions do not require 2 or more if-layers; 1 will do just fine
  • Since the LOWER layer is controlled by Conditional Layers, you cannot activate it directly; you must instead activate it indirectly using one of the if-layers
#define DEFAULT 0
#define LOWER 1
#define LOWER_TEMP 2
#define LOWER_LOCK 3

/ {
    conditional_layers {
        compatible = "zmk,conditional-layers";
        lower_temp {
            if-layers = <LOWER_TEMP>;
            then-layer = <LOWER>;
        };
        lower_lock {
            if-layers = <LOWER_LOCK>;
            then-layer = <LOWER>;
        };
    };
    keymap {
        compatible = "zmk,keymap";
        default_layer {
            bindings = <
                &mo LOWER_TEMP    &kp A    &kp B
            >;
        };
        lower_layer {
            bindings = <
                &trans    &tog LOWER_LOCK    &kp C
            >;
        };
        lower_temp_layer {
            bindings = <
                &trans    &trans    &trans
            >;
        };
        lower_lock_layer {
            bindings = <
                &trans    &trans    &trans
            >;
        };
    };
};

I wrote this on my phone so no guarantees about it being bug free or even compiling. The approach works though; I use it in my keymap for exactly this feature.

I implemented a basic version of this in #1984 and am using it locally. I'm curious how my version compares to what others had in mind. For example, I think a caps word-like option to disable locked layers would be useful, but it would be a bit difficult to configure...