mooz / xkeysnail

Yet another keyboard remapping tool for X environment
890 stars 112 forks source link

Long press trigger key of multiple stroke keys #163

Closed Ynjxsjmh closed 2 years ago

Ynjxsjmh commented 2 years ago
import re
from xkeysnail.transform import *

# define timeout for multipurpose_modmap
define_timeout(1)

define_keymap(None, {
    K('SEMICOLON'): {
        K('q'): Key.KEY_0,
        K('w'): Key.KEY_1,
        K('e'): Key.KEY_2,
        K('r'): Key.KEY_3,
        K('t'): Key.KEY_4,
    },
})

When I long press ; then type qwert in sequence, I expect the out to be 01234 but the real out is 0wert.

xkeysnail version is v0.4.0 OS: Arch Linux x86_64 Kernel: 5.18.3-arch1-1

joshgoebel commented 2 years ago

Does this work if you use a real modifier key as opposed to semicolon?

Ynjxsjmh commented 2 years ago
import re
from xkeysnail.transform import *

# define timeout for multipurpose_modmap
define_timeout(1)

define_modmap({
    K('k'): K('Shift-KEY_5'),      # doesn't work
    K("M-Shift-comma"): Key.KEY_9, # doesn't work

    K('RShift-RC-z'): Key.KEY_0,   # doesn't work, also not work for RC-RShift
    K('RShift-RC-x'): Key.KEY_1,   # doesn't work
    K('RShift-RC-c'): Key.KEY_2,   # doesn't work
    K('RShift-RC-v'): Key.KEY_3,   # doesn't work
    K('RShift-RC-b'): Key.KEY_4,   # doesn't work

    Key.LEFT_META: Key.LEFT_CTRL,  # work
    Key.LEFT_CTRL: Key.LEFT_META,  # work
})

define_keymap(None, {
    K('SEMICOLON'): {
        K('q'): Key.KEY_0,   # work
        K('w'): Key.KEY_1,   # work
        K('e'): Key.KEY_2,   # work
        K('r'): Key.KEY_3,   # work
        K('t'): Key.KEY_4,   # work
    },
})

I'm not sure what's happening, when I write this test.py and run it as sudo xkeysnail test.py, even the simplest K('k'): K('Shift-KEY_5') doesn't work.

But the rule Key.LEFT_META: Key.LEFT_CTRL, works and it works when I long press Key.LEFT_META.

joshgoebel commented 2 years ago

A modmap can only be used to remap individual keys. You cannot use K.

joshgoebel commented 2 years ago

To do this you would likely first need to conditionally modmap ; to an actual modifier. And then you probably want five individual keymap entries, not a nested keymap.

Ynjxsjmh commented 2 years ago

Thanks, but I don't quite understand the meaning of individual keys, from README, it says key specification in a keymap is in a form of K("(<Modifier>-)*<Key>"), where * I guess is the same as it in regex, could you elaborate it more?

I have tried to use something like K('RShift-RC-z'): Key.KEY_0, but it doesn't work. From the output of sudo xkeysnail test.py, I'm sure I input the right key.

joshgoebel commented 2 years ago

it says key specification in a keymap

Yes, you use K in keymap, but NOT in a modmap... in a modmap you use the Key.NAME enums only...

Ynjxsjmh commented 2 years ago

in a modmap you use the Key.NAME enums only

This is clear, don't know why there is only define_keymap definition in README.

With your suggestion, I write the following config and it works fine when I long press the semicolon

define_multipurpose_modmap(
    {Key.SEMICOLON: [Key.SEMICOLON, Key.RIGHT_CTRL]},
)

define_keymap(None, {
    K('RC-q'): Key.KEY_0,
    K('RC-w'): Key.KEY_1,
    K('RC-e'): Key.KEY_2,
})

My real purpose is to remap numbers to left hand area of my keyboard for quicker input. Since I use Emacs as my editor so using control or alt as leader key might cause conflict thus overrides the default keybinding.

To overcome this, I has some idea like

  1. Make Emacs doesn't respond right ctrl
  2. Use combination modifiers like Shift-Control-Alt, but I think this is not an individual key.

Do you have some other idea?

joshgoebel commented 2 years ago

I write the following config and it works fine

Yep, looks reasonable to me.

Make Emacs doesn't respond right ctrl

My fork keyszer allows you to define custom modifiers... so you could choose a key you're never going to use, declare it a REAL modifier and then multi-modmap semicolon to that... then keymap your custom modifier... without "cutting in" on any of your real modifiers...

I do this myself to create a Hyper key for all my Window Manager stuff:

https://github.com/joshgoebel/keyszer/wiki/Hyper

Then I modmap capslock to Hyper/F24 since I have no real F24 key.

joshgoebel commented 2 years ago

I also multi-map my pipe key to Hyper (for the right hand side), but it's still a bit buggy - haven't found the time to track it down yet.

Ynjxsjmh commented 2 years ago

My fork keyszer allows you to define custom modifiers

Thanks for your recommendation, I find there can be improvement in README

adds Meta, CommandandCmd` aliases for Super/Meta modifier

(Miss a grave)

multipurpose - The number of seconds before a held multi-purpose key is assumed to be a modifier (evne in the absence of other keys).

(Spell wrong)

For a sample systemd service file for running Keyszer as a service please see keyszer.service.

(No service file)

ACL based permissions (narrow, more secure)

...or do it by copypasting these lines into a shell

(After doing all these stuff, when I run keyszer in the shell, it says (EE) Failed to open uinput in write mode. Please check access permissions for /dev/uinput.). I try to change the owner and group of keyszer with chmod keymapper:keymapper /path/to/keyszer then run keyszer again but still get the same error. I think the guide in this section lacks some steps.

joshgoebel commented 2 years ago

Please open an issue against my repo if you'd like support. Thanks.

PR for the typos would be great.