Winit: [Android] `raw_window_handle` usage requirements are inobvious

Created on 1 Jun 2020  路  10Comments  路  Source: rust-windowing/winit

On android, when creating a window and then (pretty much) immediately requesting it's raw window handle, winit will panic at src/platform_impl/android/mod.rs:418: native window null.

This is because the code will call into android-ndk-rs:ndk-glue/src/lib.rs:68, which then tries to read the native window, which is not yet set because it's callback has not arrived yet.

I can currently reliably reproduce this issue on my Google Pixel 4.

I'm not sure whether this issue should be in the winit repo or the android-ndk-rs repo, feel free to transfer it.

easy good first issue Android normal help wanted documentation

All 10 comments

I've been having this issue too, and I've worked around it by just using std::thread::sleep before calling raw_window_handle, but that's obviously pretty silly...

@dvc94ch @JasperDeSutter do either of you have any insights on this?

It's only valid to use the native window between the Resumed and Paused events. Does it panic after the Resumed event happened?

@francesca64 I guess one slightly less hacky workaround would be to repeatedly call this function
image
until it returns Some and then retrieving the raw window handle.

That would look something like this:

let window = ...;
while ndk_glue::native_window().is_none() {
    std::thread::yield_now();
}
let handle = window.raw_window_handle();

Disclaimer: I haven't tested this code and don't know much about Android, it might be bad practice to do so, i don't know.

Here's an example using glutin 0.23, you should only render between the Resume/Pause events: https://github.com/rust-windowing/glutin/blob/ad4ae795c5fedc399597950e1cfac625f07464bb/examples/window.rs

@Friz64 thanks, that should make a better stopgap until I get a chance to restructure my app.

@dvc94ch thanks, that makes sense.

Before we can consider this solved, I think we should...

  • change the "native window null" panic message to be more descriptive/prescriptive, since it isn't currently obvious that it's the result of incorrect usage
  • make this requirement super duper clear in the documentation, since (unless I'm not looking in the right place?) it doesn't currently seem to be documented

Does anyone want to tackle this?

I ran into this issue as well, and fixed it with this snippet:

println!("Waiting for NativeScreen");
loop {
    match ndk_glue::native_window().as_ref() {
        Some(_) => {
            println!("NativeScreen Found:{:?}", ndk_glue::native_window());
            break;
        },
        None => ()
    }
}

And, instead of just putting this in the documentation, wouldn't it be better to add an awaitable method so that not everyone has to implement this waiting logic?

It's incorrect to do that. The native window will be None again. You can only use it between the resume/suspend events

OK.

... You can only use it between the resume/suspend events

Would that mean Event::Resumed and Event::Suspended @dvc94ch ?

Yes

Was this page helpful?
0 / 5 - 0 ratings

Related issues

francesca64 picture francesca64  路  4Comments

felixrabe picture felixrabe  路  3Comments

dhardy picture dhardy  路  3Comments

rukai picture rukai  路  4Comments

tomaka picture tomaka  路  3Comments