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 }
@@ -952,10 +970,11 @@ public void restartInput(View view) {
952970 mServedConnecting = true ;
953971 }
954972
955- startInputInner ();
973+ startInputInner (null , 0 , 0 , 0 );
956974 }
957975
958- void startInputInner () {
976+ boolean startInputInner (IBinder windowGainingFocus , int controlFlags , int softInputMode ,
977+ int windowFlags ) {
959978 final View view ;
960979 synchronized (mH ) {
961980 view = mServedView ;
@@ -964,7 +983,7 @@ void startInputInner() {
964983 if (DEBUG ) Log .v (TAG , "Starting input: view=" + view );
965984 if (view == null ) {
966985 if (DEBUG ) Log .v (TAG , "ABORT input: no served view!" );
967- return ;
986+ return false ;
968987 }
969988 }
970989
@@ -977,18 +996,18 @@ void startInputInner() {
977996 // If the view doesn't have a handler, something has changed out
978997 // from under us, so just bail.
979998 if (DEBUG ) Log .v (TAG , "ABORT input: no handler for view!" );
980- return ;
999+ return false ;
9811000 }
9821001 if (vh .getLooper () != Looper .myLooper ()) {
9831002 // The view is running on a different thread than our own, so
9841003 // we need to reschedule our work for over there.
9851004 if (DEBUG ) Log .v (TAG , "Starting input: reschedule to view thread" );
9861005 vh .post (new Runnable () {
9871006 public void run () {
988- startInputInner ();
1007+ startInputInner (null , 0 , 0 , 0 );
9891008 }
9901009 });
991- return ;
1010+ return false ;
9921011 }
9931012
9941013 // Okay we are now ready to call into the served view and have it
@@ -1008,12 +1027,14 @@ public void run() {
10081027 if (DEBUG ) Log .v (TAG ,
10091028 "Starting input: finished by someone else (view="
10101029 + mServedView + " conn=" + mServedConnecting + ")" );
1011- return ;
1030+ return false ;
10121031 }
1013-
1032+
10141033 // If we already have a text box, then this view is already
10151034 // connected so we want to restart it.
1016- final boolean initial = mCurrentTextBoxAttribute == null ;
1035+ if (mCurrentTextBoxAttribute == null ) {
1036+ controlFlags |= CONTROL_START_INITIAL ;
1037+ }
10171038
10181039 // Hook 'em up and let 'er rip.
10191040 mCurrentTextBoxAttribute = tba ;
@@ -1033,9 +1054,17 @@ public void run() {
10331054
10341055 try {
10351056 if (DEBUG ) Log .v (TAG , "START INPUT: " + view + " ic="
1036- + ic + " tba=" + tba + " initial=" + initial );
1037- InputBindResult res = mService .startInput (mClient ,
1038- servedContext , tba , initial , true );
1057+ + ic + " tba=" + tba + " controlFlags=#"
1058+ + Integer .toHexString (controlFlags ));
1059+ InputBindResult res ;
1060+ if (windowGainingFocus != null ) {
1061+ res = mService .windowGainedFocus (mClient , windowGainingFocus ,
1062+ controlFlags , softInputMode , windowFlags ,
1063+ tba , servedContext );
1064+ } else {
1065+ res = mService .startInput (mClient ,
1066+ servedContext , tba , controlFlags );
1067+ }
10391068 if (DEBUG ) Log .v (TAG , "Starting input: Bind result=" + res );
10401069 if (res != null ) {
10411070 if (res .id != null ) {
@@ -1044,7 +1073,7 @@ public void run() {
10441073 } else if (mCurMethod == null ) {
10451074 // This means there is no input method available.
10461075 if (DEBUG ) Log .v (TAG , "ABORT input: no input method!" );
1047- return ;
1076+ return true ;
10481077 }
10491078 }
10501079 if (mCurMethod != null && mCompletions != null ) {
@@ -1057,6 +1086,8 @@ public void run() {
10571086 Log .w (TAG , "IME died: " + mCurId , e );
10581087 }
10591088 }
1089+
1090+ return true ;
10601091 }
10611092
10621093 /**
@@ -1133,27 +1164,26 @@ void scheduleCheckFocusLocked(View view) {
11331164 * @hide
11341165 */
11351166 public void checkFocus () {
1136- if (checkFocusNoStartInput ()) {
1137- startInputInner ();
1167+ if (checkFocusNoStartInput (false )) {
1168+ startInputInner (null , 0 , 0 , 0 );
11381169 }
11391170 }
11401171
1141- private boolean checkFocusNoStartInput () {
1172+ private boolean checkFocusNoStartInput (boolean forceNewFocus ) {
11421173 // This is called a lot, so short-circuit before locking.
1143- if (mServedView == mNextServedView && !mNextServedNeedsStart ) {
1174+ if (mServedView == mNextServedView && !forceNewFocus ) {
11441175 return false ;
11451176 }
11461177
11471178 InputConnection ic = null ;
11481179 synchronized (mH ) {
1149- if (mServedView == mNextServedView && !mNextServedNeedsStart ) {
1180+ if (mServedView == mNextServedView && !forceNewFocus ) {
11501181 return false ;
11511182 }
11521183 if (DEBUG ) Log .v (TAG , "checkFocus: view=" + mServedView
11531184 + " next=" + mNextServedView
1154- + " restart =" + mNextServedNeedsStart );
1185+ + " forceNewFocus =" + forceNewFocus );
11551186
1156- mNextServedNeedsStart = false ;
11571187 if (mNextServedView == null ) {
11581188 finishInputLocked ();
11591189 // In this case, we used to have a focused view on the window,
@@ -1184,13 +1214,14 @@ void closeCurrentInput() {
11841214 } catch (RemoteException e ) {
11851215 }
11861216 }
1187-
1217+
11881218 /**
11891219 * Called by ViewAncestor when its window gets input focus.
11901220 * @hide
11911221 */
11921222 public void onWindowFocus (View rootView , View focusedView , int softInputMode ,
11931223 boolean first , int windowFlags ) {
1224+ boolean forceNewFocus = false ;
11941225 synchronized (mH ) {
11951226 if (DEBUG ) Log .v (TAG , "onWindowFocus: " + focusedView
11961227 + " softInputMode=" + softInputMode
@@ -1199,27 +1230,42 @@ public void onWindowFocus(View rootView, View focusedView, int softInputMode,
11991230 if (mHasBeenInactive ) {
12001231 if (DEBUG ) Log .v (TAG , "Has been inactive! Starting fresh" );
12011232 mHasBeenInactive = false ;
1202- mNextServedNeedsStart = true ;
1233+ forceNewFocus = true ;
12031234 }
12041235 focusInLocked (focusedView != null ? focusedView : rootView );
12051236 }
1237+
1238+ int controlFlags = 0 ;
1239+ if (focusedView != null ) {
1240+ controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS ;
1241+ if (focusedView .onCheckIsTextEditor ()) {
1242+ controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR ;
1243+ }
1244+ }
1245+ if (first ) {
1246+ controlFlags |= CONTROL_WINDOW_FIRST ;
1247+ }
12061248
1207- boolean startInput = checkFocusNoStartInput ();
1249+ if (checkFocusNoStartInput (forceNewFocus )) {
1250+ // We need to restart input on the current focus view. This
1251+ // should be done in conjunction with telling the system service
1252+ // about the window gaining focus, to help make the transition
1253+ // smooth.
1254+ if (startInputInner (rootView .getWindowToken (),
1255+ controlFlags , softInputMode , windowFlags )) {
1256+ return ;
1257+ }
1258+ }
12081259
1260+ // For some reason we didn't do a startInput + windowFocusGain, so
1261+ // we'll just do a window focus gain and call it a day.
12091262 synchronized (mH ) {
12101263 try {
1211- final boolean isTextEditor = focusedView != null &&
1212- focusedView .onCheckIsTextEditor ();
12131264 mService .windowGainedFocus (mClient , rootView .getWindowToken (),
1214- focusedView != null , isTextEditor , softInputMode , first ,
1215- windowFlags );
1265+ controlFlags , softInputMode , windowFlags , null , null );
12161266 } catch (RemoteException e ) {
12171267 }
12181268 }
1219-
1220- if (startInput ) {
1221- startInputInner ();
1222- }
12231269 }
12241270
12251271 /** @hide */
@@ -1649,8 +1695,7 @@ void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
16491695 p .println (" mCurMethod=" + mCurMethod );
16501696 p .println (" mCurRootView=" + mCurRootView );
16511697 p .println (" mServedView=" + mServedView );
1652- p .println (" mNextServedNeedsStart=" + mNextServedNeedsStart
1653- + " mNextServedView=" + mNextServedView );
1698+ p .println (" mNextServedView=" + mNextServedView );
16541699 p .println (" mServedConnecting=" + mServedConnecting );
16551700 if (mCurrentTextBoxAttribute != null ) {
16561701 p .println (" mCurrentTextBoxAttribute:" );
0 commit comments