boppreh / keyboard

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

Capture the activation of a hotkey while other keys are being pressed #624

Open mriot opened 9 months ago

mriot commented 9 months ago

Hello, I am trying to register a hotkey like shift+1 that should be suppressed even when other keys are pressed. As stated here it's by design, that any additional keys that are being pressed at the same time will not trigger the add_hotkey callback. Which means that shift+1+k will not activate.

I've been trying to get this working for hours now and didn't find a solution. I tried to focus on hook and is_pressed. Here are two examples:

  1. keyboard.hook (and related) with suppress=True and returning either True or False in the callback. This does only work if you hold down the keys. The initial keypress e.g. shift+1 will still pass.

  2. keyboard.is_pressed("shift+1") does register the hotkey flawlessly, however it appears there's no option to actually suppress the event?

Any idea is highly appreciated!

mriot commented 9 months ago

Here's some semi-pseudocode that worked for me. Basically adding all currently pressed keys to a set on key_down event and removing it from the set on key_up. Then check if your keybind is among the pressed keys.

keybind = set() # I converted the keybind I want to block to a set of scan codes
pressed_keys = set()

def on_key_event(event):
    if event.event_type == "down":
        pressed_keys.add(event.scan_code) # add key to active keys
    elif event.event_type == "up":
        pressed_keys.discard(event.scan_code) # remove key from active keys
        return True

    # block our hotkey regardless of any additional keys
    if keybind.issubset(pressed_keys): # if keybind is among pressed keys
        print("keybind blocked")
        return False

    return True

keyboard.hook(on_key_event, suppress=True)