diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/inputmethod/InputMethodManager.java | 131 |
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:"); |
