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..136a878158ec80c583e08a4018421f2d3a556978 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; |
@@ -39,6 +40,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; |
@@ -215,6 +217,8 @@ public class AdapterInputConnection extends BaseInputConnection { |
mLastUpdateSelectionEnd = selectionEnd; |
mLastUpdateCompositionStart = compositionStart; |
mLastUpdateCompositionEnd = compositionEnd; |
+ // Change in selection or cursor position invalidates any pending accent. |
+ mPendingAccent = 0; |
Ted C
2014/12/03 02:30:14
do we need to do this as well on restartInput (or
bcwhite
2014/12/03 15:49:09
Seems the smart thing to do. Done.
|
} |
/** |
@@ -368,6 +372,50 @@ public class AdapterInputConnection extends BaseInputConnection { |
if (DEBUG) { |
Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getKeyCode() + "]"); |
} |
+ |
+ if (KeyEvent.isModifierKey(event.getKeyCode())) { |
+ return mImeAdapter.translateAndSendNativeEvents(event, 0); |
+ } |
+ |
+ // 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. |
+ |
+ int unicodeChar = event.getUnicodeChar(); |
+ int pendingAccent = mPendingAccent; |
+ int nextAccent = pendingAccent; |
Ted C
2014/12/03 02:30:14
In what cases is this used? Just wondering what c
bcwhite
2014/12/03 15:49:09
It's used to keep all the accent-processing code a
|
+ |
+ if ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) != 0) { |
+ pendingAccent = 0; |
+ nextAccent = unicodeChar & KeyCharacterMap.COMBINING_ACCENT_MASK; |
+ } else if (pendingAccent != 0) { |
+ 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. |
+ // Note that deleting the displayed accent will cause an |
+ // update and clearing of mPendingAccent which is why we've |
+ // copied it to a local variable above. |
+ super.deleteSurroundingText(1, 0); |
+ mImeAdapter.deleteSurroundingText(1, 0); |
+ } else { |
+ // Previous accent doesn't combine with this character |
+ // so assume both are completely independent. |
+ pendingAccent = 0; |
+ nextAccent = 0; |
+ } |
+ } |
+ |
+ if (event.getAction() == KeyEvent.ACTION_UP) { |
+ // Forget accent after release of key being accented. |
+ nextAccent = 0; |
+ } |
+ } |
+ |
// 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 +426,30 @@ 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; |
+ } else if (unicodeChar != 0) { |
+ int combinedChar = unicodeChar; |
+ if (pendingAccent != 0) { |
+ combinedChar = KeyEvent.getDeadChar(pendingAccent, unicodeChar); |
+ if (combinedChar == 0) { |
+ combinedChar = unicodeChar; |
} |
- mEditable.replace(selectionStart, selectionEnd, |
- Character.toString((char) unicodeChar)); |
} |
+ 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) 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 +458,8 @@ public class AdapterInputConnection extends BaseInputConnection { |
return true; |
} |
} |
- mImeAdapter.translateAndSendNativeEvents(event); |
+ mImeAdapter.translateAndSendNativeEvents(event, pendingAccent); |
+ mPendingAccent = nextAccent; |
return true; |
} |