Bug 1384829 - 1. Always perform shadow text actions; r?esawin
We want to always perform actions on the shadow text side even if a
particular GeckoEditable instance is disconnected from Gecko, because
there could be other users of Editable that still expect the object to
perform valid actions.
MozReview-Commit-ID: 48OIEaPZqUE
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
@@ -446,18 +446,43 @@ final class GeckoEditable extends IGecko
private void icOfferAction(final Action action) {
if (DEBUG) {
assertOnIcThread();
Log.d(LOGTAG, "offer: Action(" +
getConstantName(Action.class, "TYPE_", action.mType) + ")");
}
+ switch (action.mType) {
+ case Action.TYPE_EVENT:
+ case Action.TYPE_SET_HANDLER:
+ break;
+
+ case Action.TYPE_SET_SPAN:
+ mText.shadowSetSpan(action.mSpanObject, action.mStart,
+ action.mEnd, action.mSpanFlags);
+ break;
+
+ case Action.TYPE_REMOVE_SPAN:
+ action.mSpanFlags = mText.getShadowText().getSpanFlags(action.mSpanObject);
+ mText.shadowRemoveSpan(action.mSpanObject);
+ break;
+
+ case Action.TYPE_REPLACE_TEXT:
+ mText.shadowReplace(action.mStart, action.mEnd, action.mSequence);
+ break;
+
+ default:
+ throw new IllegalStateException("Action not processed");
+ }
+
+ // Always perform actions on the shadow text side above, so we still act as a
+ // valid Editable object, but don't send the actions to Gecko below if we haven't
+ // been focused or initialized, or we've been destroyed.
if (mFocusedChild == null || mListener == null) {
- // We haven't been focused or initialized, or we've been destroyed.
return;
}
mActions.offer(action);
try {
icPerformAction(action);
} catch (final RemoteException e) {
@@ -475,35 +500,31 @@ final class GeckoEditable extends IGecko
break;
case Action.TYPE_SET_SPAN: {
final boolean needUpdate = (action.mSpanFlags & Spanned.SPAN_INTERMEDIATE) == 0 &&
((action.mSpanFlags & Spanned.SPAN_COMPOSING) != 0 ||
action.mSpanObject == Selection.SELECTION_START ||
action.mSpanObject == Selection.SELECTION_END);
- mText.shadowSetSpan(action.mSpanObject, action.mStart,
- action.mEnd, action.mSpanFlags);
action.mSequence = TextUtils.substring(
mText.getShadowText(), action.mStart, action.mEnd);
mNeedUpdateComposition |= needUpdate;
if (needUpdate) {
icMaybeSendComposition(mText.getShadowText(), SEND_COMPOSITION_NOTIFY_GECKO |
SEND_COMPOSITION_KEEP_CURRENT);
}
mFocusedChild.onImeSynchronize();
break;
}
case Action.TYPE_REMOVE_SPAN: {
- final int flags = mText.getShadowText().getSpanFlags(action.mSpanObject);
- final boolean needUpdate = (flags & Spanned.SPAN_INTERMEDIATE) == 0 &&
- (flags & Spanned.SPAN_COMPOSING) != 0;
- mText.shadowRemoveSpan(action.mSpanObject);
+ final boolean needUpdate = (action.mSpanFlags & Spanned.SPAN_INTERMEDIATE) == 0 &&
+ (action.mSpanFlags & Spanned.SPAN_COMPOSING) != 0;
mNeedUpdateComposition |= needUpdate;
if (needUpdate) {
icMaybeSendComposition(mText.getShadowText(), SEND_COMPOSITION_NOTIFY_GECKO |
SEND_COMPOSITION_KEEP_CURRENT);
}
mFocusedChild.onImeSynchronize();
@@ -516,17 +537,16 @@ final class GeckoEditable extends IGecko
// Because we get composition styling here essentially for free,
// we don't need to check if we're in batch mode.
if (!icMaybeSendComposition(
action.mSequence, SEND_COMPOSITION_USE_ENTIRE_TEXT)) {
// Since we don't have a composition, we can try sending key events.
sendCharKeyEvents(action);
}
- mText.shadowReplace(action.mStart, action.mEnd, action.mSequence);
mFocusedChild.onImeReplaceText(
action.mStart, action.mEnd, action.mSequence.toString());
break;
default:
throw new IllegalStateException("Action not processed");
}
}