native-activity: emit an InputAvailable event for new input

This reinstates support for notifying applications of new input events
without requiring them to always check for input as part of their
rendering updates. This makes it possible to build UI applications that
might only need to redraw in response to new input.

For now GameActivity doesn't emit this event but the plan is to also
add support for this in GameActivity.

Addresses: #4
This commit is contained in:
Robert Bragg
2022-07-06 15:22:09 +01:00
parent 1ca5f13874
commit bb8eeb705c
2 changed files with 26 additions and 18 deletions
+15 -5
View File
@@ -81,11 +81,21 @@ pub type StateLoader<'a> = activity_impl::StateLoader<'a>;
#[non_exhaustive]
#[derive(Debug)]
pub enum MainEvent<'a> {
/**
* Unused. Reserved for future use when usage of AInputQueue will be
* supported.
*/
//InputChanged,
/// New input events are available via [`AndroidApp::input_events()`]
///
/// _Note: Even if more input is received this event will not be resent
/// until [`AndroidApp::input_events()`] has been called, which enables
/// applications to batch up input processing without there being lots of
/// redundant event loop wake ups._
///
/// [`AndroidApp::input_events()`]: AndroidApp::input_events
///
/// # Portability
///
/// This is currently only supported with `NativeActivity` with the
/// "native-activity" feature. Applications using `GameActivity` should
/// continue to check for input as part of their rendering updates.
InputAvailable,
/// Command from main thread: a new [`NativeWindow`] is ready for use. Upon
/// receiving this command, [`native_window()`] will return the new window
+11 -13
View File
@@ -268,19 +268,13 @@ impl AndroidAppInner {
}
ffi::LOOPER_ID_INPUT => {
trace!("ALooper_pollAll returned ID_INPUT");
// For now we don't forward notifications of input events specifically, we just
// forward the notifications as a wake up, and assume the application main loop
// will unconditionally check events for each iteration of it's event loop
//
// (Specifically notifying when input events are received would be inconsistent
// with the current design of GameActivity input handling which we want to stay
// compatible with))
//
// XXX: Actually it was a bad idea to emit a Wake for input since applications
// are likely to _not_ consider that on its own a cause to redraw and it could
// end up spamming enough wake ups to interfere with other events that would
// trigger a redraw + input handling
//callback(PollEvent::Wake);
// To avoid spamming the application with event loop iterations notifying them of
// input events then we only send one `InputAvailable` per iteration of input
// handling. We re-attache the looper when the application calls
// `AndroidApp::input_events()`
ffi::android_app_detach_input_queue_looper(app_ptr.as_ptr());
callback(PollEvent::InputAvailable)
}
_ => {
let events = FdEvent::from_bits(events as u32)
@@ -341,6 +335,10 @@ impl AndroidAppInner {
pub fn input_events<'b, F>(&self, mut callback: F)
where F: FnMut(&input::InputEvent)
{
// Reattach the input queue to the looper so future input will again deliver an
// `InputAvailable` event.
ffi::android_app_attach_input_queue_looper(app_ptr.as_ptr());
let queue = unsafe {
let app_ptr = self.ptr.as_ptr();
if (*app_ptr).inputQueue == ptr::null_mut() {