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

Keyboard input not captured on latest macOS 10.15.2 system #1470

Open
luojia65 opened this issue Feb 15, 2020 · 10 comments
Open

Keyboard input not captured on latest macOS 10.15.2 system #1470

luojia65 opened this issue Feb 15, 2020 · 10 comments
Labels
B - bug Dang, that shouldn't have happened C - needs investigation Issue must be confirmed and researched DS - macos H - help wanted Someone please save us

Comments

@luojia65
Copy link

luojia65 commented Feb 15, 2020

Hello! I recently updated my macOS Catalina to 10.15.2. When I try to write winit code like this:

fn main() {
    let event_loop = winit::event_loop::EventLoop::new();
    winit::window::WindowBuilder::new()
        .with_title("Hello world!")
        .with_inner_size(winit::dpi::LogicalSize::new(1024.0, 768.0))
        .build(&event_loop).unwrap();

    event_loop.run(|ev, _target, flow| match ev {
        winit::event::Event::WindowEvent { event, .. } => match event {
            winit::event::WindowEvent::CloseRequested => 
                *flow = winit::event_loop::ControlFlow::Exit,
            winit::event::WindowEvent::KeyboardInput {
                device_id, input: kin, is_synthetic: _
            } => {
                println!("WindowEvent Key: {:?} DeviceId: {:?}", kin, device_id);
            },
            _ => {},
        },
        winit::event::Event::DeviceEvent { event, device_id } => match event {
            winit::event::DeviceEvent::Key(kin) => {
                println!("DeviceEvent Key: {:?} DeviceId: {:?}", kin, device_id);
            },
            _ => {},
        },
        _ => {},
    });
}

When I run and press any keys, I expect to have an both WindowEvent and DeviceEvent in the output. However the output is like this:

WindowEvent Key: KeyboardInput { scancode: 23, state: Pressed, virtual_keycode: Some(Key5), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 23, state: Released, virtual_keycode: Some(Key5), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 22, state: Pressed, virtual_keycode: Some(Key6), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 22, state: Released, virtual_keycode: Some(Key6), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 28, state: Pressed, virtual_keycode: Some(Key8), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 28, state: Released, virtual_keycode: Some(Key8), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 25, state: Pressed, virtual_keycode: Some(Key9), modifiers: (empty) } DeviceId: DeviceId(DeviceId)
WindowEvent Key: KeyboardInput { scancode: 25, state: Released, virtual_keycode: Some(Key9), modifiers: (empty) } DeviceId: DeviceId(DeviceId)

There is no DeviceEvent in the output. Is this expected behavior to have WindowEvent only? Or is there something wrong with my code or operating system (permission or something)? Thanks!

My winit version is winit = "0.21.0".

(I have raised issue at glium/glium#1822 , but that could be an issue on winit)

@goddessfreya goddessfreya added DS - macos H - help wanted Someone please save us C - needs investigation Issue must be confirmed and researched B - bug Dang, that shouldn't have happened labels Feb 15, 2020
@sanbox-irl
Copy link

If I'm not mistaken, macOS does not send global key press events to applications via AppKit. The only device events the winit macOS backend emits are mouse/trackpad events.

We maybe could reliably do this though using this https://developer.apple.com/documentation/appkit/nsevent/1535472-addglobalmonitorforeventsmatchin?language=objc. Not sure it's a great idea though.

@sanbox-irl
Copy link

For now, simply getting the keyboard input (and remember to also get the modifier states, those will also be reported globally correctly from Device Events) will cover you more than enough unless you specifically are trying to log inputs to other windows, in which case first, don't think winit can support it yet

@sanbox-irl
Copy link

Sorry -- I just looked through the Documents more carefully. macOS will only send "Key-related events..if accessibility is enabled or if your application is trusted for accessibility access".

That could be a long term thing to support in the future, along with various other macOS accessibility options, but for now, I think this issue should be closed. We could simulate and send DeviceEvents when we can, but that would just be a footgun to programmers who may rely on it for.

Is there a reason you wanted to have both events report?

@luojia65
Copy link
Author

I may need to build cross-platform window applications, and do not expect underlying library behavior to change depending on platforms. Maybe it's possible to write to doc that due to accessbility settings DeviceEvent is in some conditions not fired on macOS; or winit could design new APIs to make macOS system calls to ask user for permission if possible (could save this API for other platforms, may always return Ok if permission grant is not needed)

@sanbox-irl
Copy link

Yes, it should be made clearer what's going on. Personally, the way I do it is that all platforms cfgh(not(target_os = "macos")) check DeviceEvents for keyinput, and then cfg(target_os = "macos") check for windowkey events.

@Osspial what do you think?

@leeola
Copy link

leeola commented Apr 4, 2020

Is there a reason you wanted to have both events report?

I may want this as well, though I'm new to the API so perhaps I'm misguided. My use case is a simple show/hide global key bind. Such that a user could be in one window, use a keyboard and have the Winit appear.

Sidenote, I've been trying to enable accessibility for a binary to get DeviceEvents with no success yet. With respect to:

macOS will only send "Key-related events..if accessibility is enabled or if your application is trusted for accessibility access".

I'm unsure how to enable accessibility within the binary, but I have at least added the Winit binary to the accessibility access under security. No luck getting background key events.

Thoughts?

edit: I fear the binary needs to be code signed.

@luojia65
Copy link
Author

luojia65 commented Apr 5, 2020

How does other macOS applications ask for enable accessibility settings in practice? Are some preconditions that must be satisfied?
(Users may use #cfg by now)

@leeola
Copy link

leeola commented Apr 5, 2020

No idea. Hell, I've been toying with Electron and my Rust / WASM / Electron app can catch global key binds without any special accessibility requests or provisions. So accessibility might be a bit off the mark. But perhaps the core electron process is signed, allowing background events? All speculation.

@leeola
Copy link

leeola commented May 9, 2020

Are there any hacks that might get this to work? So we can get any form of key events (Device or Window) for a background window?

@leeola
Copy link

leeola commented May 9, 2020

So I was poking around pretty blindly, and I found out that the https://github.com/Narsil/rdev crate successfully reports background key events. Seemingly it even works with winit, though with some logged errors (I was running rdev in a background thread, of which OSX was not happy about).

While I have no clue why rdev works, perhaps it may give insight that this is not solely a permission issue? The same binary allows rdev to receive background input events, but not winit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened C - needs investigation Issue must be confirmed and researched DS - macos H - help wanted Someone please save us
Development

No branches or pull requests

4 participants