Expose android_app_set_motion_event_filter from native app glue
4emodan opened this issue · 1 comments
By default android_native_app_glue uses the filter which only listens to SOURCE_TOUCHSCREEN (0x1002)
events.
It doesn't seem to work on emulators - I saw event->source == 0x5002
, can't even find a constant for that. The same problem I've experienced with the Samsung s-pen input devices.
So it would be great to have an option to setup the filter or drop it completely.
Yeah, this relates to quite a significant difference between how NativeActivity
based apps get events via an InputQueue
and GameActivity
instead hooks into Activity
callbacks for events.
The InputQueue
abstraction supports the notion that an event may not be "handled" by an application and in that case a default handler can run.
This is important for system buttons, like volume up/down + camera buttons which applications don't normally want to override.
The way this (roughly) works is that input events are dispatched to the root View which internally implements a notion of an 'InputStage' + 'AsyncInputStage' which are daisy chained together and allow events to be associated with an 'finish' handler. Two of these stages support forwarding events to an InputQueue
for native code (i.e. there is baked-in special-case support for how to route input events to native apps that are using an InputQueue
and the lifecycle of these events is tracked by these AsyncInputStage
implementations that have an onFinishedInputEvent
callback that will relay whether the native application really handled the event or not. (See: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/ViewRootImpl.java and e.g. NativePreImeInputStage
)
On the other hand GameActivity
does not get input events via an InputQueue
- it instead hooks into the Activity
callbacks like onKeyPress
which don't have the same kind of asynchronous tracking.
With the Activity callbacks they are
- run in the Java main thread and
- require the application to synchronously determine whether the event will be handled before returning
This means that we can't do anything with the InputStatus
that applications return when processing input events with the GameActivity
backend since there no way for us to trigger default handling for events if they have already been buffered.
To account for special cases like the volume keys then GameActivity
instead supports the notion of an event filter that will run on the Java main thread and can decide before buffering events whether they should be buffered or ignored (so they get default handling) and by default GameActivity
filters out volume key buttons, so native applications wouldn't see them and they would get default volume key handling.
The GameActivity
approach makes the full Java api for KeyEvent
and MotionEvent
accessible, including for example getUnicodeChar
which isn't exposed to the ndk
and is more awkward to emulate for NativeActivity
based applications.
In android-activity we don't currently expose this idea of an event filter and so applications get the default filter.
This means that GameActivity
based apps don't see volume up/down keys (because if they weren't filtered out then there would be no way to trigger the default system behavior if they aren't handled by applications).
If we were to expose this idea of an event filter then we could also run the same filter on top of the InputQueue
events for consistency.
For the motion events, I'm not aware of any reason why we couldn't change the default filter so that all motion events are buffered and exposed to applications but if any events might need default handling when applications aren't interested in them, there would be a similar issue as with the volume keys.