houmain / keymapper

A cross-platform context-aware key remapper.
GNU General Public License v3.0
257 stars 21 forks source link

timing issues on group keypress #121

Closed kbilsted closed 2 months ago

kbilsted commented 3 months ago

Hi I really like the simplicity of keymapper and have spent a lot of time remapping stuff around. I'm facing some issues with chording timing on windows 11 using the latest release.

I want to shortcut enter by pressing two keys. The doc told me to do (J K ) >> Enter unfortunately it forces me to type very slowly when e.g. spelling the name "kjeld".

I then tried

(J K ){!110ms} >> Enter

where I across keyboards see the same pattern

If I change the configuration to

(K J ){!110ms} >> Enter

I observe the opposite. Now I cannot trigger it using K->J but I can do it with J->K

When I Instead use a more verbose syntax

K !160ms J >> Enter
J !160ms K >> Enter

it seems to work differently and a bit better. Now I'm able to trigger with both keys simultaneously and k->j.. but not j->k only if i press j release j press k it triggers.

Another difference I observe is a delay to the screen when typing j and k on their own.. but that I'm sure is not a problem once you get used to it.

houmain commented 3 months ago

I already noticed that timings after groups do not work correctly and will try to fix it soon. You can also try this configuration. This should prevent triggering it accidentally while typing:

J{K !K} >> Enter
K{J !J} >> Enter
kbilsted commented 3 months ago

Thanks for a quick reply! What does J{K !K} >> Enter Mean?

I read it as j followed by k and not another k after that? Why is this helping me?;)

anyways I tried your suggestion and it was almost impossible for me to trigger anything.

houmain commented 3 months ago

J{K !K} means that K needs to be pressed and released while J is hold. Maybe a group timeout is really what you need but this usecase reminded me of this discussion.

ristomatti commented 3 months ago

@kbilsted Have you tried this:

J{K} >> Enter
K{J} >> Enter

For me this works reliably to trigger enter. It breaks key repeat though. I was able to get key repeat working for J with this config:

J !50ms J >> J
J{K}      >> Enter
# K !50ms K >> K
K{J}      >> Enter

Curiously if I include the commented out line, I can't anymore get enter to trigger reliably without either j or k being included in the output.

Edit: While the first config works reliably, it seems like a bad idea for anything that uses Vim-bindings. The idea is interesting though. I've now been using a US ANSI keyboard for 3.5 months (after >30 years of ISO Nordic) and I still fail to hit Enter at times. I'm going to see if this trick would work for me, but with this instead:

J{F} >> Enter
F{J} >> Enter
kbilsted commented 3 months ago

@ristomatti I'm not sure where from i got the idea. But I think I will really enjoy it. I also tinker with the idea that it should map to ";" ENTER instead. Since I do a lot of that combination ;) The current setup right now

ristomatti commented 3 months ago

@kbilsted Might want to make it >> End ';' Enter, so that you can also use it to complete a line regardles of the location. But note that there might be such a feature in your editor already. WebStorm/IDEA does:

image

houmain commented 3 months ago

Groups with timeouts like (J K ){!110ms} >> Enter should work in the 4.0.0 release.

kbilsted commented 3 months ago

Thanks for the new release! Really appreciate all your work

Using v4.0.0 on windows

using (J K ){!110ms} >> Enter i experience some weird stuff

houmain commented 3 months ago

Currently it should trigger when both keys are pressed and then one of them is released within 110ms.

Maybe you are more after something like the following:

J !50ms K >> Enter
K !50ms J >> Enter
kbilsted commented 3 months ago

I'll try.. but for now the original behaviour is irradic

ristomatti commented 3 months ago

These both ways seem to work reliably for me on v4.0.0:

NoModifier = !ControlLeft !ControlRight !MetaLeft !MetaRight !AltLeft !AltRight !ShiftLeft !ShiftRight

[default]
  J{F}      >> Enter
  F{J}      >> Enter

# I have this "FJ"-experiment on top of my config, so this NoModifier trick
# was required to avoid breaking mappings later on in the config.
[modifier="NoModifier"]
  J !75ms F >> Enter
  F !75ms J >> Enter
kbilsted commented 3 months ago

Thanks. Will try out soon. I REALLY like these sort of combos over going to another layer

kbilsted commented 3 months ago

awesome idea with the NoModifier should go to the readme

ristomatti commented 3 months ago

@kbilsted Here's a few more utility aliases:

