Skip to content

Commit 133dc2d

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Fix issue #6048808: sometimes auto-correct is inactive" into ics-mr1
2 parents 816b873 + 7663d80 commit 133dc2d

File tree

3 files changed

+172
-81
lines changed

3 files changed

+172
-81
lines changed

core/java/android/view/inputmethod/InputMethodManager.java

Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.android.internal.view.InputBindResult;
2727

2828
import android.content.Context;
29-
import android.content.pm.PackageManager;
3029
import android.graphics.Rect;
3130
import android.os.Bundle;
3231
import 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:");

core/java/com/android/internal/view/IInputMethodManager.aidl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,17 @@ interface IInputMethodManager {
4343
void removeClient(in IInputMethodClient client);
4444

4545
InputBindResult startInput(in IInputMethodClient client,
46-
IInputContext inputContext, in EditorInfo attribute,
47-
boolean initial, boolean needResult);
46+
IInputContext inputContext, in EditorInfo attribute, int controlFlags);
4847
void finishInput(in IInputMethodClient client);
4948
boolean showSoftInput(in IInputMethodClient client, int flags,
5049
in ResultReceiver resultReceiver);
5150
boolean hideSoftInput(in IInputMethodClient client, int flags,
5251
in ResultReceiver resultReceiver);
53-
void windowGainedFocus(in IInputMethodClient client, in IBinder windowToken,
54-
boolean viewHasFocus, boolean isTextEditor,
55-
int softInputMode, boolean first, int windowFlags);
52+
// Report that a window has gained focus. If 'attribute' is non-null,
53+
// this will also do a startInput.
54+
InputBindResult windowGainedFocus(in IInputMethodClient client, in IBinder windowToken,
55+
int controlFlags, int softInputMode, int windowFlags,
56+
in EditorInfo attribute, IInputContext inputContext);
5657

5758
void showInputMethodPickerFromClient(in IInputMethodClient client);
5859
void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);

0 commit comments

Comments
 (0)