Merge "Unbalanced batch edit begin and end leave TextView unresponsive"

This commit is contained in:
Gilles Debunne
2012-01-25 15:08:29 -08:00
committed by Android (Google) Code Review
2 changed files with 72 additions and 26 deletions

View File

@@ -651,19 +651,7 @@ public final class InputMethodManager {
}
}
if (mServedInputConnection != null) {
// We need to tell the previously served view that it is no
// longer the input target, so it can reset its state. Schedule
// this call on its window's Handler so it will be on the correct
// thread and outside of our lock.
Handler vh = mServedView.getHandler();
if (vh != null) {
// This will result in a call to reportFinishInputConnection()
// below.
vh.sendMessage(vh.obtainMessage(ViewRootImpl.FINISH_INPUT_CONNECTION,
mServedInputConnection));
}
}
notifyInputConnectionFinished();
mServedView = null;
mCompletions = null;
@@ -671,7 +659,25 @@ public final class InputMethodManager {
clearConnectionLocked();
}
}
/**
* Notifies the served view that the current InputConnection will no longer be used.
*/
private void notifyInputConnectionFinished() {
if (mServedView != null && mServedInputConnection != null) {
// We need to tell the previously served view that it is no
// longer the input target, so it can reset its state. Schedule
// this call on its window's Handler so it will be on the correct
// thread and outside of our lock.
Handler vh = mServedView.getHandler();
if (vh != null) {
// This will result in a call to reportFinishInputConnection() below.
vh.sendMessage(vh.obtainMessage(ViewRootImpl.FINISH_INPUT_CONNECTION,
mServedInputConnection));
}
}
}
/**
* Called from the FINISH_INPUT_CONNECTION message above.
* @hide
@@ -681,7 +687,7 @@ public final class InputMethodManager {
ic.finishComposingText();
}
}
public void displayCompletions(View view, CompletionInfo[] completions) {
checkFocus();
synchronized (mH) {
@@ -831,7 +837,7 @@ public final class InputMethodManager {
* shown with {@link #SHOW_FORCED}.
*/
public static final int HIDE_NOT_ALWAYS = 0x0002;
/**
* Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
* without a result: request to hide the soft input window from the
@@ -993,7 +999,7 @@ public final class InputMethodManager {
tba.fieldId = view.getId();
InputConnection ic = view.onCreateInputConnection(tba);
if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
synchronized (mH) {
// Now that we are locked again, validate that our state hasn't
// changed.
@@ -1012,6 +1018,8 @@ public final class InputMethodManager {
// Hook 'em up and let 'er rip.
mCurrentTextBoxAttribute = tba;
mServedConnecting = false;
// Notify the served view that its previous input connection is finished
notifyInputConnectionFinished();
mServedInputConnection = ic;
IInputContext servedContext;
if (ic != null) {
@@ -1115,7 +1123,7 @@ public final class InputMethodManager {
}
}
void scheduleCheckFocusLocked(View view) {
static void scheduleCheckFocusLocked(View view) {
Handler vh = view.getHandler();
if (vh != null && !vh.hasMessages(ViewRootImpl.CHECK_FOCUS)) {
// This will result in a call to checkFocus() below.

View File

@@ -35,6 +35,11 @@ public class EditableInputConnection extends BaseInputConnection {
private final TextView mTextView;
// Keeps track of nested begin/end batch edit to ensure this connection always has a
// balanced impact on its associated TextView.
// A negative value means that this connection has been finished by the InputMethodManager.
private int mBatchEditNesting;
public EditableInputConnection(TextView textview) {
super(textview, true);
mTextView = textview;
@@ -48,19 +53,35 @@ public class EditableInputConnection extends BaseInputConnection {
}
return null;
}
@Override
public boolean beginBatchEdit() {
mTextView.beginBatchEdit();
return true;
synchronized(this) {
if (mBatchEditNesting >= 0) {
mTextView.beginBatchEdit();
mBatchEditNesting++;
return true;
}
}
return false;
}
@Override
public boolean endBatchEdit() {
mTextView.endBatchEdit();
return true;
synchronized(this) {
if (mBatchEditNesting > 0) {
// When the connection is reset by the InputMethodManager and finishComposingText
// is called, some endBatchEdit calls may still be asynchronously received from the
// IME. Do not take these into account, thus ensuring that this IC's final
// contribution to mTextView's nested batch edit count is zero.
mTextView.endBatchEdit();
mBatchEditNesting--;
return true;
}
}
return false;
}
@Override
public boolean clearMetaKeyStates(int states) {
final Editable content = getEditable();
@@ -76,7 +97,24 @@ public class EditableInputConnection extends BaseInputConnection {
}
return true;
}
@Override
public boolean finishComposingText() {
final boolean superResult = super.finishComposingText();
synchronized(this) {
if (mBatchEditNesting < 0) {
// The connection was already finished
return false;
}
while (mBatchEditNesting > 0) {
endBatchEdit();
}
// Will prevent any further calls to begin or endBatchEdit
mBatchEditNesting = -1;
}
return superResult;
}
@Override
public boolean commitCompletion(CompletionInfo text) {
if (DEBUG) Log.v(TAG, "commitCompletion " + text);