Bug 835906 - Handle off-thread GeckoEditable and GeckoInputConnection calls; r=cpeterson

This commit is contained in:
Jim Chen 2013-02-08 16:07:12 -05:00
parent 9d18f3a9c3
commit ddca886e23
2 changed files with 57 additions and 10 deletions

View File

@ -458,10 +458,17 @@ final class GeckoEditable
// GeckoEditableClient interface
@Override
public void sendEvent(GeckoEvent event) {
if (DEBUG) {
// GeckoEditableClient methods should all be called from the IC thread
assertOnIcThread();
public void sendEvent(final GeckoEvent event) {
if (!onIcThread()) {
// Events may get dispatched to the main thread;
// reroute to our IC thread instead
mIcRunHandler.post(new Runnable() {
@Override
public void run() {
sendEvent(event);
}
});
return;
}
/*
We are actually sending two events to Gecko here,
@ -477,18 +484,24 @@ final class GeckoEditable
@Override
public Editable getEditable() {
if (DEBUG) {
// GeckoEditableClient methods should all be called from the IC thread
assertOnIcThread();
if (!onIcThread()) {
// Android may be holding an old InputConnection; ignore
if (DEBUG) {
Log.i(LOGTAG, "getEditable() called on non-IC thread");
}
return null;
}
return mProxy;
}
@Override
public void setUpdateGecko(boolean update) {
if (DEBUG) {
// GeckoEditableClient methods should all be called from the IC thread
assertOnIcThread();
if (!onIcThread()) {
// Android may be holding an old InputConnection; ignore
if (DEBUG) {
Log.i(LOGTAG, "setUpdateGecko() called on non-IC thread");
}
return;
}
if (update) {
icUpdateGecko(false);

View File

@ -481,6 +481,40 @@ class GeckoInputConnection
return this;
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
// BaseInputConnection.sendKeyEvent() dispatches the key event to the main thread.
// In order to ensure events are processed in the proper order, we must block the
// IC thread until the main thread finishes processing the key event
super.sendKeyEvent(event);
final View v = getView();
if (v == null) {
return false;
}
final Handler icHandler = mEditableClient.getInputConnectionHandler();
final Handler mainHandler = v.getRootView().getHandler();
if (icHandler.getLooper() != mainHandler.getLooper()) {
// We are on separate IC thread but the event is queued on the main thread;
// wait on IC thread until the main thread processes our posted Runnable. At
// that point the key event has already been processed.
synchronized (icHandler) {
mainHandler.post(new Runnable() {
@Override
public void run() {
synchronized (icHandler) {
icHandler.notify();
}
}
});
try {
icHandler.wait();
} catch (InterruptedException e) {
}
}
}
return false; // seems to always return false
}
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
return false;
}