Bug: dynamic-macro-play is not repeatable if outside base layer
Requirements
- [X] I've searched issues to see if this has not been reported before.
Describe the bug
When tapping dynamic-macro-play on a layer-while-hold layer multiple times, it will replay the marco only once then the key from the base layer will be outputted.
Relevant kanata config
(defcfg
sequence-timeout 3000
process-unmapped-keys yes
dynamic-macro-max-presses 20
)
(defsrc
1 2 3 4 5 6 7 8 9 0
a b c
spc
)
(deflayer base
1 2 3 4 5 6 7 8 9 (dynamic-macro-play 1)
a b c
(layer-toggle dyn)
)
(deflayer dyn
(dynamic-macro-play 1) 2 3 4 lrld dynamic-macro-record-stop (dynamic-macro-record 1) 8 9 0
a b c
_
)
To Reproduce
- press space + 7 to record macro abc
- press space + 6 to save macro
- press
000to getabcabcabc - press space + 111 to get
abc11
Expected behavior
- press space + 111 to get
abcabcabc
Kanata version
1.5.nighly
Debug logs
No response
Operating system
windows 10 Intercepetion
Additional context
No response
Ah I see, the issue is not being outside the base layer, but rather being in a toggle / while-held layer.
I guess the issue is that kanata always releases all pressed keys as part of a macro, which includes the key that's activating the layer.
https://github.com/jtroo/kanata/blob/ae855e7d4955acebb8471c5619b7f188b3289947/src/kanata/dynamic_macro.rs#L44
The motivation for doing this is as a safety mechanism to prevent kanata from keeping a key held pressed that the user doesn't know is held. E.g. if in step 2 of the steps to reproduce, the user does something like:
- hold space for the layer
- hold 4, which types a new key
- press 6 to save the macro
Without the release, the recorded macro will have a press of 4 without a release, and the 4 key will remain pressed unbeknownst to the user, until they press+release the key themselves.
Maybe we don't need this mechanism though, and should trust the user to not record such a macro? Though maybe other things will break if this code is removed.
Ah, reading through the context here: https://github.com/jtroo/kanata/issues/300 , it seems that the tradeoff is that, if the macro play button is on the base layer but record/stop is on a while-held layer, without releasing active keys at the end of the macro, the behaviour is wrong because playing the macro will put the user on the while-held layer.
Maybe with some more complicated customization of dynamic macro this could be resolvable, e.g. allow user to customize precisely which keys to release, but maybe for now documenting the issue is enough.
At the time of #300 though, #365 that fixes #359 had not yet been implemented.
One not fully-fleshed out idea:
- add a stop option that does not release pressed keys and also mandates a truncation number
This should hopefully enable the use case of starting+stopping+replaying on a while-held layer, and not break existing users.
I'm not sure the original reason to have truncation still exists. I have record start and stop on the same layer-while-hold and can't see a differece wether I use truncation-1 or not.
another observation: Hold Layer1: start record Release Layer1 ... Hold Layer1: stop record
I can now put the PLAY button on Layer1 or the base layer and in will work (meaning it will do the Layer1 to base transition at the start of the macro!!!
Also putting the the PLAY button on Layer2 will now not work because it picks keys from Layer2 instead of base.
IDEA: we have a play button that
- has a release Everything before you start option, (to get out of any layers)
- has a replay currenty hold keys option (to get back into the current layer if the key is still held)
I have record start and stop on the same layer-while-hold and can't see a differece wether I use truncation-1 or not.
Truncation of 1 is might just be releasing some key release. I could imagine a truncation number needing to be larger if, for example, someone uses a defseq to start/stop macros.
IDEA: we have a play button that
- has a release Everything before you start option, (to get out of any layers)
- has a replay currenty hold keys option (to get back into the current layer if the key is still held)
Conceptually this might work. Implementation-wise it might be need some wrangling to do the replaying of held keys.