evremap icon indicating copy to clipboard operation
evremap copied to clipboard

Combos also press the individual keys

Open cgoates opened this issue 2 years ago • 3 comments

Hello, your code here looks right up the alley of what I'm looking for, but I've noticed some unexpected behavior as I'm trying it out, wondering if I'm just doing something wrong. Here's my config (minus the device name):

[[remap]]
input=["KEY_A", "KEY_S"]
output = ["KEY_N"]

Every time I hit the combo, I get not only an n, but also an s or an a. I was expecting/hoping to just get the n. Is this an expected behavior? If so, I might take the time to dig in and see if I can resolve that at least for my own use, and I'm happy to submit a PR for it if you would like.

cgoates avatar Apr 24 '22 02:04 cgoates

I wouldn't expect it to work like that, but it wouldn't surprise me if it has been doing that all along, as my use cases always involve the main key and a modifier key, and it is typically harmless if the modifier continues to be reported.

I don't have a ton of bandwidth to investigate this, so I would value your effort to figure out what's going on and perhaps resolve it!

wez avatar Apr 25 '22 14:04 wez

~I'm experiencing a similar issue~ While doing further research, it turned out that my issue is unrelated. Keeping this for historic purposes.

[[dual_role]]
input = "KEY_CAPSLOCK"
hold = ["KEY_RIGHTMETA"]
tap = ["KEY_ESC"]

[[remap]]
input = ["KEY_LEFTMETA", "KEY_I"]
output = ["KEY_UP"]
[[remap]]
input = ["KEY_LEFTMETA", "KEY_J"]
output = ["KEY_LEFT"]
[[remap]]
input = ["KEY_LEFTMETA", "KEY_K"]
output = ["KEY_DOWN"]
[[remap]]
input = ["KEY_LEFTMETA", "KEY_L"]
output = ["KEY_RIGHT"]

When performing the following sequence:

  • press META
  • press J
  • press L
  • release J
  • release L
  • release META

...the following inputs are generated by evremap:

  • LEFT
  • L (exactly when J is released)
  • RIGHT

and3rson avatar Jul 01 '23 21:07 and3rson

Seems like the issue might be due to evremap releasing the modifier (META) once J is pressed. I've added some logs to debug this, here's the output of my previous key sequence:

 2023-07-02T01:13:12.439 ERROR evremap::remapper > Press [KEY_RIGHTMETA]
 2023-07-02T01:13:12.520 ERROR evremap::remapper > Press [KEY_LEFT]
 2023-07-02T01:13:12.520 ERROR evremap::remapper > Release [KEY_RIGHTMETA]
 2023-07-02T01:13:12.571 ERROR evremap::remapper > Press [KEY_L]
 2023-07-02T01:13:12.614 ERROR evremap::remapper > Press [KEY_RIGHT]
 2023-07-02T01:13:12.614 ERROR evremap::remapper > Release [KEY_LEFT, KEY_L]
 2023-07-02T01:13:12.657 ERROR evremap::remapper > Press [KEY_RIGHTMETA]
 2023-07-02T01:13:12.657 ERROR evremap::remapper > Release [KEY_RIGHT]
 2023-07-02T01:13:12.723 ERROR evremap::remapper > Release [KEY_RIGHTMETA]

Here's the logs of me pressing META+J alone:

 2023-07-02T01:14:21.745 ERROR evremap > Short delay: release any keys now!
 2023-07-02T01:14:24.121 ERROR evremap::remapper > Going into read loop
 2023-07-02T01:14:24.863 ERROR evremap::remapper > Press [KEY_RIGHTMETA]
 2023-07-02T01:14:25.092 ERROR evremap::remapper > Press [KEY_LEFT]
 2023-07-02T01:14:25.092 ERROR evremap::remapper > Release [KEY_RIGHTMETA] <---- fake release
 2023-07-02T01:14:25.252 ERROR evremap::remapper > Press [KEY_RIGHTMETA]   <---- followed by a press again 
 2023-07-02T01:14:25.252 ERROR evremap::remapper > Release [KEY_LEFT]
 2023-07-02T01:14:25.580 ERROR evremap::remapper > Release [KEY_RIGHTMETA]

This also happens when I use a single-role modifier, e. g. CTRL or LEFTMETA.

EDIT: When I press META+J, desired_keys becomes empty. I think this is what causes evremap to release the modifier. Inside compute_keys, keys still contain META & J during first phase, however they are removed during second phase. This seems like a tricky situation, since:

  • It makes sense for evremap to release META during substitution (to properly generate LEFT instead of META+LEFT), however evremap needs to remember that META was pressed in order to generate proper remap for a second press while first press has not been released yet.
  • It seems like evremap sees META, J, & L pressed all together, and it substitutes META+J from the list, thus treating L as pressed without a modifier. This means evremap will probably need to differentiate between modifiers and non-modifier keys.

EDIT 2: I was able to resolve my issue with the following patch:

diff --git a/src/remapper.rs b/src/remapper.rs
index 0e90697..2965184 100644
--- a/src/remapper.rs
+++ b/src/remapper.rs
@@ -164,13 +164,17 @@ impl InputMapper {
                 if input.is_subset(&keys_minus_remapped) {
                     for i in input {
                         keys.remove(i);
-                        keys_minus_remapped.remove(i);
+                        if !is_modifier(i) {
+                            keys_minus_remapped.remove(i);
+                        }
                     }
                     for o in output {
                         keys.insert(o.clone());
                         // Outputs that apply are not visible as
                         // inputs for later remap rules
-                        keys_minus_remapped.remove(o);
+                        if !is_modifier(o) {
+                            keys_minus_remapped.remove(o);
+                        }
                     }
                 }
             }

Not sure if there are any side effects to this, but this made my life much easier! The idea here is to allow modifier keys to be reused for multiple remaps, e. g. when keys that are pressed trigger multiple remaps with shared key, e. g. META+J+K -> META+J and META+K. Let me know what you think.

and3rson avatar Jul 01 '23 22:07 and3rson