# Exact modifiers
_Meta           = !ControlLeft !ControlRight           !MetaRight !AltLeft !AltGr MetaLeft
_MetaRight      = !ControlLeft !ControlRight !MetaLeft            !AltLeft !AltGr MetaRight
_Alt            = !ControlLeft !ControlRight !MetaLeft !MetaRight          !AltGr AltLeft
_AltGr          = !ControlLeft !ControlRight !MetaLeft !MetaRight !AltLeft        AltGr
_Control        =              !ControlRight !MetaLeft !MetaRight !AltLeft !AltGr ControlLeft
_ControlRight   = !ControlLeft               !MetaLeft !MetaRight !AltLeft !AltGr ControlRight
_Shift          = !ControlLeft !ControlRight !MetaLeft !MetaRight !AltLeft !AltGr ShiftLeft
_ShiftRight     = !ControlLeft !ControlRight !MetaLeft !MetaRight !AltLeft !AltGr ShiftRight

# Modifier groups
EitherControl   = ControlLeft | ControlRight
EitherAlt       = AltLeft | AltGr
EitherMeta      = MetaLeft | MetaRight
EitherShift     = ShiftLeft | ShiftRight

Modifier        = ControlLeft | ControlRight | MetaLeft | MetaRight | AltLeft | AltRight | ShiftLeft | ShiftRight
NoModifier      = !ControlLeft !ControlRight !MetaLeft !MetaRight !AltLeft !AltRight !ShiftLeft !ShiftRight

# Key groups
MouseButton     = ButtonLeft | ButtonRight | ButtonMiddle | ButtonBack | ButtonForward
Digit           = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Letter          = A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z
FunctionKey     = F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12

# Function key symbols on Keychron keyboards
FnRewind        = F7
FnPlayPause     = F8
FnFastForward   = F9
FnMute          = F10
FnVolumeDown    = F11
FnVolumeUp      = F12

# Directional navigation
KeyUp           = I
KeyLeft         = J
KeyDown         = K
KeyRight        = L
Direction       = KeyUp | KeyLeft | KeyDown | KeyRight

Exact modifiers are to prevent the mapped keys from affecting the output. For example if I map AltGr{T} >> Control{T} on Chrome, it won't work as Chrome will actually receive AltGr{Control{T}}.

The Fn* aliases are used to map directly to equivalent media keys on specific apps.

Directional aliases I've used for example to map Escape !200ms Direction >> (Control Alt){Direction} on WebStorm. I've then configured the Control+Alt+IJKL keys to pane navigation within WebStorm as it cannot handle Escape in it's keymaps.

kbilsted commented 3 months ago

If its ok with you ill grab these for my keyboard github https://github.com/kbilsted/KeyboardLayoutGalore . all contributions welcome. I still need to learn a lot like how to properly do alt-tab... and alt-tab-hold-alt ... but then again i just learned about windowd+ which is amazing when you toggle a lot.

ristomatti commented 3 months ago

Go right ahead. I'm been planning on posting some of my keeper config hacks here https://github.com/houmain/keymapper/discussions/categories/show-and-tell but I never seem to find time (even though I seem to have infinite amount of time with Keymapper and other OS tweaking). :grin:

I did update my keymapper.conf gist just now though.

kbilsted commented 2 months ago

@ristomatti thanks i just got bit by not having the [modifier="NoModifier"] enabled

do you use [default] to go back to "normal"

ristomatti commented 2 months ago

Yup.. Or any other context block.

ristomatti commented 2 months ago

I wonder if it would be practical to step debug through the code. With a lot of googling and handhelding from JetBrains CLion IDE I might even be able to set it up. At least I've managed to setup on-chip step debugging for some Arduino C++ in the past (pretty much automated by PlatformIO). :thinking:

I'm not exactly sure how it could help but it might still be an interesting experiment. Keymapper's source looks completely foreign to a measly CRUD developer like myself. :grin:

kbilsted commented 2 months ago

I agree there should be a logging commandline parameter - in .net you can specify logging on different levels so verbosity and where in the code are two different dimensions of configuring the logging. That way you can say e.g. VERBOSE logging.. but only in the ConfigurationEvaluator

but notice that logging may encur time differences that may make debugging difficult especially here where we keypress simultanously.

ristomatti commented 2 months ago

Yep surely adding verbose logging would be the most practical approach (behind a build flag not to affect performance). It'd clutter the codebase though so I can imagine why it's not there.

kbilsted commented 2 months ago

yes it could be built as 2 different exe files so both were in the release zip.