-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
In android, Window::request_redraw() can block UserEvents send by EvenLoopProxy::send_event to reach the event loop callback.
I think this happens because of the way that request_redraw is injected in the Looper. In request_redraw the request is store in the static INTERNAL_EVENT, and the Looper is wakened:
winit/src/platform_impl/android/mod.rs
Lines 676 to 679 in 4dd2b66
| pub fn request_redraw(&self) { | |
| *INTERNAL_EVENT.write().unwrap() = Some(InternalEvent::RedrawRequested); | |
| ForeignLooper::for_thread().unwrap().wake(); | |
| } |
And in Poll::Wake, the request is injected in the Looper, taking priority over EventSource::User:
winit/src/platform_impl/android/mod.rs
Lines 220 to 226 in 4dd2b66
| Poll::Wake => Some( | |
| INTERNAL_EVENT | |
| .write() | |
| .unwrap() | |
| .take() | |
| .map_or(EventSource::User, EventSource::Internal), | |
| ), |
And send_event also wakes up the Looper:
winit/src/platform_impl/android/mod.rs
Lines 583 to 587 in 4dd2b66
| pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed<T>> { | |
| self.queue.lock().unwrap().push_back(event); | |
| self.looper.wake(); | |
| Ok(()) | |
| } |
This means that if both calls to loop.wake() creates a single Poll::Wake, request_event will always be blocking send_event (as happens in my device).
Reproducing the issue
I can reproduce this bug by adding the following example to the examples folder: https://gist.github.com/Rodrigodd/379a24ea39c6bead98a8b5dad5e0753e
And running in android, as instructed in the README.md.
// add this to Cargo.toml
[[example]]
name = "android_send_event_block"
crate-type = ["cdylib"]
cargo apk run --example android_send_event_block
adb logcat RustStdoutStderr:D *:S
Reproducible on Android 11.