From 2c6081ce3593712f30dacd990a97209c791d6ced Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Thu, 15 Jul 2010 17:44:53 -0700 Subject: Implement native key pre-dispatching to IMEs. This significantly re-works the native key dispatching code to allow events to be pre-dispatched to the current IME before being processed by native code. It introduces one new public API, which must be called after retrieving an event if the app wishes for it to be pre-dispatched. Currently the native code will only do pre-dispatching of system keys, to avoid significant overhead for gaming input. This should be improved to be smarted, filtering for only keys that the IME is interested in. Unfortunately IMEs don't currently provide this information. :p Change-Id: Ic1c7aeec8b348164957f2cd88119eb5bd85c2a9f --- .../android_runtime/android_app_NativeActivity.h | 72 +++++++++++++++++++--- include/ui/Input.h | 2 + 2 files changed, 65 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/android_runtime/android_app_NativeActivity.h b/include/android_runtime/android_app_NativeActivity.h index d7a9a2c..c388ba8 100644 --- a/include/android_runtime/android_app_NativeActivity.h +++ b/include/android_runtime/android_app_NativeActivity.h @@ -42,8 +42,26 @@ extern void android_NativeActivity_hideSoftInput( /* * NDK input queue API. + * + * Here is the event flow: + * 1. Event arrives in input consumer, and is returned by getEvent(). + * 2. Application calls preDispatchEvent(): + * a. Event is assigned a sequence ID and enqueued in mPreDispatchingKeys. + * b. Main thread picks up event, hands to input method. + * c. Input method eventually returns sequence # and whether it was handled. + * d. finishPreDispatch() is called to enqueue the information. + * e. next getEvent() call will: + * - finish any pre-dispatch events that the input method handled + * - return the next pre-dispatched event that the input method didn't handle. + * f. (A preDispatchEvent() call on this event will now return false). + * 3. Application calls finishEvent() with whether it was handled. + * - If handled is true, the event is finished. + * - If handled is false, the event is put on mUnhandledKeys, and: + * a. Main thread receives event from consumeUnhandledEvent(). + * b. Java sends event through default key handler. + * c. event is finished. */ -struct AInputQueue { +struct AInputQueue : public android::InputEventFactoryInterface { public: /* Creates a consumer associated with an input channel. */ explicit AInputQueue(const android::sp& channel, int workWrite); @@ -59,8 +77,9 @@ public: int32_t getEvent(AInputEvent** outEvent); - void finishEvent(AInputEvent* event, bool handled); + bool preDispatchEvent(AInputEvent* event); + void finishEvent(AInputEvent* event, bool handled); // ---------------------------------------------------------- @@ -68,28 +87,63 @@ public: void dispatchEvent(android::KeyEvent* event); + void finishPreDispatch(int seq, bool handled); + android::KeyEvent* consumeUnhandledEvent(); + android::KeyEvent* consumePreDispatchingEvent(int* outSeq); + + virtual android::KeyEvent* createKeyEvent(); + virtual android::MotionEvent* createMotionEvent(); int mWorkWrite; private: - void doDefaultKey(android::KeyEvent* keyEvent); + void doUnhandledKey(android::KeyEvent* keyEvent); + bool preDispatchKey(android::KeyEvent* keyEvent); + void wakeupDispatch(); android::InputConsumer mConsumer; - android::PreallocatedInputEventFactory mInputEventFactory; android::sp mPollLoop; int mDispatchKeyRead; int mDispatchKeyWrite; - // This is only touched by the event reader thread. It is the current - // key events that came out of the mDispatchingKeys list and are now - //Êdelivered to the app. - android::Vector mDeliveringKeys; + struct in_flight_event { + android::InputEvent* event; + int seq; + bool doFinish; + }; + + struct finish_pre_dispatch { + int seq; + bool handled; + }; android::Mutex mLock; - android::Vector mPendingKeys; + + int mSeq; + + // Cache of previously allocated key events. + android::Vector mAvailKeyEvents; + // Cache of previously allocated motion events. + android::Vector mAvailMotionEvents; + + // All input events that are actively being processed. + android::Vector mInFlightEvents; + + // Key events that the app didn't handle, and are pending for + // delivery to the activity's default key handling. + android::Vector mUnhandledKeys; + + // Keys that arrived in the Java framework and need to be + // dispatched to the app. android::Vector mDispatchingKeys; + + // Key events that are pending to be pre-dispatched to the IME. + android::Vector mPreDispatchingKeys; + + // Event sequence numbers that we have finished pre-dispatching. + android::Vector mFinishPreDispatches; }; #endif // _ANDROID_APP_NATIVEACTIVITY_H diff --git a/include/ui/Input.h b/include/ui/Input.h index f069888..d9b1091 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -152,6 +152,7 @@ public: protected: void initialize(int32_t deviceId, int32_t source); + void initialize(const InputEvent& from); private: int32_t mDeviceId; @@ -202,6 +203,7 @@ public: int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime); + void initialize(const KeyEvent& from); private: int32_t mAction; -- cgit v1.1