Search code examples
pythonpython-3.xpynput

Squelching keyboard input when modifier is held down with pynput on Windows


I have a simple script that looks for certain key combinations. When they are found it writes them to a file. I am using ` as the modifier. For example, if I do `+x then "x" will be written to the file.

My problem is that the keyboard input is also sent to whatever window is active. I don't want that. I just want the input to be sent to the file when ` is being held down. Is there a way to do that?

Edit: I would also be fine with redirecting the keyboard strokes to a particular window, like Notepad open in the background, if that would be easier.

Here is the script. It's using Python3 on Windows.

import os

from pynput import keyboard

def main():
    filename = "log.txt"

    # The key combination to check
    COMBINATIONS = [
        # Alpha characters
        {keyboard.KeyCode(char="`"), keyboard.KeyCode(char='x')},
        {keyboard.KeyCode(char="`"), keyboard.KeyCode(char='X')}
    ]

    current = set()

    def execute(combo):
        command = []
        for item in combo:
            try:
                print(item.char)
                command.append(item.char)
            except AttributeError as e:
                print(item.name)
                command.append(item.name)
        command = [c for c in command if c != "`"]
        command = " ".join(sorted(command))
        print(command)

        fo = open(filename, "a+")
        fo.write("{}\n".format(command))

    def on_press(key):
        if any([key in COMBO for COMBO in COMBINATIONS]):
            current.add(key)
            if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
                print((k in current for k in COMBO) for COMBO in COMBINATIONS)
                execute(current)

    def on_release(key):
        if any([key in COMBO for COMBO in COMBINATIONS]):
            current.remove(key)

    with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()

if __name__ == "__main__":
    main()

Solution

  • OK, so I wasn't able to find a way to do this using Python. I"m sure it's possible but I couldn't figure it out! Anyway, the computer is running Windows so I decided to do it with AutoHotkey. That was trivial to do and worked like a charm.

    Edit: Here is the example AHK script. I know this answer doesn't really belong in the Python section, but hopefully it will help anybody who finds this through Google :)

    I decided to go with a toggle key that will capture all keyboard input when it is pressed. When the toggle key is pressed again the script is suspended and all commands go to whichever window is active.

    #NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
    ; #Warn  ; Enable warnings to assist with detecting common errors.
    SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
    
    SetWorkingDir C:\ahkscripts
    
    ; Use capslock as a toggle key
    capslock::
        Suspend
    return
    
    ; write "1" to a file. FileAppend will create the file if it doesn't exist
    1::
        FileAppend, `n1, *myoutputfile.txt, 
    return
    
    
    
    ; write alt+1 to a file
    !1::
        FileAppend, `naltleft 1, *myoutputfile.txt, 
    return
    
    
    ; write shift+1 to a file
    
    +1::
        FileAppend, `nshiftleft 1, *myoutputfile.txt, 
    return