summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java131
1 files changed, 88 insertions, 43 deletions
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 925e78129dbe..ce36046a26b5 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,7 +26,6 @@ import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -198,7 +197,31 @@ public final class InputMethodManager {
static final Object mInstanceSync = new Object();
static InputMethodManager mInstance;
-
+
+ /**
+ * @hide Flag for IInputMethodManager.windowGainedFocus: a view in
+ * the window has input focus.
+ */
+ public static final int CONTROL_WINDOW_VIEW_HAS_FOCUS = 1<<0;
+
+ /**
+ * @hide Flag for IInputMethodManager.windowGainedFocus: the focus
+ * is a text editor.
+ */
+ public static final int CONTROL_WINDOW_IS_TEXT_EDITOR = 1<<1;
+
+ /**
+ * @hide Flag for IInputMethodManager.windowGainedFocus: this is the first
+ * time the window has gotten focus.
+ */
+ public static final int CONTROL_WINDOW_FIRST = 1<<2;
+
+ /**
+ * @hide Flag for IInputMethodManager.startInput: this is the first
+ * time the window has gotten focus.
+ */
+ public static final int CONTROL_START_INITIAL = 1<<8;
+
final IInputMethodManager mService;
final Looper mMainLooper;
@@ -216,7 +239,7 @@ public final class InputMethodManager {
/**
* Set whenever this client becomes inactive, to know we need to reset
- * state with the IME then next time we receive focus.
+ * state with the IME the next time we receive focus.
*/
boolean mHasBeenInactive = true;
@@ -243,11 +266,6 @@ public final class InputMethodManager {
*/
View mNextServedView;
/**
- * True if we should restart input in the next served view, even if the
- * view hasn't actually changed from the current serve view.
- */
- boolean mNextServedNeedsStart;
- /**
* This is set when we are in the process of connecting, to determine
* when we have actually finished.
*/
@@ -331,7 +349,7 @@ public final class InputMethodManager {
mCurId = res.id;
mBindSequence = res.sequence;
}
- startInputInner();
+ startInputInner(null, 0, 0, 0);
return;
}
case MSG_UNBIND: {
@@ -362,7 +380,7 @@ public final class InputMethodManager {
}
}
if (startInput) {
- startInputInner();
+ startInputInner(null, 0, 0, 0);
}
return;
}
@@ -952,10 +970,11 @@ public final class InputMethodManager {
mServedConnecting = true;
}
- startInputInner();
+ startInputInner(null, 0, 0, 0);
}
- void startInputInner() {
+ boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
+ int windowFlags) {
final View view;
synchronized (mH) {
view = mServedView;
@@ -964,7 +983,7 @@ public final class InputMethodManager {
if (DEBUG) Log.v(TAG, "Starting input: view=" + view);
if (view == null) {
if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
- return;
+ return false;
}
}
@@ -977,7 +996,7 @@ public final class InputMethodManager {
// If the view doesn't have a handler, something has changed out
// from under us, so just bail.
if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");
- return;
+ return false;
}
if (vh.getLooper() != Looper.myLooper()) {
// The view is running on a different thread than our own, so
@@ -985,10 +1004,10 @@ public final class InputMethodManager {
if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
vh.post(new Runnable() {
public void run() {
- startInputInner();
+ startInputInner(null, 0, 0, 0);
}
});
- return;
+ return false;
}
// Okay we are now ready to call into the served view and have it
@@ -1008,12 +1027,14 @@ public final class InputMethodManager {
if (DEBUG) Log.v(TAG,
"Starting input: finished by someone else (view="
+ mServedView + " conn=" + mServedConnecting + ")");
- return;
+ return false;
}
-
+
// If we already have a text box, then this view is already
// connected so we want to restart it.
- final boolean initial = mCurrentTextBoxAttribute == null;
+ if (mCurrentTextBoxAttribute == null) {
+ controlFlags |= CONTROL_START_INITIAL;
+ }
// Hook 'em up and let 'er rip.
mCurrentTextBoxAttribute = tba;
@@ -1033,9 +1054,17 @@ public final class InputMethodManager {
try {
if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
- + ic + " tba=" + tba + " initial=" + initial);
- InputBindResult res = mService.startInput(mClient,
- servedContext, tba, initial, true);
+ + ic + " tba=" + tba + " controlFlags=#"
+ + Integer.toHexString(controlFlags));
+ InputBindResult res;
+ if (windowGainingFocus != null) {
+ res = mService.windowGainedFocus(mClient, windowGainingFocus,
+ controlFlags, softInputMode, windowFlags,
+ tba, servedContext);
+ } else {
+ res = mService.startInput(mClient,
+ servedContext, tba, controlFlags);
+ }
if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
if (res != null) {
if (res.id != null) {
@@ -1044,7 +1073,7 @@ public final class InputMethodManager {
} else if (mCurMethod == null) {
// This means there is no input method available.
if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
- return;
+ return true;
}
}
if (mCurMethod != null && mCompletions != null) {
@@ -1057,6 +1086,8 @@ public final class InputMethodManager {
Log.w(TAG, "IME died: " + mCurId, e);
}
}
+
+ return true;
}
/**
@@ -1133,27 +1164,26 @@ public final class InputMethodManager {
* @hide
*/
public void checkFocus() {
- if (checkFocusNoStartInput()) {
- startInputInner();
+ if (checkFocusNoStartInput(false)) {
+ startInputInner(null, 0, 0, 0);
}
}
- private boolean checkFocusNoStartInput() {
+ private boolean checkFocusNoStartInput(boolean forceNewFocus) {
// This is called a lot, so short-circuit before locking.
- if (mServedView == mNextServedView && !mNextServedNeedsStart) {
+ if (mServedView == mNextServedView && !forceNewFocus) {
return false;
}
InputConnection ic = null;
synchronized (mH) {
- if (mServedView == mNextServedView && !mNextServedNeedsStart) {
+ if (mServedView == mNextServedView && !forceNewFocus) {
return false;
}
if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
+ " next=" + mNextServedView
- + " restart=" + mNextServedNeedsStart);
+ + " forceNewFocus=" + forceNewFocus);
- mNextServedNeedsStart = false;
if (mNextServedView == null) {
finishInputLocked();
// In this case, we used to have a focused view on the window,
@@ -1184,13 +1214,14 @@ public final class InputMethodManager {
} catch (RemoteException e) {
}
}
-
+
/**
* Called by ViewAncestor when its window gets input focus.
* @hide
*/
public void onWindowFocus(View rootView, View focusedView, int softInputMode,
boolean first, int windowFlags) {
+ boolean forceNewFocus = false;
synchronized (mH) {
if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
+ " softInputMode=" + softInputMode
@@ -1199,27 +1230,42 @@ public final class InputMethodManager {
if (mHasBeenInactive) {
if (DEBUG) Log.v(TAG, "Has been inactive! Starting fresh");
mHasBeenInactive = false;
- mNextServedNeedsStart = true;
+ forceNewFocus = true;
}
focusInLocked(focusedView != null ? focusedView : rootView);
}
+
+ int controlFlags = 0;
+ if (focusedView != null) {
+ controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS;
+ if (focusedView.onCheckIsTextEditor()) {
+ controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR;
+ }
+ }
+ if (first) {
+ controlFlags |= CONTROL_WINDOW_FIRST;
+ }
- boolean startInput = checkFocusNoStartInput();
+ if (checkFocusNoStartInput(forceNewFocus)) {
+ // We need to restart input on the current focus view. This
+ // should be done in conjunction with telling the system service
+ // about the window gaining focus, to help make the transition
+ // smooth.
+ if (startInputInner(rootView.getWindowToken(),
+ controlFlags, softInputMode, windowFlags)) {
+ return;
+ }
+ }
+ // For some reason we didn't do a startInput + windowFocusGain, so
+ // we'll just do a window focus gain and call it a day.
synchronized (mH) {
try {
- final boolean isTextEditor = focusedView != null &&
- focusedView.onCheckIsTextEditor();
mService.windowGainedFocus(mClient, rootView.getWindowToken(),
- focusedView != null, isTextEditor, softInputMode, first,
- windowFlags);
+ controlFlags, softInputMode, windowFlags, null, null);
} catch (RemoteException e) {
}
}
-
- if (startInput) {
- startInputInner();
- }
}
/** @hide */
@@ -1649,8 +1695,7 @@ public final class InputMethodManager {
p.println(" mCurMethod=" + mCurMethod);
p.println(" mCurRootView=" + mCurRootView);
p.println(" mServedView=" + mServedView);
- p.println(" mNextServedNeedsStart=" + mNextServedNeedsStart
- + " mNextServedView=" + mNextServedView);
+ p.println(" mNextServedView=" + mNextServedView);
p.println(" mServedConnecting=" + mServedConnecting);
if (mCurrentTextBoxAttribute != null) {
p.println(" mCurrentTextBoxAttribute:");