Open felix-hilden opened 1 month ago
I would benefit from this too.
My usecase is a little different though: I use tap-dance to on my dedicated layers buttons:
The issue with this is: if I'm on layer_1 toggled, and double tap layer_2 button, both layer_1 and layer_2 will be enabled, and double tapping layer_2 button will return to layer_1.
With the behaviour: I could create a macro that, on double tap, disables all layers and then toggle (or enable, same at this point) the layer this button is dedicated to. This way I'd always have a single layer enabled and know I just have to double tap the currently enabled layer to return to base layer.
With the behaviour: I could create a macro that, on double tap, disables all layers and then toggle (or enable, same at this point) the layer this button is dedicated to.
IIUC the &to behavior should work for this: https://zmk.dev/docs/keymaps/behaviors#layer-navigation-behaviors
My bad, I simplified my situation for the sake of explaining, but turns out I oversimplified.
I have to regularly switch between OSX and Linux, and for this reason I actually have an intermediate layer (swaps LGUI and OSX) I toggle with another combo. So my layers are:
This causes that I cannot use &to
since it would disable layer_OSX and I want to keep it active (if it was active) when double tapping another layer key.
The macro I want to do is, when double tapping layer_X: disable layer_1, disable layer_2, disable layer_3, then enable layer_X
@saponace I'm probably missing something, but perhaps take a look at my &csl
and &cmo
macros here? https://github.com/minusfive/zmk-config/blob/main/knucklehead/macros.dtsi#L30
I [try to] explain it here: https://github.com/minusfive/zmk-config#upper-layer-swapping-vs-stacking
Thank you for taking the time to answer.
However, I do not fully understand your macro csl
.
It uses keycode K_CANCEL
that, according to your documentation, clears all active smart layers. But I don't see anywhere in your repository a config that would define this behaviour, neither do I see anything relevant about this keycode in ZMK documentation. All I can find is https://zmk.dev/docs/keymaps/list-of-keycodes, where it doesn't say anything about this keycode being intercepted or having a specifig behaviour.
To be sure, I tried to add a button that sends &kp K_CANCEL
, but it does nothing aside from sending this keycode to the computer.
I also know github issues is not the best place for asking for support and would gladly move somewhere else if you are willing to explain how your macro works.
@saponace are you on the ZMK discord? Ping me there
@saponace FYI K_CANCEL
is a normal keycode typically ignored by most OSes, essentially used as a noop; in my case to break out of smart / sticky behaviors / layers, as it's just not in the continue list.
But in your case... I took a look at your layout, and if I understood correctly, couldn't you do something like this?:
/*
This macro:
- disables all layers except `0` (default) - see `&to` documentation
- and activates the desired `base layer` (param 1)
- and subsequently toggles the desired `upper layer` (param 2)
Params:
1. base layer to activate
2. upper layer to activate
Example:
`&btog OSX NUM`
*/
btog: btog {
wait-ms = <0>;
tap-ms = <0>;
compatible = "zmk,behavior-macro-two-param";
#binding-cells = <2>;
bindings = <¯o_param_1to1>,
<¯o_press &to MACRO_PLACEHOLDER>,
<¯o_param_2to1>,
<¯o_press &tog MACRO_PLACEHOLDER>;
};
Then on your ALPHA
layer you can use normal &to
or &tog
behaviors (or this macro if you want to be explicit), and on your OSX
layer you override those keys/combos with this macro.
Does that make sense?
That's actually a pretty good workaround for me too! Mainly I would indeed want to activate an extra layer on top of the base (and also include the output device preference in the macro), and even activating different base layers would be possible by using different macro params based on the current layer - maybe with conditional layers.
Still, being able to disable and enable layers individually would make it much easier and succinct to define this kind of behavior 🙏
@felix-hilden nice, glad to be of help. That layer + bt profile case sounds cool, hadn't considered it, but yeah, should work w/macros.
And yeah, I can still see how explicit layer on/off would be nice in these cases.
Oh wow, that's a smart workaround. Thank you for taking the time to look into my config @minusfive ! I added the macro you suggest.
This has me double the number of tap-dance behaviors I have for each layer: &num
to be called from the base layer (btog ALPHA NUM
) and &num_on_osx
to be called from OSX layer (btog OSX NUM
).
That's not very elegant, but it works.
The downside of this workaround with my keymap is that it doesn't work for layer SYSTEM, that is triggered via a combo.
From within the combo I don't know what behavior to trigger: num
or num_on_osx
because I don't the context (OSX layer enabled or disabled).
The best I've found is to create another combo lsystem_on_osx
that filters on layer OSX and triggers the behavior &system_on_osx
, and leave combo lsystem
unchanged (trigger behavior &suystem
).
To avoid conflicts with the combo lsystem
, I need to specify layers for lsystem
(all layers except OSX
).
This causes that whenever I leave layer SYSTEM
by tapping the combo once from NUM
or SYMBOLS
it triggers behavior &system
and returns to layer ALPHA
instead of OSX
.
Surprisingly, and for a reason I don't understand, triggering the combo from layer SYSTEM
with layer OSX
enabled returns to OSX
instead of ALPHA
. Which is great because it is the behavior I want, but it does not make sense to me why it works that way.
For reference, this is my config as defined above: https://github.com/saponace/zmk-config/blob/525983a54677827eb93b2d97ee3e488abad8e77f/config/corne.keymap
Another surprising behaviour I don't understand is: I tried to enable combo lsystem
only on layers ALPHA
and SYSTEM
. It would behave weirdly in that config: I could tap once the combo from any layer to return to the expected base layer (OSX
or ALPHA
) from anywhere, but couldn't hold the combo for the first tap of the tap-dance behavior (&sl
).
It is a cool behavior I could see myself using, but I don't want to leave in my config something that doesn't make sense and it reduces maintainability of the config.
Anyways, long story short. Thanks for your help, and a new behavior &lon
and &loff
to turn on/off a layer would make some configs so much more simple
@felix-hilden pleasure!
You can make macros work on hold
, just need to use ¯o_pause_for_release
. You can read more about it here https://zmk.dev/docs/keymaps/behaviors/macros#processing-continuation-on-release, and see my example here:
https://github.com/minusfive/zmk-config/blob/main/knucklehead/macros.dtsi#L3-L28
Generally I recommend you read thoroughly those docs, and experiment, experiment, experiment. I've found ZMK's power lies primarily in its composability and modularity, as you don't have to depend on new features being added to the core that often, as the primitives can give you most of the behaviors you want. BUT there's a LOT there, and takes patience and experimentation to leverage it. I feel I'm only scratching the surface myself.
The solution for your combo issue, that I'm not sure about. I'd have to think about it more. Top level it'd be best if you contained the contextual behaviors to the base layer, and used regular &trans
keys on all upper layers. Perhaps moving "something else" to the combo? But I know that's not going to work in all cases. That's probably just my head trying to find the simplest path, though :P.
Holding the key/combo down works as expected and the tap-dance picks it up correctly as the first hold (and fires a
&mo
).
Regarding the combo behaving the way it does, I'll look further into it and will post here when (if) I find what I did wrong and how to do it properly.
Thank you again for your precious help. ZMK is indeed a tough piece to approach and I want to get better at understanding how it works and be more comfortable with it
The ability to only turn on or off a layer with dedicated behaviors would make complex layer setups and combos easier. Let me give a specific example:
I regularly work and switch between two computers. One is connected via USB and uses Windows, and one is a Mac I connect to with Bluetooth. To make my layers consistent across the operating systems, I've defined some patches to my basic layers to activate on a flag layer. I always activate this layer when switching to prefer bluetooth connections, and disable it when going back to USB. But the way I need to do it now, is with a layer toggle. Sometimes I mistype, and end up with the wrong layer and output device combo.
Instead of using a layer toggle, I'd want to be sure I am explicitly activating or deactivating a layer. This would also make it usable in a macro, where I can put both actions behind a single key.
Any thoughts? Maybe I've just missed something obvious :sweat_smile: and if that's the case, please do inform me. Many thanks for considering this!