boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition, boolean isCommit) { if (mNativeImeAdapterAndroid == 0) return false; // Committing an empty string finishes the current composition. boolean isFinish = text.isEmpty(); mViewEmbedder.onImeEvent(isFinish); int keyCode = shouldSendKeyEventWithKeyCode(text); long timeStampMs = System.currentTimeMillis(); if (keyCode != COMPOSITION_KEY_CODE) { sendKeyEventWithKeyCode(keyCode, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); } else { nativeSendSyntheticKeyEvent( mNativeImeAdapterAndroid, sEventTypeRawKeyDown, timeStampMs, keyCode, 0); if (isCommit) { nativeCommitText(mNativeImeAdapterAndroid, text); } else { nativeSetComposingText(mNativeImeAdapterAndroid, text, newCursorPosition); } nativeSendSyntheticKeyEvent( mNativeImeAdapterAndroid, sEventTypeKeyUp, timeStampMs, keyCode, 0); } return true; }
/** @see BaseInputConnection#performEditorAction(int) */ @Override public boolean performEditorAction(int actionCode) { if (DEBUG) Log.w(TAG, "performEditorAction [" + actionCode + "]"); if (actionCode == EditorInfo.IME_ACTION_NEXT) { restartInput(); // Send TAB key event long timeStampMs = SystemClock.uptimeMillis(); mImeAdapter.sendSyntheticKeyEvent( WebInputEventType.RawKeyDown, timeStampMs, KeyEvent.KEYCODE_TAB, 0, 0); } else { mImeAdapter.sendKeyEventWithKeyCode( KeyEvent.KEYCODE_ENTER, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.FLAG_EDITOR_ACTION); } return true; }
private boolean deleteSurroundingTextImpl( int beforeLength, int afterLength, boolean fromPhysicalKey) { if (DEBUG) { Log.w( TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + " " + fromPhysicalKey + "]"); } if (mPendingAccent != 0) { finishComposingText(); } int originalBeforeLength = beforeLength; int originalAfterLength = afterLength; int selectionStart = Selection.getSelectionStart(mEditable); int selectionEnd = Selection.getSelectionEnd(mEditable); int availableBefore = selectionStart; int availableAfter = mEditable.length() - selectionEnd; beforeLength = Math.min(beforeLength, availableBefore); afterLength = Math.min(afterLength, availableAfter); // Adjust these values even before calling super.deleteSurroundingText() to be consistent // with the super class. if (isIndexBetweenUtf16SurrogatePair(mEditable, selectionStart - beforeLength)) { beforeLength += 1; } if (isIndexBetweenUtf16SurrogatePair(mEditable, selectionEnd + afterLength)) { afterLength += 1; } super.deleteSurroundingText(beforeLength, afterLength); updateSelectionIfRequired(); // If this was called due to a physical key, no need to generate a key event here as // the caller will take care of forwarding the original. if (fromPhysicalKey) { return true; } // For single-char deletion calls |ImeAdapter.sendKeyEventWithKeyCode| with the real key // code. For multi-character deletion, executes deletion by calling // |ImeAdapter.deleteSurroundingText| and sends synthetic key events with a dummy key code. int keyCode = KeyEvent.KEYCODE_UNKNOWN; if (originalBeforeLength == 1 && originalAfterLength == 0) { keyCode = KeyEvent.KEYCODE_DEL; } else if (originalBeforeLength == 0 && originalAfterLength == 1) { keyCode = KeyEvent.KEYCODE_FORWARD_DEL; } boolean result = true; if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { result = mImeAdapter.sendSyntheticKeyEvent( WebInputEventType.RawKeyDown, SystemClock.uptimeMillis(), keyCode, 0, 0); result &= mImeAdapter.deleteSurroundingText(beforeLength, afterLength); result &= mImeAdapter.sendSyntheticKeyEvent( WebInputEventType.KeyUp, SystemClock.uptimeMillis(), keyCode, 0, 0); } else { mImeAdapter.sendKeyEventWithKeyCode( keyCode, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); } return result; }