contextfree / winrt-rust

Use and (eventually) make Windows Runtime APIs with Rust
Apache License 2.0
142 stars 10 forks source link

Missing EventHandler usage #56

Open ticky opened 6 years ago

ticky commented 6 years ago

Hi there,

I’m trying to use the Windows.Gaming.Input methods to get Gamepad access. I’m having a lot of trouble figuring out how to implement the event handlers! I’ve gotten as far as getting an event handler with a signature that got accepted (kind of complicated, it seems!);

extern crate winrt;

use winrt::*;
use winrt::windows::foundation::*;
use winrt::windows::gaming::input::*;

fn main() {
    let rt = RuntimeContext::init();
    run();
    rt.uninit();
}

fn added(_sender: *mut winrt::IInspectable, gamepad: *mut Gamepad) -> Result<()> {
    print!("Gamepad added");

    Ok(())
}

fn run() {
    let gamepad_list = Gamepad::get_gamepads().unwrap().unwrap();

    print!("{} gamepads connected", gamepad_list.into_iter().count());

    match Gamepad::add_gamepad_added(&<EventHandler<Gamepad>>::new(added)) {
        Error => panic!("Couldn't add event handler")
    }

    for (_index, gamepad) in gamepad_list.into_iter().enumerate() {
        print!("{:?}", gamepad.unwrap().get_current_reading().unwrap());
    };
}

Unfortunately, I get “0 gamepads connected” printed, before it panics with not being able to add the event handler.

Is there something I’ve missed in how this is intended to work? I can find references in issues to event handlers, but I can’t see any example code.

Any help would be very appreciated - I’d also be happy to contribute the above in a PR as an example if I can get it working :)

Boddlnagg commented 6 years ago

I have a working "example" in the (unreleased) winrt backend of midir: https://github.com/Boddlnagg/midir/blob/5e90714e5bd5eb9062c19ca1d934dfec767d9711/src/backend/winrt/mod.rs#L107

It looks like you're doing basically the same thing, but your matching on the result seems wrong: When I build your example, I get the following warning:

warning: variable `Error` should have a snake case name such as `error`
  --> examples\events.rs:25:9
   |
25 |         Error => panic!("Couldn't add event handler")
   |         ^^^^^
   |
   = note: #[warn(non_snake_case)] on by default

This is because you're not actually matching on the Err variant, but your match arm matches in any case and it assigns the result (whether Err or Ok) to a new variable Error. This means that your code will panic even when the call to add_gamepad_added is returns successfully.

ticky commented 6 years ago

Is that warning showing for you on the nightly version of the compiler or something? I don’t remember seeing it! Thanks for the catch.

Might be nice to add an example of how to use this somewhere in the crate docs or the docs around the EventHandler object. :) Would you be up for a PR adding such a thing?

Boddlnagg commented 6 years ago

I think this warning should appear also on stable.

I would appreciate a PR for adding documentation around this, but I'm not sure where it's best to put it. On the EventHandler it's difficult because it's part of the generated code (and there are multiple event handler types, which you can see in the midir example which uses TypedEventHandler).