Closed urza closed 2 years ago
Looks like you are using Oryx to configure the board, which implements such complex key behavior using the Tap Dance feature. Unfortunately, Tap Dance does not respect most of Tap-Hold configuration options — only the tapping term gets applied, and any other modes, such as Permissive Hold, do not affect the behavior of tap dance keys. And the implementation details of Tap Dance make implementing any mode other than an equivalent of HOLD_ON_OTHER_KEY_PRESS
impossible — the tap dance code cannot delay other key events to defer the decision between a tap and a hold.
Even worse, the code generated by Oryx explicitly handles an “interrupted” tap dance (the case when you press another key while still holding the tap dance key before the tapping term had expired) as a tap, not a hold; you are probably seeing this behavior.
And yet another problem is that switching layers from tap dances requires some workarounds, otherwise in the “interrupted” case the layer switch is not applied to the next key pressed after the tap dance key. Looks like Oryx does not implement that workaround in the generated code, and with your particular configuration implementing that workaround does not even seem to be possible — the layer that would be used for the next key after the tap dance must be determined at the moment the tap dance key is pressed, and in your case it might be either 0 or 4, but it is not possible to distinguish a tap from a hold at that time.
Probably the best way to implement the behavior that you want is to use a keycode which is handled by the builtin tap-hold code (e.g., LT()
, which performs an equivalent of MO()
on a hold), and then replace its tap behavior as described in Intercepting Mod-Taps. If you do this, you can use all tap-hold decision modes (e.g., PERMISSIVE_HOLD
or PERMISSIVE_HOLD_PER_KEY
), and the other key events would be delayed if needed to perform the tap-hold decision. However, you cannot do that using the Oryx configurator or config.qmk.fm — you will need to edit the keymap as C code and compile the firmware from source.
@sigprof thanks for your excellent answer.. it is unfortunate situation, it seems I would either have to fiddle with the generated C code (and merge this every time I do some changes in Oryx) or come up with some other way of switching layers or organize my keys in layers so that I can avoid this switching issue in most common cases..
In retrospect dual function keys caused me quite some trouble and I would do better to try to avoid dual function keys as much as possible..
Here are some discussion threads from reddit from people with similar issue:
https://old.reddit.com/r/ergodox/comments/opnpzv/retro_tapping_on_tap_dance/
https://old.reddit.com/r/Moonlander/comments/pxygoc/layer_switch_not_happening_when_typing_fast/
thread by me, where people posted some workarounds: https://www.reddit.com/r/ergodox/comments/qufr0o/is_it_possible_to_cofigure_permissive_hold_for_mo/
This issue has been automatically marked as stale because it has not had activity in the last 90 days. It will be closed in the next 30 days unless it is tagged properly or other activity occurs.
For maintainers: Please label with bug
, in progress
, on hold
, discussion
or to do
to prevent the issue from being re-flagged.
This issue has been automatically closed because it has not had activity in the last 30 days. If this issue is still valid, re-open the issue and let us know. // [stale-action-closed]
I am also seeking to use a dual-function momentary layer toggle key, and similarly I use oryx, and with "hold on other key press" modifiers like shift work but layer switching requires me to hold the key for the entire tapping term to get the layer switch, slowing me down. So I am also avoiding it, although I would be using it religiously if it worked well. To reiterate, the behaviour I would like to work is: press dual-function layer switch, press key on target layer, release dual-function layer switch, all within tapping term.
Edit: while I still think it'd be good to have the above behaviour be possible, it's not going to work for my use case since after thinking carefully about it (I can't experiment with it because it does not work!), I would tend to roll from my space/MO key to another key on the layer very quickly and it would result in a lot of typos.
As well, there's an issue if I reduce the tapping term low enough to reliably trigger a layer switch before releasing the dual function MO key, that rolling ONTO the dual function MO key prevents retro tapping from working correctly (a low tapping term also makes tap-hold key repeat unusable).
A low tapping term also makes a dual-function key such as shifted punctuation " on tap, Shift on hold, unable to type " due to some bug/odd behaviour with shifted punctuation dual function keys.
In all, this has been deeply confusing lol. It turns out I probably don't want what I thought I wanted, but it'd still be nice for it to be possible anyway so I can put MO hold on keys I don't frequently roll from, not just modifier hold.
Sad to see that this thread went stale. I'm looking for the same feature.
I will forever be confused, but I think I ended up getting the behaviour I wanted with the following combination of options in oyrx. my layout: https://configure.zsa.io/ergodox-ez/layouts/MzODX/b3E9p/0
For example, if I press Enter/MO(2), then press a second key which is bound on layer 2, then as soon as I press the second key, it sends the layer 2 key. So this completely does not depend on when I release Enter/MO(2).
I think the first 3 settings are relevant. I don't recall if Tapping force hold is relevant.
I would try the most recent firmware available through oryx (recompile your layout) and see if it does what you want.
@orogenic I finally had time to sit down and mess around with my layout and I can confirm that this does work and that tapping force isn't needed. Thanks for figuring this out! I'll have to mess with this a bit more now :D My thumbs can hopefully move even less!
This is the situation: I have Moonlander keyboard, one of the thumb key is configured as: tap: TO(0) hold: MO(4) So tapping this button goes to base layer, but holding it activates layer 4 for as long at it is hold and then goes back to whichever layer was active (0, 1, 2, 3).
Now imagine you are in layer 2 and you want to press one key from layer 4. So you hold down the thumb key plus the key you need from layer 4, then release both and you are back in layer 2. So far so good. But if you do this action too quickly (hold, press, release all within tapping term) what happens instead is that you will activate TO(0) and press key from base layer instead. Unfortunately this is very common and happens all the time to me.
It seems like permissive hold should solve this: Permissive hold If you press and release a dual-function key (e.g, Shift when held, A when tapped) and a regular key (e.g, "x") within the tapping term period, normally it would send just the tapped keys ("ax"). Enable this to ensure it sends the hold version (a shifted "x" keystroke in this case).
However it doesn't seem to work, is it because permissive hold doesn't affect MO? If so I suggest this as a feature that would be very appreciated 🥰