boppreh / keyboard

Hook and simulate global keyboard events on Windows and Linux.
MIT License
3.8k stars 433 forks source link

suppress=True isn't honored by some hotkeys #220

Open jayquonmarton opened 6 years ago

jayquonmarton commented 6 years ago
keyboard.add_hotkey('capslock', lambda: foo(), suppress=True)
keyboard.wait()

Now if you press capslock, the capslock is set.

Expected behavior is that it is not set.

win 7 64bit. master branch


You may want to look at how autohotkey implements their hotkeys in windows. They seem to have implemented it well enough that it is accurate in expected behavior, though I don't know how complex it is. That includes suppressing caplocks. There are a couple forks of autohotkey, but https://github.com/HotKeyIt/ahkdll is one.

thiskurt commented 4 years ago

Hey,

I ran into the same problem where if I used capslock in a hotkey remapping it would work, but it wouldn't suppress capslock so I'd end up in ALL CAPS after using hotkeys like that.

I found a quick solution to the issue by setting a flag that marks when capslock was pressed during a hotkey and then whenever capslock is released checking if it was pressed in a hotkey or not.

If it was last pressed in a hotkey, I just press capslock again to undo the incorrect capslock state and reset the flag.

It's not very fancy, but it works, plus I use it on windows, but on linux and mac it should be usable too, there's not key suppression there at all, I believe.

In case anyone can use it or if it's useful in fixing the bug, here's what I did:

import keyboard

caps_hot = False    # Keep track of whether capslock was pressed as part of a hotkey
remaps = {
    "capslock+i": "up",
    "capslock+k": "down"
}

def main():
    for key, value in remaps.items():
        keyboard.remap_hotkey(key, value)
        if key.__contains__('capslock'):
            keyboard.add_hotkey(key, make_caps_hot)     # Set caps_hot flag

    keyboard.on_release_key('capslock', release_caps)   # Undo capslock after hot key

    keyboard.wait()

def make_caps_hot():
    """Set flag showing capslock was pressed as part of a hotkey"""
    global caps_hot; caps_hot = True

def release_caps(e=None):
    """On releasing capslock check if it was pressed as part of a hotkey. If so: press capslock & reset flag"""
    global caps_hot
    if caps_hot:
        keyboard.send('capslock')
        caps_hot = False

if __name__ == "__main__":
    main()