enigo icon indicating copy to clipboard operation
enigo copied to clipboard

Listen to User Events

Open shekohex opened this issue 7 years ago • 16 comments

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.

shekohex avatar Jul 10 '18 06:07 shekohex

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.

pythoneer avatar Jul 10 '18 14:07 pythoneer

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

jD91mZM2 avatar Jul 10 '18 15:07 jD91mZM2

@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?

pythoneer avatar Jul 10 '18 17:07 pythoneer

@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

jD91mZM2 avatar Jul 10 '18 17:07 jD91mZM2

@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?

pythoneer avatar Jul 10 '18 17:07 pythoneer

enigo.register_event(Key::ESC);
for event in enigo.events() {
    let event = event?;
    // do something with event
}

jD91mZM2 avatar Jul 10 '18 17:07 jD91mZM2

Ok, just like SDL etc..

pythoneer avatar Jul 10 '18 17:07 pythoneer

Just my idea, seems like the cleanest

jD91mZM2 avatar Jul 10 '18 17:07 jD91mZM2

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

pythoneer avatar Jul 10 '18 17:07 pythoneer

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.

  • inputBot works great but seems sometimes have some problem about toggling buttons.

shekohex avatar Jul 11 '18 02:07 shekohex

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.

jD91mZM2 avatar Jul 11 '18 05:07 jD91mZM2

There are two functions in Mac

  • InstallEventHandler (Carbon)
  • addGlobalMonitorForEventsMatchingMask (Cocoa)

Mac global hotkey in Swift (Carbon)

  • https://github.com/Clipy/Magnet

elbaro avatar Jun 14 '19 18:06 elbaro

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

bnau avatar Nov 10 '19 14:11 bnau

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

pythoneer avatar Nov 10 '19 14:11 pythoneer

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

bnau avatar Nov 10 '19 15:11 bnau

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.

Narsil avatar Feb 15 '20 10:02 Narsil