pynput
pynput copied to clipboard
Is it possible to create 2 separate Threads for on_press and on_release events alongside the Main thread?
Hi! I'm trying to translate keyboard keys to joystick movements on an emulator screen (BlueStacks) on my Mac Catalina.
What I'm trying to achieve is to keep the movement until the key is released so I decided to create a loop to repeat the movement until the key is released. However, the loop is blocking the Thread so I can't accomplish that easily. I tried then to create 2 Threads, 1 for on_press
events and another for on_release
events but that don't work either since I always get AttributeError
s from the objc
for any key I press.
Part of my code:
CURRENT_STATE = 'released'
DELAY = 0.25
def on_press(key):
try:
global CURRENT_STATE
CURRENT_STATE = 'pressing'
X, Y = INITIAL['X'], INITIAL['Y']
if key == Key.shift:
print('UP')
X, Y = MOVES['UP']
elif key == Key.ctrl:
print('LEFT')
X, Y = MOVES['LEFT']
elif key == Key.alt:
print('DOWN')
X, Y = MOVES['DOWN']
elif key == Key.cmd:
print('RIGHT')
X, Y = MOVES['RIGHT']
if key in VALID_KEYS:
while CURRENT_STATE == 'pressing':
device.input_swipe(INITIAL['X'], INITIAL['Y'], X, Y, DELAY * 1000)
time.sleep(DELAY)
except Exception as err:
print(err)
def on_release(key):
if key in VALID_KEYS:
global CURRENT_STATE
CURRENT_STATE = 'released'
print('released')
elif key == Key.cmd_r:
# Stop listener
return False
def main():
press_listener = Listener(on_press=on_press)
press_listener.start()
release_listener = Listener(on_release=on_release)
release_listener.start()
while True:
continue
main()
Thanks for any help and directions =)
Disclaimer: I tried to use pyinput
for mouse events but I couldn't make it work on my Mac, even allowing my terminal and IDE on Accessibility (couldn't auth Python) and running with sudo
so I'm using ADB.
Have you considered creating a thread responsible for sending device events (device.input_swipe
) that reads a global state, like:
class State(enum.Enum):
IDLE = 0
MOVE_DOWN = 1
# ...
QUIT = N
and then just update the global state from the callback? The thread body would be a simple while STATE != State.Quit
-loop.
And your problems with mouse events seem strange, since keyboard events require even more privileges. Do you have a stack trace or other information? Or do you simply not receive any events?
Thanks for the reply! I will soon try again to use pyinput
and I will try out your approach and post the feedback here.
I don't have any stack trace, no events were coming indeed so I believe Mac was swallowing them.
To investigate the missing events, you might want to add some debug logging here.