Merge "Optimize focused input event dispatch in view root."
This commit is contained in:
@@ -229,6 +229,13 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
int mLastSystemUiVisibility;
|
int mLastSystemUiVisibility;
|
||||||
int mClientWindowLayoutFlags;
|
int mClientWindowLayoutFlags;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static final int EVENT_NOT_HANDLED = 0;
|
||||||
|
/** @hide */
|
||||||
|
public static final int EVENT_HANDLED = 1;
|
||||||
|
/** @hide */
|
||||||
|
public static final int EVENT_IN_PROGRESS = 2;
|
||||||
|
|
||||||
// Pool of queued input events.
|
// Pool of queued input events.
|
||||||
private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
|
private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
|
||||||
private QueuedInputEvent mQueuedInputEventPool;
|
private QueuedInputEvent mQueuedInputEventPool;
|
||||||
@@ -3240,19 +3247,19 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverInputEvent(QueuedInputEvent q) {
|
private int deliverInputEvent(QueuedInputEvent q) {
|
||||||
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
|
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
|
||||||
try {
|
try {
|
||||||
if (q.mEvent instanceof KeyEvent) {
|
if (q.mEvent instanceof KeyEvent) {
|
||||||
deliverKeyEvent(q);
|
return deliverKeyEvent(q);
|
||||||
} else {
|
} else {
|
||||||
final int source = q.mEvent.getSource();
|
final int source = q.mEvent.getSource();
|
||||||
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
||||||
deliverPointerEvent(q);
|
return deliverPointerEvent(q);
|
||||||
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
|
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
|
||||||
deliverTrackballEvent(q);
|
return deliverTrackballEvent(q);
|
||||||
} else {
|
} else {
|
||||||
deliverGenericMotionEvent(q);
|
return deliverGenericMotionEvent(q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -3260,7 +3267,25 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverPointerEvent(QueuedInputEvent q) {
|
private int deliverInputEventPostIme(QueuedInputEvent q) {
|
||||||
|
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEventPostIme");
|
||||||
|
try {
|
||||||
|
if (q.mEvent instanceof KeyEvent) {
|
||||||
|
return deliverKeyEventPostIme(q);
|
||||||
|
} else {
|
||||||
|
final int source = q.mEvent.getSource();
|
||||||
|
if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
|
||||||
|
return deliverTrackballEventPostIme(q);
|
||||||
|
} else {
|
||||||
|
return deliverGenericMotionEventPostIme(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int deliverPointerEvent(QueuedInputEvent q) {
|
||||||
final MotionEvent event = (MotionEvent)q.mEvent;
|
final MotionEvent event = (MotionEvent)q.mEvent;
|
||||||
final boolean isTouchEvent = event.isTouchEvent();
|
final boolean isTouchEvent = event.isTouchEvent();
|
||||||
if (mInputEventConsistencyVerifier != null) {
|
if (mInputEventConsistencyVerifier != null) {
|
||||||
@@ -3273,8 +3298,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
// If there is no view, then the event will not be handled.
|
// If there is no view, then the event will not be handled.
|
||||||
if (mView == null || !mAdded) {
|
if (mView == null || !mAdded) {
|
||||||
finishInputEvent(q, false);
|
return EVENT_NOT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate the pointer event for compatibility, if needed.
|
// Translate the pointer event for compatibility, if needed.
|
||||||
@@ -3307,16 +3331,10 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
if (MEASURE_LATENCY) {
|
if (MEASURE_LATENCY) {
|
||||||
lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());
|
lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());
|
||||||
}
|
}
|
||||||
if (handled) {
|
return handled ? EVENT_HANDLED : EVENT_NOT_HANDLED;
|
||||||
finishInputEvent(q, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointer event was unhandled.
|
|
||||||
finishInputEvent(q, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverTrackballEvent(QueuedInputEvent q) {
|
private int deliverTrackballEvent(QueuedInputEvent q) {
|
||||||
final MotionEvent event = (MotionEvent)q.mEvent;
|
final MotionEvent event = (MotionEvent)q.mEvent;
|
||||||
if (mInputEventConsistencyVerifier != null) {
|
if (mInputEventConsistencyVerifier != null) {
|
||||||
mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
|
mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
|
||||||
@@ -3335,24 +3353,25 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
if (DEBUG_IMF)
|
if (DEBUG_IMF)
|
||||||
Log.v(TAG, "Sending trackball event to IME: seq="
|
Log.v(TAG, "Sending trackball event to IME: seq="
|
||||||
+ seq + " event=" + event);
|
+ seq + " event=" + event);
|
||||||
imm.dispatchTrackballEvent(mView.getContext(), seq, event,
|
int result = imm.dispatchTrackballEvent(mView.getContext(), seq, event,
|
||||||
mInputMethodCallback);
|
mInputMethodCallback);
|
||||||
return;
|
if (result != EVENT_NOT_HANDLED) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not dispatching to IME, continue with post IME actions.
|
// Not dispatching to IME, continue with post IME actions.
|
||||||
deliverTrackballEventPostIme(q);
|
return deliverTrackballEventPostIme(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverTrackballEventPostIme(QueuedInputEvent q) {
|
private int deliverTrackballEventPostIme(QueuedInputEvent q) {
|
||||||
final MotionEvent event = (MotionEvent) q.mEvent;
|
final MotionEvent event = (MotionEvent) q.mEvent;
|
||||||
|
|
||||||
// If there is no view, then the event will not be handled.
|
// If there is no view, then the event will not be handled.
|
||||||
if (mView == null || !mAdded) {
|
if (mView == null || !mAdded) {
|
||||||
finishInputEvent(q, false);
|
return EVENT_NOT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deliver the trackball event to the view.
|
// Deliver the trackball event to the view.
|
||||||
@@ -3362,10 +3381,8 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
// event into a key event, touch mode will not exit, so we exit
|
// event into a key event, touch mode will not exit, so we exit
|
||||||
// touch mode here.
|
// touch mode here.
|
||||||
ensureTouchMode(false);
|
ensureTouchMode(false);
|
||||||
|
|
||||||
finishInputEvent(q, true);
|
|
||||||
mLastTrackballTime = Integer.MIN_VALUE;
|
mLastTrackballTime = Integer.MIN_VALUE;
|
||||||
return;
|
return EVENT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate the trackball event into DPAD keys and try to deliver those.
|
// Translate the trackball event into DPAD keys and try to deliver those.
|
||||||
@@ -3473,10 +3490,10 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
// Unfortunately we can't tell whether the application consumed the keys, so
|
// Unfortunately we can't tell whether the application consumed the keys, so
|
||||||
// we always consider the trackball event handled.
|
// we always consider the trackball event handled.
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverGenericMotionEvent(QueuedInputEvent q) {
|
private int deliverGenericMotionEvent(QueuedInputEvent q) {
|
||||||
final MotionEvent event = (MotionEvent)q.mEvent;
|
final MotionEvent event = (MotionEvent)q.mEvent;
|
||||||
if (mInputEventConsistencyVerifier != null) {
|
if (mInputEventConsistencyVerifier != null) {
|
||||||
mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
|
mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
|
||||||
@@ -3494,18 +3511,20 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
if (DEBUG_IMF)
|
if (DEBUG_IMF)
|
||||||
Log.v(TAG, "Sending generic motion event to IME: seq="
|
Log.v(TAG, "Sending generic motion event to IME: seq="
|
||||||
+ seq + " event=" + event);
|
+ seq + " event=" + event);
|
||||||
imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
|
int result = imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
|
||||||
mInputMethodCallback);
|
mInputMethodCallback);
|
||||||
return;
|
if (result != EVENT_NOT_HANDLED) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not dispatching to IME, continue with post IME actions.
|
// Not dispatching to IME, continue with post IME actions.
|
||||||
deliverGenericMotionEventPostIme(q);
|
return deliverGenericMotionEventPostIme(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverGenericMotionEventPostIme(QueuedInputEvent q) {
|
private int deliverGenericMotionEventPostIme(QueuedInputEvent q) {
|
||||||
final MotionEvent event = (MotionEvent) q.mEvent;
|
final MotionEvent event = (MotionEvent) q.mEvent;
|
||||||
final int source = event.getSource();
|
final int source = event.getSource();
|
||||||
final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
|
final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
|
||||||
@@ -3519,8 +3538,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
//Convert TouchPad motion into a TrackBall event
|
//Convert TouchPad motion into a TrackBall event
|
||||||
mSimulatedTrackball.updateTrackballDirection(this, event);
|
mSimulatedTrackball.updateTrackballDirection(this, event);
|
||||||
}
|
}
|
||||||
finishInputEvent(q, false);
|
return EVENT_NOT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deliver the event to the view.
|
// Deliver the event to the view.
|
||||||
@@ -3531,22 +3549,21 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
//Convert TouchPad motion into a TrackBall event
|
//Convert TouchPad motion into a TrackBall event
|
||||||
mSimulatedTrackball.updateTrackballDirection(this, event);
|
mSimulatedTrackball.updateTrackballDirection(this, event);
|
||||||
}
|
}
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isJoystick) {
|
if (isJoystick) {
|
||||||
// Translate the joystick event into DPAD keys and try to deliver
|
// Translate the joystick event into DPAD keys and try to deliver
|
||||||
// those.
|
// those.
|
||||||
updateJoystickDirection(event, true);
|
updateJoystickDirection(event, true);
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
} else if (isTouchPad) {
|
}
|
||||||
|
if (isTouchPad) {
|
||||||
//Convert TouchPad motion into a TrackBall event
|
//Convert TouchPad motion into a TrackBall event
|
||||||
mSimulatedTrackball.updateTrackballDirection(this, event);
|
mSimulatedTrackball.updateTrackballDirection(this, event);
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
} else {
|
|
||||||
finishInputEvent(q, false);
|
|
||||||
}
|
}
|
||||||
|
return EVENT_NOT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateJoystickDirection(MotionEvent event, boolean synthesizeNewKeys) {
|
private void updateJoystickDirection(MotionEvent event, boolean synthesizeNewKeys) {
|
||||||
@@ -3690,7 +3707,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverKeyEvent(QueuedInputEvent q) {
|
private int deliverKeyEvent(QueuedInputEvent q) {
|
||||||
final KeyEvent event = (KeyEvent)q.mEvent;
|
final KeyEvent event = (KeyEvent)q.mEvent;
|
||||||
if (mInputEventConsistencyVerifier != null) {
|
if (mInputEventConsistencyVerifier != null) {
|
||||||
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
|
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
|
||||||
@@ -3701,8 +3718,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
// Perform predispatching before the IME.
|
// Perform predispatching before the IME.
|
||||||
if (mView.dispatchKeyEventPreIme(event)) {
|
if (mView.dispatchKeyEventPreIme(event)) {
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch to the IME before propagating down the view hierarchy.
|
// Dispatch to the IME before propagating down the view hierarchy.
|
||||||
@@ -3713,81 +3729,30 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
final int seq = event.getSequenceNumber();
|
final int seq = event.getSequenceNumber();
|
||||||
if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq="
|
if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq="
|
||||||
+ seq + " event=" + event);
|
+ seq + " event=" + event);
|
||||||
imm.dispatchKeyEvent(mView.getContext(), seq, event, mInputMethodCallback);
|
int result = imm.dispatchKeyEvent(mView.getContext(), seq, event,
|
||||||
return;
|
mInputMethodCallback);
|
||||||
|
if (result != EVENT_NOT_HANDLED) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not dispatching to IME, continue with post IME actions.
|
// Not dispatching to IME, continue with post IME actions.
|
||||||
deliverKeyEventPostIme(q);
|
return deliverKeyEventPostIme(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleImeFinishedEvent(int seq, boolean handled) {
|
private int deliverKeyEventPostIme(QueuedInputEvent q) {
|
||||||
final QueuedInputEvent q = mCurrentInputEvent;
|
|
||||||
if (q != null && q.mEvent.getSequenceNumber() == seq) {
|
|
||||||
if (DEBUG_IMF) {
|
|
||||||
Log.v(TAG, "IME finished event: seq=" + seq
|
|
||||||
+ " handled=" + handled + " event=" + q);
|
|
||||||
}
|
|
||||||
if (handled) {
|
|
||||||
finishInputEvent(q, true);
|
|
||||||
} else {
|
|
||||||
if (q.mEvent instanceof KeyEvent) {
|
|
||||||
KeyEvent event = (KeyEvent)q.mEvent;
|
|
||||||
if (event.getAction() != KeyEvent.ACTION_UP) {
|
|
||||||
// If the window doesn't currently have input focus, then drop
|
|
||||||
// this event. This could be an event that came back from the
|
|
||||||
// IME dispatch but the window has lost focus in the meantime.
|
|
||||||
if (!mAttachInfo.mHasWindowFocus) {
|
|
||||||
Slog.w(TAG, "Dropping event due to no window focus: " + event);
|
|
||||||
finishInputEvent(q, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deliverKeyEventPostIme(q);
|
|
||||||
} else {
|
|
||||||
MotionEvent event = (MotionEvent)q.mEvent;
|
|
||||||
if (event.getAction() != MotionEvent.ACTION_CANCEL
|
|
||||||
&& event.getAction() != MotionEvent.ACTION_UP) {
|
|
||||||
// If the window doesn't currently have input focus, then drop
|
|
||||||
// this event. This could be an event that came back from the
|
|
||||||
// IME dispatch but the window has lost focus in the meantime.
|
|
||||||
if (!mAttachInfo.mHasWindowFocus) {
|
|
||||||
Slog.w(TAG, "Dropping event due to no window focus: " + event);
|
|
||||||
finishInputEvent(q, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final int source = q.mEvent.getSource();
|
|
||||||
if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
|
|
||||||
deliverTrackballEventPostIme(q);
|
|
||||||
} else {
|
|
||||||
deliverGenericMotionEventPostIme(q);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (DEBUG_IMF) {
|
|
||||||
Log.v(TAG, "IME finished event: seq=" + seq
|
|
||||||
+ " handled=" + handled + ", event not found!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deliverKeyEventPostIme(QueuedInputEvent q) {
|
|
||||||
final KeyEvent event = (KeyEvent)q.mEvent;
|
final KeyEvent event = (KeyEvent)q.mEvent;
|
||||||
|
|
||||||
// If the view went away, then the event will not be handled.
|
// If the view went away, then the event will not be handled.
|
||||||
if (mView == null || !mAdded) {
|
if (mView == null || !mAdded) {
|
||||||
finishInputEvent(q, false);
|
return EVENT_NOT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the key's purpose is to exit touch mode then we consume it and consider it handled.
|
// If the key's purpose is to exit touch mode then we consume it and consider it handled.
|
||||||
if (checkForLeavingTouchModeAndConsume(event)) {
|
if (checkForLeavingTouchModeAndConsume(event)) {
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the fallback event policy sees all keys that will be delivered to the
|
// Make sure the fallback event policy sees all keys that will be delivered to the
|
||||||
@@ -3796,8 +3761,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
// Deliver the key to the view hierarchy.
|
// Deliver the key to the view hierarchy.
|
||||||
if (mView.dispatchKeyEvent(event)) {
|
if (mView.dispatchKeyEvent(event)) {
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the Control modifier is held, try to interpret the key as a shortcut.
|
// If the Control modifier is held, try to interpret the key as a shortcut.
|
||||||
@@ -3806,15 +3770,13 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
&& event.getRepeatCount() == 0
|
&& event.getRepeatCount() == 0
|
||||||
&& !KeyEvent.isModifierKey(event.getKeyCode())) {
|
&& !KeyEvent.isModifierKey(event.getKeyCode())) {
|
||||||
if (mView.dispatchKeyShortcutEvent(event)) {
|
if (mView.dispatchKeyShortcutEvent(event)) {
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the fallback event policy.
|
// Apply the fallback event policy.
|
||||||
if (mFallbackEventHandler.dispatchKeyEvent(event)) {
|
if (mFallbackEventHandler.dispatchKeyEvent(event)) {
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle automatic focus changes.
|
// Handle automatic focus changes.
|
||||||
@@ -3867,22 +3829,20 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
if (v.requestFocus(direction, mTempRect)) {
|
if (v.requestFocus(direction, mTempRect)) {
|
||||||
playSoundEffect(SoundEffectConstants
|
playSoundEffect(SoundEffectConstants
|
||||||
.getContantForFocusDirection(direction));
|
.getContantForFocusDirection(direction));
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give the focused view a last chance to handle the dpad key.
|
// Give the focused view a last chance to handle the dpad key.
|
||||||
if (mView.dispatchUnhandledMove(focused, direction)) {
|
if (mView.dispatchUnhandledMove(focused, direction)) {
|
||||||
finishInputEvent(q, true);
|
return EVENT_HANDLED;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key was unhandled.
|
// Key was unhandled.
|
||||||
finishInputEvent(q, false);
|
return EVENT_NOT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drag/drop */
|
/* drag/drop */
|
||||||
@@ -4403,7 +4363,11 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
mFirstPendingInputEvent = q.mNext;
|
mFirstPendingInputEvent = q.mNext;
|
||||||
q.mNext = null;
|
q.mNext = null;
|
||||||
mCurrentInputEvent = q;
|
mCurrentInputEvent = q;
|
||||||
deliverInputEvent(q);
|
|
||||||
|
final int result = deliverInputEvent(q);
|
||||||
|
if (result != EVENT_IN_PROGRESS) {
|
||||||
|
finishCurrentInputEvent(result == EVENT_HANDLED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are done processing all input events that we can process right now
|
// We are done processing all input events that we can process right now
|
||||||
@@ -4414,10 +4378,42 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishInputEvent(QueuedInputEvent q, boolean handled) {
|
void handleImeFinishedEvent(int seq, boolean handled) {
|
||||||
if (q != mCurrentInputEvent) {
|
final QueuedInputEvent q = mCurrentInputEvent;
|
||||||
throw new IllegalStateException("finished input event out of order");
|
if (q != null && q.mEvent.getSequenceNumber() == seq) {
|
||||||
|
if (DEBUG_IMF) {
|
||||||
|
Log.v(TAG, "IME finished event: seq=" + seq
|
||||||
|
+ " handled=" + handled + " event=" + q);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
// If the window doesn't currently have input focus, then drop
|
||||||
|
// this event. This could be an event that came back from the
|
||||||
|
// IME dispatch but the window has lost focus in the meantime.
|
||||||
|
if (!mAttachInfo.mHasWindowFocus && !isTerminalInputEvent(q.mEvent)) {
|
||||||
|
Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent);
|
||||||
|
} else {
|
||||||
|
final int result = deliverInputEventPostIme(q);
|
||||||
|
if (result == EVENT_HANDLED) {
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finishCurrentInputEvent(handled);
|
||||||
|
|
||||||
|
// Immediately start processing the next input event.
|
||||||
|
doProcessInputEvents();
|
||||||
|
} else {
|
||||||
|
if (DEBUG_IMF) {
|
||||||
|
Log.v(TAG, "IME finished event: seq=" + seq
|
||||||
|
+ " handled=" + handled + ", event not found!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishCurrentInputEvent(boolean handled) {
|
||||||
|
final QueuedInputEvent q = mCurrentInputEvent;
|
||||||
|
mCurrentInputEvent = null;
|
||||||
|
|
||||||
if (q.mReceiver != null) {
|
if (q.mReceiver != null) {
|
||||||
q.mReceiver.finishInputEvent(q.mEvent, handled);
|
q.mReceiver.finishInputEvent(q.mEvent, handled);
|
||||||
@@ -4426,10 +4422,18 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycleQueuedInputEvent(q);
|
recycleQueuedInputEvent(q);
|
||||||
|
}
|
||||||
|
|
||||||
mCurrentInputEvent = null;
|
private static boolean isTerminalInputEvent(InputEvent event) {
|
||||||
if (mFirstPendingInputEvent != null) {
|
if (event instanceof KeyEvent) {
|
||||||
scheduleProcessInputEvents();
|
final KeyEvent keyEvent = (KeyEvent)event;
|
||||||
|
return keyEvent.getAction() == KeyEvent.ACTION_UP;
|
||||||
|
} else {
|
||||||
|
final MotionEvent motionEvent = (MotionEvent)event;
|
||||||
|
final int action = motionEvent.getAction();
|
||||||
|
return action == MotionEvent.ACTION_UP
|
||||||
|
|| action == MotionEvent.ACTION_CANCEL
|
||||||
|
|| action == MotionEvent.ACTION_HOVER_EXIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ public final class InputMethodManager {
|
|||||||
|
|
||||||
class H extends Handler {
|
class H extends Handler {
|
||||||
H(Looper looper) {
|
H(Looper looper) {
|
||||||
super(looper);
|
super(looper, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1565,38 +1565,36 @@ public final class InputMethodManager {
|
|||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void dispatchKeyEvent(Context context, int seq, KeyEvent key,
|
public int dispatchKeyEvent(Context context, int seq, KeyEvent key,
|
||||||
FinishedEventCallback callback) {
|
FinishedEventCallback callback) {
|
||||||
boolean handled = false;
|
|
||||||
synchronized (mH) {
|
synchronized (mH) {
|
||||||
if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
|
if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
|
||||||
|
|
||||||
if (mCurMethod != null) {
|
if (mCurMethod != null) {
|
||||||
if (key.getAction() == KeyEvent.ACTION_DOWN
|
if (key.getAction() == KeyEvent.ACTION_DOWN
|
||||||
&& key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
|
&& key.getKeyCode() == KeyEvent.KEYCODE_SYM
|
||||||
|
&& key.getRepeatCount() == 0) {
|
||||||
showInputMethodPickerLocked();
|
showInputMethodPickerLocked();
|
||||||
handled = true;
|
return ViewRootImpl.EVENT_HANDLED;
|
||||||
} else {
|
}
|
||||||
try {
|
try {
|
||||||
if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
|
if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
|
||||||
final long startTime = SystemClock.uptimeMillis();
|
final long startTime = SystemClock.uptimeMillis();
|
||||||
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
|
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
|
||||||
mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
|
mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
|
||||||
return;
|
return ViewRootImpl.EVENT_IN_PROGRESS;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
|
Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ViewRootImpl.EVENT_NOT_HANDLED;
|
||||||
callback.finishedEvent(seq, handled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
|
public int dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
|
||||||
FinishedEventCallback callback) {
|
FinishedEventCallback callback) {
|
||||||
synchronized (mH) {
|
synchronized (mH) {
|
||||||
if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
|
if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
|
||||||
@@ -1607,20 +1605,19 @@ public final class InputMethodManager {
|
|||||||
final long startTime = SystemClock.uptimeMillis();
|
final long startTime = SystemClock.uptimeMillis();
|
||||||
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
|
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
|
||||||
mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
|
mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
|
||||||
return;
|
return ViewRootImpl.EVENT_IN_PROGRESS;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
|
Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ViewRootImpl.EVENT_NOT_HANDLED;
|
||||||
callback.finishedEvent(seq, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
|
public int dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
|
||||||
FinishedEventCallback callback) {
|
FinishedEventCallback callback) {
|
||||||
synchronized (mH) {
|
synchronized (mH) {
|
||||||
if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent");
|
if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent");
|
||||||
@@ -1631,14 +1628,13 @@ public final class InputMethodManager {
|
|||||||
final long startTime = SystemClock.uptimeMillis();
|
final long startTime = SystemClock.uptimeMillis();
|
||||||
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
|
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
|
||||||
mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback);
|
mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback);
|
||||||
return;
|
return ViewRootImpl.EVENT_IN_PROGRESS;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e);
|
Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ViewRootImpl.EVENT_NOT_HANDLED;
|
||||||
callback.finishedEvent(seq, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void finishedEvent(int seq, boolean handled) {
|
void finishedEvent(int seq, boolean handled) {
|
||||||
|
|||||||
Reference in New Issue
Block a user