How do I listen for keyboard input without a window using winit?

Hi, I am trying to listen for keyboard inputs without creating a window. Similar behavior to SetWindowsHookW and SetWindowsHookExW in Win32.

use winit::event_loop::{ControlFlow, EventLoop};

fn main() {
  let event_loop = EventLoop::new().unwrap();
  event_loop.set_control_flow(ControlFlow::Wait);
  event_loop.run(move |ev, wt| {
    // Here
  });
}

I think it can be done with any other crates too, if it's not possible using winit crate. I Appreciate any help on this.

1 Like

There is no cross-platform way to do this. (eg iOS, Android, Wayland and the web don't allow this to make spyware harder to implement.) And winit doesn't expose anything for this.

2 Likes

I know it's common for spyware to have a keylogger. But isn't it is more common for applications where they can listen for hotkey to start something?

For example, NVIDIA game bar.

1 Like

That is a use case. It is hard to distinguish between a keylogger and hotkeys though. For this reason outside of Windows and X11, platforms that support hotkeys in the first place require user permission to set a hotkey.

On macOS either the user itself needs to manually add the specific hotkey under system settings, the app needs to use RegisterEventHotKey from the deprecated Carbon api (probably almost certainly doesn't work in the app store sandbox and could go away at any time) or use NSEvent.addGlobalMonitorForEvents(matching:handler:) (which needs the accessibility permission).

For Wayland if your desktop environment supports it you can use the global shortcuts portal dbus interface which too requires the user to give permission. It seems currently KDE supports it, but Gnome doesn't yet.

2 Likes

I forgot to mention that cross-platform support is required, but it's not a priority in the near future. Windows should be prioritized over other platforms.

So, yeah I need cross-platform support. But for now, I need the solution for Windows.

Because I've been using Win32 for months in C++. I basically know how to use SetWindowsHook thing in Rust using any of the FFI crates, if and only if I understand Rust more than I know today.

I need a simpler solution. Because FFI crates involves unsafe Rust, which is beyond my current knowledge. And yes of course, I keep learning Rust, but it takes time to get there: unsafe Rust.

I've seen a lot of people ask more or less this question[1], and I haven't ever seen a response with a solution, though I haven't searched for one myself. So, I conclude that if you want a cross-platform API for global hotkeys — which would be a good library to have! — then you're going to have to write it.

Perhaps it can be a learning goal.


  1. mostly on Discord, not here ↩ī¸Ž

3 Likes

Yes, I think it can be a good learning goal.

I've personally had pretty decent results with device_query crate.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.