Index: content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
index 19bcb89d1ecde85d5ac9d5fce66f463b7e10e045..092ffbee345c5ffeb93623e852d05c5e1920f9ca 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
@@ -10,6 +10,7 @@ import android.text.InputType; |
import android.text.Selection; |
import android.text.TextUtils; |
import android.util.Log; |
+import android.view.KeyCharacterMap; |
import android.view.KeyEvent; |
import android.view.View; |
import android.view.inputmethod.BaseInputConnection; |
@@ -27,6 +28,7 @@ import org.chromium.base.VisibleForTesting; |
public class AdapterInputConnection extends BaseInputConnection { |
private static final String TAG = "AdapterInputConnection"; |
private static final boolean DEBUG = false; |
+ private static final int NO_ACCENT = 0; |
/** |
* Selection value should be -1 if not known. See EditorInfo.java for details. |
*/ |
@@ -39,6 +41,7 @@ public class AdapterInputConnection extends BaseInputConnection { |
private boolean mSingleLine; |
private int mNumNestedBatchEdits = 0; |
+ private int mPendingAccent; |
private int mLastUpdateSelectionStart = INVALID_SELECTION; |
private int mLastUpdateSelectionEnd = INVALID_SELECTION; |
@@ -125,6 +128,16 @@ public class AdapterInputConnection extends BaseInputConnection { |
updateSelectionIfRequired(); |
} |
+ public static int maybeAddAccentToCharacter(int accentChar, int unicodeChar) { |
+ if (accentChar != NO_ACCENT) { |
+ int combinedChar = KeyEvent.getDeadChar(accentChar, unicodeChar); |
+ if (combinedChar != 0) { |
+ return combinedChar; |
+ } |
+ } |
+ return unicodeChar; |
+ } |
+ |
/** |
* Updates the AdapterInputConnection's internal representation of the text being edited and |
* its selection and composition properties. The resulting Editable is accessible through the |
@@ -215,6 +228,8 @@ public class AdapterInputConnection extends BaseInputConnection { |
mLastUpdateSelectionEnd = selectionEnd; |
mLastUpdateCompositionStart = compositionStart; |
mLastUpdateCompositionEnd = compositionEnd; |
+ // Change in selection or cursor position invalidates any pending accent. |
+ mPendingAccent = NO_ACCENT; |
} |
/** |
@@ -368,6 +383,14 @@ public class AdapterInputConnection extends BaseInputConnection { |
if (DEBUG) { |
Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getKeyCode() + "]"); |
} |
+ |
+ // Short-cut modifier keys so they're not affected by accents. |
+ if (KeyEvent.isModifierKey(event.getKeyCode())) { |
+ return mImeAdapter.translateAndSendNativeEvents(event, NO_ACCENT); |
+ } |
+ |
+ int unicodeChar = event.getUnicodeChar(); |
+ |
// If this is a key-up, and backspace/del or if the key has a character representation, |
// need to update the underlying Editable (i.e. the local representation of the text |
// being edited). |
@@ -378,26 +401,24 @@ public class AdapterInputConnection extends BaseInputConnection { |
} else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) { |
deleteSurroundingText(0, 1); |
return true; |
- } else { |
- int unicodeChar = event.getUnicodeChar(); |
- if (unicodeChar != 0) { |
- int selectionStart = Selection.getSelectionStart(mEditable); |
- int selectionEnd = Selection.getSelectionEnd(mEditable); |
- if (selectionStart > selectionEnd) { |
- int temp = selectionStart; |
- selectionStart = selectionEnd; |
- selectionEnd = temp; |
- } |
- mEditable.replace(selectionStart, selectionEnd, |
- Character.toString((char) unicodeChar)); |
+ } else if (unicodeChar != 0) { |
+ int selectionStart = Selection.getSelectionStart(mEditable); |
+ int selectionEnd = Selection.getSelectionEnd(mEditable); |
+ if (selectionStart > selectionEnd) { |
+ int temp = selectionStart; |
+ selectionStart = selectionEnd; |
+ selectionEnd = temp; |
} |
+ int combinedChar = maybeAddAccentToCharacter(mPendingAccent, unicodeChar); |
+ mEditable.replace(selectionStart, selectionEnd, |
+ Character.toString((char) combinedChar)); |
} |
} else if (event.getAction() == KeyEvent.ACTION_DOWN) { |
// TODO(aurimas): remove this workaround when crbug.com/278584 is fixed. |
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { |
beginBatchEdit(); |
finishComposingText(); |
- mImeAdapter.translateAndSendNativeEvents(event); |
+ mImeAdapter.translateAndSendNativeEvents(event, 0); |
endBatchEdit(); |
return true; |
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { |
@@ -406,7 +427,43 @@ public class AdapterInputConnection extends BaseInputConnection { |
return true; |
} |
} |
- mImeAdapter.translateAndSendNativeEvents(event); |
+ mImeAdapter.translateAndSendNativeEvents(event, mPendingAccent); |
+ |
+ // Physical keyboards also have their events come through here though not |
+ // by BaseInputConnection. In order to support "accent" key sequences |
+ // such as "~n" or "^o" we have to record that one has been pressed |
+ // and, if an accentable letter follows, delete the accent glyph and |
+ // insert the composed character. |
+ |
+ // Copy class variable to local because class version may get indirectly |
+ // cleared by the deleteSurroundingText() call below. |
+ int pendingAccent = mPendingAccent; |
+ |
+ if ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) != 0) { |
+ pendingAccent = unicodeChar & KeyCharacterMap.COMBINING_ACCENT_MASK; |
+ } else if (pendingAccent != NO_ACCENT) { |
+ if (event.getAction() == KeyEvent.ACTION_DOWN) { |
+ int combined = KeyEvent.getDeadChar(pendingAccent, unicodeChar); |
+ if (combined != 0) { |
+ // Previous accent combines with new character to create |
+ // a new accented character. First delete the displayed |
+ // accent so it appears overwritten by the composition. |
+ super.deleteSurroundingText(1, 0); |
+ mImeAdapter.deleteSurroundingText(1, 0); |
+ } else { |
+ // Previous accent doesn't combine with this character |
+ // so assume both are completely independent. |
+ pendingAccent = NO_ACCENT; |
+ } |
+ } |
+ |
+ if (event.getAction() == KeyEvent.ACTION_UP) { |
+ // Forget accent after release of key being accented. |
+ pendingAccent = NO_ACCENT; |
+ } |
+ } |
+ |
+ mPendingAccent = pendingAccent; |
return true; |
} |
@@ -448,6 +505,7 @@ public class AdapterInputConnection extends BaseInputConnection { |
if (DEBUG) Log.w(TAG, "restartInput"); |
getInputMethodManagerWrapper().restartInput(mInternalView); |
mNumNestedBatchEdits = 0; |
+ mPendingAccent = NO_ACCENT; |
} |
/** |