2626import com .android .internal .view .InputBindResult ;
2727
2828import android .content .Context ;
29- import android .content .pm .PackageManager ;
3029import android .graphics .Rect ;
3130import android .os .Bundle ;
3231import android .os .Handler ;
@@ -198,7 +197,31 @@ public final class InputMethodManager {
198197
199198 static final Object mInstanceSync = new Object ();
200199 static InputMethodManager mInstance ;
201-
200+
201+ /**
202+ * @hide Flag for IInputMethodManager.windowGainedFocus: a view in
203+ * the window has input focus.
204+ */
205+ public static final int CONTROL_WINDOW_VIEW_HAS_FOCUS = 1 <<0 ;
206+
207+ /**
208+ * @hide Flag for IInputMethodManager.windowGainedFocus: the focus
209+ * is a text editor.
210+ */
211+ public static final int CONTROL_WINDOW_IS_TEXT_EDITOR = 1 <<1 ;
212+
213+ /**
214+ * @hide Flag for IInputMethodManager.windowGainedFocus: this is the first
215+ * time the window has gotten focus.
216+ */
217+ public static final int CONTROL_WINDOW_FIRST = 1 <<2 ;
218+
219+ /**
220+ * @hide Flag for IInputMethodManager.startInput: this is the first
221+ * time the window has gotten focus.
222+ */
223+ public static final int CONTROL_START_INITIAL = 1 <<8 ;
224+
202225 final IInputMethodManager mService ;
203226 final Looper mMainLooper ;
204227
@@ -216,7 +239,7 @@ public final class InputMethodManager {
216239
217240 /**
218241 * Set whenever this client becomes inactive, to know we need to reset
219- * state with the IME then next time we receive focus.
242+ * state with the IME the next time we receive focus.
220243 */
221244 boolean mHasBeenInactive = true ;
222245
@@ -242,11 +265,6 @@ public final class InputMethodManager {
242265 * we get around to updating things.
243266 */
244267 View mNextServedView ;
245- /**
246- * True if we should restart input in the next served view, even if the
247- * view hasn't actually changed from the current serve view.
248- */
249- boolean mNextServedNeedsStart ;
250268 /**
251269 * This is set when we are in the process of connecting, to determine
252270 * when we have actually finished.
@@ -331,7 +349,7 @@ public void handleMessage(Message msg) {
331349 mCurId = res .id ;
332350 mBindSequence = res .sequence ;
333351 }
334- startInputInner ();
352+ startInputInner (null , 0 , 0 , 0 );
335353 return ;
336354 }
337355 case MSG_UNBIND : {
@@ -362,7 +380,7 @@ public void handleMessage(Message msg) {
362380 }
363381 }
364382 if (startInput ) {
365- startInputInner ();
383+ startInputInner (null , 0 , 0 , 0 );
366384 }
367385 return ;
368386 }
@@ -957,10 +975,11 @@ public void restartInput(View view) {
957975 mServedConnecting = true ;
958976 }
959977
960- startInputInner ();
978+ startInputInner (null , 0 , 0 , 0 );
961979 }
962980
963- void startInputInner () {
981+ boolean startInputInner (IBinder windowGainingFocus , int controlFlags , int softInputMode ,
982+ int windowFlags ) {
964983 final View view ;
965984 synchronized (mH ) {
966985 view = mServedView ;
@@ -969,7 +988,7 @@ void startInputInner() {
969988 if (DEBUG ) Log .v (TAG , "Starting input: view=" + view );
970989 if (view == null ) {
971990 if (DEBUG ) Log .v (TAG , "ABORT input: no served view!" );
972- return ;
991+ return false ;
973992 }
974993 }
975994
@@ -982,18 +1001,18 @@ void startInputInner() {
9821001 // If the view doesn't have a handler, something has changed out
9831002 // from under us, so just bail.
9841003 if (DEBUG ) Log .v (TAG , "ABORT input: no handler for view!" );
985- return ;
1004+ return false ;
9861005 }
9871006 if (vh .getLooper () != Looper .myLooper ()) {
9881007 // The view is running on a different thread than our own, so
9891008 // we need to reschedule our work for over there.
9901009 if (DEBUG ) Log .v (TAG , "Starting input: reschedule to view thread" );
9911010 vh .post (new Runnable () {
9921011 public void run () {
993- startInputInner ();
1012+ startInputInner (null , 0 , 0 , 0 );
9941013 }
9951014 });
996- return ;
1015+ return false ;
9971016 }
9981017
9991018 // Okay we are now ready to call into the served view and have it
@@ -1013,12 +1032,14 @@ public void run() {
10131032 if (DEBUG ) Log .v (TAG ,
10141033 "Starting input: finished by someone else (view="
10151034 + mServedView + " conn=" + mServedConnecting + ")" );
1016- return ;
1035+ return false ;
10171036 }
1018-
1037+
10191038 // If we already have a text box, then this view is already
10201039 // connected so we want to restart it.
1021- final boolean initial = mCurrentTextBoxAttribute == null ;
1040+ if (mCurrentTextBoxAttribute == null ) {
1041+ controlFlags |= CONTROL_START_INITIAL ;
1042+ }
10221043
10231044 // Hook 'em up and let 'er rip.
10241045 mCurrentTextBoxAttribute = tba ;
@@ -1040,9 +1061,17 @@ public void run() {
10401061
10411062 try {
10421063 if (DEBUG ) Log .v (TAG , "START INPUT: " + view + " ic="
1043- + ic + " tba=" + tba + " initial=" + initial );
1044- InputBindResult res = mService .startInput (mClient ,
1045- servedContext , tba , initial , true );
1064+ + ic + " tba=" + tba + " controlFlags=#"
1065+ + Integer .toHexString (controlFlags ));
1066+ InputBindResult res ;
1067+ if (windowGainingFocus != null ) {
1068+ res = mService .windowGainedFocus (mClient , windowGainingFocus ,
1069+ controlFlags , softInputMode , windowFlags ,
1070+ tba , servedContext );
1071+ } else {
1072+ res = mService .startInput (mClient ,
1073+ servedContext , tba , controlFlags );
1074+ }
10461075 if (DEBUG ) Log .v (TAG , "Starting input: Bind result=" + res );
10471076 if (res != null ) {
10481077 if (res .id != null ) {
@@ -1051,7 +1080,7 @@ public void run() {
10511080 } else if (mCurMethod == null ) {
10521081 // This means there is no input method available.
10531082 if (DEBUG ) Log .v (TAG , "ABORT input: no input method!" );
1054- return ;
1083+ return true ;
10551084 }
10561085 }
10571086 if (mCurMethod != null && mCompletions != null ) {
@@ -1064,6 +1093,8 @@ public void run() {
10641093 Log .w (TAG , "IME died: " + mCurId , e );
10651094 }
10661095 }
1096+
1097+ return true ;
10671098 }
10681099
10691100 /**
@@ -1139,27 +1170,26 @@ static void scheduleCheckFocusLocked(View view) {
11391170 * @hide
11401171 */
11411172 public void checkFocus () {
1142- if (checkFocusNoStartInput ()) {
1143- startInputInner ();
1173+ if (checkFocusNoStartInput (false )) {
1174+ startInputInner (null , 0 , 0 , 0 );
11441175 }
11451176 }
11461177
1147- private boolean checkFocusNoStartInput () {
1178+ private boolean checkFocusNoStartInput (boolean forceNewFocus ) {
11481179 // This is called a lot, so short-circuit before locking.
1149- if (mServedView == mNextServedView && !mNextServedNeedsStart ) {
1180+ if (mServedView == mNextServedView && !forceNewFocus ) {
11501181 return false ;
11511182 }
11521183
11531184 InputConnection ic = null ;
11541185 synchronized (mH ) {
1155- if (mServedView == mNextServedView && !mNextServedNeedsStart ) {
1186+ if (mServedView == mNextServedView && !forceNewFocus ) {
11561187 return false ;
11571188 }
11581189 if (DEBUG ) Log .v (TAG , "checkFocus: view=" + mServedView
11591190 + " next=" + mNextServedView
1160- + " restart =" + mNextServedNeedsStart );
1191+ + " forceNewFocus =" + forceNewFocus );
11611192
1162- mNextServedNeedsStart = false ;
11631193 if (mNextServedView == null ) {
11641194 finishInputLocked ();
11651195 // In this case, we used to have a focused view on the window,
@@ -1190,13 +1220,14 @@ void closeCurrentInput() {
11901220 } catch (RemoteException e ) {
11911221 }
11921222 }
1193-
1223+
11941224 /**
11951225 * Called by ViewAncestor when its window gets input focus.
11961226 * @hide
11971227 */
11981228 public void onWindowFocus (View rootView , View focusedView , int softInputMode ,
11991229 boolean first , int windowFlags ) {
1230+ boolean forceNewFocus = false ;
12001231 synchronized (mH ) {
12011232 if (DEBUG ) Log .v (TAG , "onWindowFocus: " + focusedView
12021233 + " softInputMode=" + softInputMode
@@ -1205,27 +1236,42 @@ public void onWindowFocus(View rootView, View focusedView, int softInputMode,
12051236 if (mHasBeenInactive ) {
12061237 if (DEBUG ) Log .v (TAG , "Has been inactive! Starting fresh" );
12071238 mHasBeenInactive = false ;
1208- mNextServedNeedsStart = true ;
1239+ forceNewFocus = true ;
12091240 }
12101241 focusInLocked (focusedView != null ? focusedView : rootView );
12111242 }
1243+
1244+ int controlFlags = 0 ;
1245+ if (focusedView != null ) {
1246+ controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS ;
1247+ if (focusedView .onCheckIsTextEditor ()) {
1248+ controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR ;
1249+ }
1250+ }
1251+ if (first ) {
1252+ controlFlags |= CONTROL_WINDOW_FIRST ;
1253+ }
12121254
1213- boolean startInput = checkFocusNoStartInput ();
1255+ if (checkFocusNoStartInput (forceNewFocus )) {
1256+ // We need to restart input on the current focus view. This
1257+ // should be done in conjunction with telling the system service
1258+ // about the window gaining focus, to help make the transition
1259+ // smooth.
1260+ if (startInputInner (rootView .getWindowToken (),
1261+ controlFlags , softInputMode , windowFlags )) {
1262+ return ;
1263+ }
1264+ }
12141265
1266+ // For some reason we didn't do a startInput + windowFocusGain, so
1267+ // we'll just do a window focus gain and call it a day.
12151268 synchronized (mH ) {
12161269 try {
1217- final boolean isTextEditor = focusedView != null &&
1218- focusedView .onCheckIsTextEditor ();
12191270 mService .windowGainedFocus (mClient , rootView .getWindowToken (),
1220- focusedView != null , isTextEditor , softInputMode , first ,
1221- windowFlags );
1271+ controlFlags , softInputMode , windowFlags , null , null );
12221272 } catch (RemoteException e ) {
12231273 }
12241274 }
1225-
1226- if (startInput ) {
1227- startInputInner ();
1228- }
12291275 }
12301276
12311277 /** @hide */
@@ -1676,8 +1722,7 @@ void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
16761722 p .println (" mCurMethod=" + mCurMethod );
16771723 p .println (" mCurRootView=" + mCurRootView );
16781724 p .println (" mServedView=" + mServedView );
1679- p .println (" mNextServedNeedsStart=" + mNextServedNeedsStart
1680- + " mNextServedView=" + mNextServedView );
1725+ p .println (" mNextServedView=" + mNextServedView );
16811726 p .println (" mServedConnecting=" + mServedConnecting );
16821727 if (mCurrentTextBoxAttribute != null ) {
16831728 p .println (" mCurrentTextBoxAttribute:" );
0 commit comments