enigo-rs / enigo

Cross platform input simulation in Rust
MIT License
1.03k stars 102 forks source link

Listen to User Events #59

Open shekohex opened 6 years ago

shekohex commented 6 years ago

Hi, is there is a way to listen to user events. e.g Keyboard events or mouse clicks? currently i need to listen to some hotkeys e.g "Capslock" toggled so i can make some actions against it.

Thank you.

pythoneer commented 6 years ago

Currently there is no way to listen to events with enigo. We're thinking about it but don't expect this to happen anytime soon because this is a quite involved task to do cross platform and would possibly involve some async system (tokio-'core'?). I just don't have a clear vision about this topic currently.

jD91mZM2 commented 6 years ago

Seems to be possible on Linux X11 (not with libxdo sadly) to have an event loop, on windows it seems limited to hotkeys, which may be sent to either a window or a thread-local event queue. For mac, I have no idea

pythoneer commented 6 years ago

@jD91mZM2 how do you think this should be handled from the user perspective? having a register method the that takes a closure? and in the background we start a thread and run an event loop – or somehow try to use tokio stuff?

jD91mZM2 commented 6 years ago

@pythoneer Since most operating systems' APIs are blocking, I'd suggest we make it blocking as well, and if the user wants it concurrent use threads

pythoneer commented 6 years ago

@jD91mZM2 this sounds right for now. I was concerned about starting threads because i don't think the user expect that to happen and you don't just start threads out of nowhere. But how should a blocking API should look like for a use case where you want to "register" multiple events?

jD91mZM2 commented 6 years ago
enigo.register_event(Key::ESC);
for event in enigo.events() {
    let event = event?;
    // do something with event
}
pythoneer commented 6 years ago

Ok, just like SDL etc..

jD91mZM2 commented 6 years ago

Just my idea, seems like the cleanest

pythoneer commented 6 years ago

looks about right. I think the user can expect it to look like this coming from SDL, win32, or from any other input event handling background.

//EDIT:

I was just thinking about something like

enigo.register(Key::ESC, |evt| println!("escape pressed"));

but i think this is just to problematic

shekohex commented 6 years ago

after some googling, just found some good crates that maybe useful https://github.com/obv-mikhail/InputBot which i just tried and it works fine* and also https://github.com/autopilot-rs/autopilot-rs which seems interesting too, as it works with python too https://github.com/autopilot-rs/autopy

if we can have an API as @pythoneer proposed i think it will be good too. and as @jD91mZM2 mentioned about that making it blocking, that's not acceptable in some use cases. we can provide both, something like this:

// Call this to start listening for bound inputs.
handle_input_events();

// or async
handle_input_events_async();

anyway i'm ready to help, just make a new issue with a Check list, and we can make it together.

jD91mZM2 commented 6 years ago

mentioned about that making it blocking, that's not acceptable in some use cases. we can provide both, something like this:

The idea is that if the underlying api is blocking, then we should not use threads to make it not so. Especially not call it "async" if it's not actually async but rather using threads.

elbaro commented 5 years ago

There are two functions in Mac

Mac global hotkey in Swift (Carbon)

bnau commented 4 years ago

Is there a WIP on this topic? I'm ready to help too.

pythoneer commented 4 years ago

@bnau i think no one has actually started a serious effort in this direction as of now.

bnau commented 4 years ago

@pythoneer Okay, thx. I will fork the project and make a PR as soon as something is ready. Any idea/suggestion/contribution is welcome!

Narsil commented 4 years ago

I worked on something like this to see how we could do Cross platform rust.

https://github.com/Narsil/rdev

It's not compatible with Enigo because I stayed lower level (only raw keycodes for now) but it might be handy for ppl that want to include it in Enigo.

Main caveat, on MacOS you need to be a main app to be able to listen to events AND have enabled accessibility for Terminal or the name of the app. Cheers. Edit: I didn't do windows code because I don't have access to one right now.