jtroo / kanata

Improve keyboard comfort and usability with advanced customization
GNU Lesser General Public License v3.0
3.19k stars 131 forks source link

Bug: dynamic-macro-play is not repeatable if outside base layer #702

Open gerhard-h opened 10 months ago

gerhard-h commented 10 months ago

Requirements

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

  1. press space + 7 to record macro abc
  2. press space + 6 to save macro
  3. press 000 to get abcabcabc
  4. press space + 111 to get abc11

Expected behavior

  1. press space + 111 to get abcabcabc

Kanata version

1.5.nighly

Debug logs

No response

Operating system

windows 10 Intercepetion

Additional context

No response

jtroo commented 10 months ago

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:

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.

jtroo commented 10 months ago

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.

jtroo commented 10 months ago

At the time of #300 though, #365 that fixes #359 had not yet been implemented.

One not fully-fleshed out idea:

This should hopefully enable the use case of starting+stopping+replaying on a while-held layer, and not break existing users.

gerhard-h commented 10 months ago

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

jtroo commented 10 months ago

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.