summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/inputmethodservice/AbstractInputMethodService.java29
-rw-r--r--core/java/android/inputmethodservice/IInputMethodSessionWrapper.java16
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java25
-rw-r--r--core/java/android/view/InputEventConsistencyVerifier.java2
-rw-r--r--core/java/android/view/ViewRootImpl.java81
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java26
-rw-r--r--core/java/android/view/inputmethod/InputMethodSession.java15
-rw-r--r--core/java/com/android/internal/view/IInputMethodSession.aidl2
8 files changed, 179 insertions, 17 deletions
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 27af013..3c3182a 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -149,6 +149,17 @@ public abstract class AbstractInputMethodService extends Service
callback.finishedEvent(seq, handled);
}
}
+
+ /**
+ * Take care of dispatching incoming generic motion events to the appropriate
+ * callbacks on the service, and tell the client when this is done.
+ */
+ public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) {
+ boolean handled = onGenericMotionEvent(event);
+ if (callback != null) {
+ callback.finishedEvent(seq, handled);
+ }
+ }
}
/**
@@ -189,7 +200,25 @@ public abstract class AbstractInputMethodService extends Service
return new IInputMethodWrapper(this, mInputMethod);
}
+ /**
+ * Implement this to handle trackball events on your input method.
+ *
+ * @param event The motion event being received.
+ * @return True if the event was handled in this function, false otherwise.
+ * @see View#onTrackballEvent
+ */
public boolean onTrackballEvent(MotionEvent event) {
return false;
}
+
+ /**
+ * Implement this to handle generic motion events on your input method.
+ *
+ * @param event The motion event being received.
+ * @return True if the event was handled in this function, false otherwise.
+ * @see View#onGenericMotionEvent
+ */
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ return false;
+ }
}
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index ce797d1..5324f81 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -43,6 +43,7 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
private static final int DO_DISPATCH_KEY_EVENT = 70;
private static final int DO_DISPATCH_TRACKBALL_EVENT = 80;
+ private static final int DO_DISPATCH_GENERIC_MOTION_EVENT = 85;
private static final int DO_UPDATE_SELECTION = 90;
private static final int DO_UPDATE_CURSOR = 95;
private static final int DO_APP_PRIVATE_COMMAND = 100;
@@ -109,6 +110,15 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
args.recycle();
return;
}
+ case DO_DISPATCH_GENERIC_MOTION_EVENT: {
+ SomeArgs args = (SomeArgs)msg.obj;
+ mInputMethodSession.dispatchGenericMotionEvent(msg.arg1,
+ (MotionEvent)args.arg1,
+ new InputMethodEventCallbackWrapper(
+ (IInputMethodCallback)args.arg2));
+ args.recycle();
+ return;
+ }
case DO_UPDATE_SELECTION: {
SomeArgs args = (SomeArgs)msg.obj;
mInputMethodSession.updateSelection(args.argi1, args.argi2,
@@ -167,6 +177,12 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
event, callback));
}
+ public void dispatchGenericMotionEvent(int seq, MotionEvent event,
+ IInputMethodCallback callback) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_GENERIC_MOTION_EVENT, seq,
+ event, callback));
+ }
+
public void updateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index d5b9edc..cf3b802 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1773,7 +1773,7 @@ public class InputMethodService extends AbstractInputMethodService {
* Override this to intercept special key multiple events before they are
* processed by the
* application. If you return true, the application will not itself
- * process the event. If you return true, the normal application processing
+ * process the event. If you return false, the normal application processing
* will occur as if the IME had not seen the event at all.
*
* <p>The default implementation always returns false, except when
@@ -1788,7 +1788,7 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* Override this to intercept key up events before they are processed by the
* application. If you return true, the application will not itself
- * process the event. If you return true, the normal application processing
+ * process the event. If you return false, the normal application processing
* will occur as if the IME had not seen the event at all.
*
* <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
@@ -1806,8 +1806,29 @@ public class InputMethodService extends AbstractInputMethodService {
return doMovementKey(keyCode, event, MOVEMENT_UP);
}
+ /**
+ * Override this to intercept trackball motion events before they are
+ * processed by the application.
+ * If you return true, the application will not itself process the event.
+ * If you return false, the normal application processing will occur as if
+ * the IME had not seen the event at all.
+ */
@Override
public boolean onTrackballEvent(MotionEvent event) {
+ if (DEBUG) Log.v(TAG, "onTrackballEvent: " + event);
+ return false;
+ }
+
+ /**
+ * Override this to intercept generic motion events before they are
+ * processed by the application.
+ * If you return true, the application will not itself process the event.
+ * If you return false, the normal application processing will occur as if
+ * the IME had not seen the event at all.
+ */
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ if (DEBUG) Log.v(TAG, "onGenericMotionEvent(): event " + event);
return false;
}
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index fafe416..5dda934 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -322,7 +322,7 @@ public final class InputEventConsistencyVerifier {
final int action = event.getAction();
final boolean newStream = action == MotionEvent.ACTION_DOWN
- || action == MotionEvent.ACTION_CANCEL;
+ || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_OUTSIDE;
if (newStream && (mTouchEventStreamIsTainted || mTouchEventStreamUnhandled)) {
mTouchEventStreamIsTainted = false;
mTouchEventStreamUnhandled = false;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a4c0235..3006b5d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3211,6 +3211,33 @@ public final class ViewRootImpl implements ViewParent,
mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
}
+ if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
+ if (LOCAL_LOGV)
+ Log.v(TAG, "Dispatching trackball " + event + " to " + mView);
+
+ // Dispatch to the IME before propagating down the view hierarchy.
+ // The IME will eventually call back into handleImeFinishedEvent.
+ if (mLastWasImTarget) {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null) {
+ final int seq = event.getSequenceNumber();
+ if (DEBUG_IMF)
+ Log.v(TAG, "Sending trackball event to IME: seq="
+ + seq + " event=" + event);
+ imm.dispatchTrackballEvent(mView.getContext(), seq, event,
+ mInputMethodCallback);
+ return;
+ }
+ }
+ }
+
+ // Not dispatching to IME, continue with post IME actions.
+ deliverTrackballEventPostIme(q);
+ }
+
+ private void deliverTrackballEventPostIme(QueuedInputEvent q) {
+ final MotionEvent event = (MotionEvent) q.mEvent;
+
// If there is no view, then the event will not be handled.
if (mView == null || !mAdded) {
finishInputEvent(q, false);
@@ -3344,8 +3371,33 @@ public final class ViewRootImpl implements ViewParent,
mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
}
- final int source = event.getSource();
- final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
+ if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
+ if (LOCAL_LOGV)
+ Log.v(TAG, "Dispatching generic motion " + event + " to " + mView);
+
+ // Dispatch to the IME before propagating down the view hierarchy.
+ // The IME will eventually call back into handleImeFinishedEvent.
+ if (mLastWasImTarget) {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null) {
+ final int seq = event.getSequenceNumber();
+ if (DEBUG_IMF)
+ Log.v(TAG, "Sending generic motion event to IME: seq="
+ + seq + " event=" + event);
+ imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
+ mInputMethodCallback);
+ return;
+ }
+ }
+ }
+
+ // Not dispatching to IME, continue with post IME actions.
+ deliverGenericMotionEventPostIme(q);
+ }
+
+ private void deliverGenericMotionEventPostIme(QueuedInputEvent q) {
+ final MotionEvent event = (MotionEvent) q.mEvent;
+ final boolean isJoystick = (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
// If there is no view, then the event will not be handled.
if (mView == null || !mAdded) {
@@ -3366,7 +3418,8 @@ public final class ViewRootImpl implements ViewParent,
}
if (isJoystick) {
- // Translate the joystick event into DPAD keys and try to deliver those.
+ // Translate the joystick event into DPAD keys and try to deliver
+ // those.
updateJoystickDirection(event, true);
finishInputEvent(q, true);
} else {
@@ -3521,13 +3574,7 @@ public final class ViewRootImpl implements ViewParent,
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
}
- if ((q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
- // If there is no view, then the event will not be handled.
- if (mView == null || !mAdded) {
- finishInputEvent(q, false);
- return;
- }
-
+ if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
if (LOCAL_LOGV) Log.v(TAG, "Dispatching key " + event + " to " + mView);
// Perform predispatching before the IME.
@@ -3557,15 +3604,23 @@ public final class ViewRootImpl implements ViewParent,
void handleImeFinishedEvent(int seq, boolean handled) {
final QueuedInputEvent q = mCurrentInputEvent;
if (q != null && q.mEvent.getSequenceNumber() == seq) {
- final KeyEvent event = (KeyEvent)q.mEvent;
if (DEBUG_IMF) {
Log.v(TAG, "IME finished event: seq=" + seq
- + " handled=" + handled + " event=" + event);
+ + " handled=" + handled + " event=" + q);
}
if (handled) {
finishInputEvent(q, true);
} else {
- deliverKeyEventPostIme(q);
+ if (q.mEvent instanceof KeyEvent) {
+ deliverKeyEventPostIme(q);
+ } else {
+ final int source = q.mEvent.getSource();
+ if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+ deliverTrackballEventPostIme(q);
+ } else {
+ deliverGenericMotionEventPostIme(q);
+ }
+ }
}
} else {
if (DEBUG_IMF) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e754adc..3ea6df3 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1593,7 +1593,7 @@ public final class InputMethodManager {
/**
* @hide
*/
- void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
+ public void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
FinishedEventCallback callback) {
synchronized (mH) {
if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
@@ -1614,6 +1614,30 @@ public final class InputMethodManager {
callback.finishedEvent(seq, false);
}
+ /**
+ * @hide
+ */
+ public void dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
+ FinishedEventCallback callback) {
+ synchronized (mH) {
+ if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent");
+
+ if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
+ try {
+ if (DEBUG) Log.v(TAG, "DISPATCH GENERIC MOTION: " + mCurMethod);
+ final long startTime = SystemClock.uptimeMillis();
+ enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+ mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback);
+ return;
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e);
+ }
+ }
+ }
+
+ callback.finishedEvent(seq, false);
+ }
+
void finishedEvent(int seq, boolean handled) {
final FinishedEventCallback callback;
synchronized (mH) {
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index ea6f5ee..6386299 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -138,6 +138,21 @@ public interface InputMethodSession {
public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback);
/**
+ * This method is called when there is a generic motion event.
+ *
+ * <p>
+ * If the input method wants to handle this event, return true, otherwise
+ * return false and the caller (i.e. the application) will handle the event.
+ *
+ * @param event The motion event.
+ *
+ * @return Whether the input method wants to handle this event.
+ *
+ * @see android.view.MotionEvent
+ */
+ public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback);
+
+ /**
* Process a private command sent from the application to the input method.
* This can be used to provide domain-specific features that are
* only known between certain input methods and their clients.
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index f875cbd..cdec254 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -47,6 +47,8 @@ oneway interface IInputMethodSession {
void dispatchTrackballEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
+ void dispatchGenericMotionEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
+
void appPrivateCommand(String action, in Bundle data);
void toggleSoftInput(int showFlags, int hideFlags);