Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to create 2 separate Threads for on_press and on_release events alongside the Main thread? #327

Open
fabriciopirini opened this issue Dec 12, 2020 · 3 comments

Comments

@fabriciopirini
Copy link

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 AttributeErrors 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.

@moses-palmer
Copy link
Owner

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?

@fabriciopirini
Copy link
Author

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.

@moses-palmer
Copy link
Owner

To investigate the missing events, you might want to add some debug logging here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants