@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_ENTER_ACTION | EditorInfo.IME_ACTION_NONE; outAttrs.inputType = EditorInfo.TYPE_NULL; return new BaseInputConnection(this, false) { @Override public boolean deleteSurroundingText (int leftLength, int rightLength) { if (rightLength == 0 && leftLength == 0) { return this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); } for (int i = 0; i < leftLength; i++) { this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); } // TODO: forward delete return true; } }; }
public void testViaBackButtonOnView() { testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html"); sleep(); String url = testView.getUrl(); assertTrue(url.endsWith("sample2.html")); testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html"); sleep(); url = testView.getUrl(); assertTrue(url.endsWith("sample3.html")); BaseInputConnection viewConnection = new BaseInputConnection(testView, true); KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK); KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK); viewConnection.sendKeyEvent(backDown); viewConnection.sendKeyEvent(backUp); sleep(); url = testView.getUrl(); assertTrue(url.endsWith("sample2.html")); viewConnection.sendKeyEvent(backDown); viewConnection.sendKeyEvent(backUp); sleep(); url = testView.getUrl(); assertTrue(url.endsWith("index.html")); }
public void testViaBackButtonOnLayout() { testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html"); sleep(); String url = testView.getUrl(); assertTrue(url.endsWith("sample2.html")); testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html"); sleep(); url = testView.getUrl(); assertTrue(url.endsWith("sample3.html")); BaseInputConnection viewConnection = new BaseInputConnection(containerView, true); KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK); KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK); viewConnection.sendKeyEvent(backDown); viewConnection.sendKeyEvent(backUp); sleep(); url = testView.getUrl(); assertTrue(url.endsWith("sample2.html")); viewConnection.sendKeyEvent(backDown); viewConnection.sendKeyEvent(backUp); sleep(); url = testView.getUrl(); assertTrue(url.endsWith("index.html")); }
/** * Whether we want to be showing inline autocomplete results. We don't want to show them as the * user deletes input. Also if there is a composition (e.g. while using the Japanese IME), * we must not autocomplete or we'll destroy the composition. * @return Whether we want to be showing inline autocomplete results. */ public boolean shouldAutocomplete() { if (mLastUrlEditWasDelete) return false; Editable text = getText(); return isCursorAtEndOfTypedText() && !isPastedText() && !isHandlingBatchInput() && BaseInputConnection.getComposingSpanEnd(text) == BaseInputConnection.getComposingSpanStart(text); }
@Override public void afterTextChanged(Editable s) { boolean isComposing = BaseInputConnection.getComposingSpanStart(s) != -1; innerWatcher.afterTextChanged(s); if (isComposing) { inputMethodManager.restartInput(textView); } }
private void clean() { Editable text = mEditor.getText(); BaseInputConnection.removeComposingSpans(text); /* Cleanup ParagraphStyles to: - make sure spans are applied to whole paragraphs - remove obsolete spans - Note: the sequence is important */ Effects.cleanupParagraphs(mEditor); }
/** * Whether we want to be showing inline autocomplete results. We don't want to show them as the * user deletes input. Also if there is a composition (e.g. while using the Japanese IME), * we must not autocomplete or we'll destroy the composition. * @return Whether we want to be showing inline autocomplete results. */ private boolean shouldAutocomplete() { if (mLastUrlEditWasDelete) return false; Editable text = mUrlBar.getText(); return mUrlBar.isCursorAtEndOfTypedText() && !mUrlBar.isHandlingBatchInput() && BaseInputConnection.getComposingSpanEnd(text) == BaseInputConnection.getComposingSpanStart(text); }
/** * Whether we want to be showing inline autocomplete results. We don't want to show them as the * user deletes input. Also if there is a composition (e.g. while using the Japanese IME), * we must not autocomplete or we'll destroy the composition. * @return Whether we want to be showing inline autocomplete results. */ public boolean shouldAutocomplete() { if (mLastEditWasDelete) return false; Editable text = getText(); return isCursorAtEndOfTypedText() && !isHandlingBatchInput() && BaseInputConnection.getComposingSpanEnd(text) == BaseInputConnection.getComposingSpanStart(text); }
/** * @param editable The editable. * @return Debug string for the given {@Editable}. */ static String getEditableDebugString(Editable editable) { return String.format(Locale.US, "Editable {[%s] SEL[%d %d] COM[%d %d]}", editable.toString(), Selection.getSelectionStart(editable), Selection.getSelectionEnd(editable), BaseInputConnection.getComposingSpanStart(editable), BaseInputConnection.getComposingSpanEnd(editable)); }
protected GeckoInputConnection(View targetView, GeckoEditableClient editable) { super(targetView, true); mEditableClient = editable; mIMEState = IME_STATE_DISABLED; // InputConnection that sends keys for plugins, which don't have full editors mKeyInputConnection = new BaseInputConnection(targetView, false); }
@Override public InputConnection onCreateInputConnection (EditorInfo outAttrs) { // add this line, the IME can show the selectable words when use chinese input method editor. if (outAttrs != null) { outAttrs.imeOptions = outAttrs.imeOptions | EditorInfo.IME_FLAG_NO_EXTRACT_UI; } BaseInputConnection connection = new BaseInputConnection(this, false) { @Override public boolean deleteSurroundingText (int beforeLength, int afterLength) { int sdkVersion = android.os.Build.VERSION.SDK_INT; if (sdkVersion >= 16) { /* * In Jelly Bean, they don't send key events for delete. Instead, they send beforeLength = 1, afterLength = 0. So, * we'll just simulate what it used to do. */ if (beforeLength == 1 && afterLength == 0) { sendDownUpKeyEventForBackwardCompatibility(KeyEvent.KEYCODE_DEL); return true; } } return super.deleteSurroundingText(beforeLength, afterLength); } @TargetApi(16) private void sendDownUpKeyEventForBackwardCompatibility (final int code) { final long eventTime = SystemClock.uptimeMillis(); super.sendKeyEvent(new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE)); super.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE)); } }; return connection; }
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { return new BaseInputConnection(this, false) { @Override public boolean commitText(CharSequence text, int newCursorPosition) { // TODO Auto-generated method stub return super.commitText(text, newCursorPosition); } }; }
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { outAttrs.actionLabel = null; outAttrs.inputType = InputType.TYPE_NULL; /* TODO: If people complain about kbd not working, this is a possible workaround to * test and add an option for. // Workaround for IME's that don't support InputType.TYPE_NULL. outAttrs.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_FULLSCREEN; */ return new BaseInputConnection(this, false); }
@Override public boolean setComposingText(CharSequence text, int newCursorPosition) { Editable currentText = getText(); int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan); if (autoCompleteSpanStart >= 0) { int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText); // On certain device/keyboard combinations, the composing regions are specified // with a noticeable delay after the initial character is typed, and in certain // circumstances it does not check that the current state of the text matches the // expectations of it's composing region. // For example, you can be typing: // chrome://f // Chrome will autocomplete to: // chrome://f[lags] // And after the autocomplete has been set, the keyboard will set the composing // region to the last character and it assumes it is 'f' as it was the last // character the keyboard sent. If we commit this composition, the text will // look like: // chrome://flag[f] // And if we use the autocomplete clearing logic below, it will look like: // chrome://f[f] // To work around this, we see if the composition matches all the characters prior // to the autocomplete and just readjust the composing region to be that subset. // // See crbug.com/366732 if (composingEnd == currentText.length() && autoCompleteSpanStart >= text.length() && TextUtils.equals( currentText.subSequence( autoCompleteSpanStart - text.length(), autoCompleteSpanStart), text)) { setComposingRegion( autoCompleteSpanStart - text.length(), autoCompleteSpanStart); } // Once composing text is being modified, the autocomplete text has been accepted // or has to be deleted. mAutocompleteSpan.clearSpan(); Selection.setSelection(currentText, autoCompleteSpanStart); currentText.delete(autoCompleteSpanStart, currentText.length()); } return super.setComposingText(text, newCursorPosition); }
/** * Use {@link BaseInputConnection#removeComposingSpans * BaseInputConnection.removeComposingSpans()} to remove any IME composing * state from this text view. */ public void clearComposingText() { if (mText instanceof Spannable) { BaseInputConnection.removeComposingSpans((Spannable)mText); } }
@Override public boolean setComposingText(CharSequence text, int newCursorPosition) { if (DEBUG) Log.i(TAG, "setComposingText: [%s]", text); Editable currentText = getText(); int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan); if (autoCompleteSpanStart >= 0) { int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText); // On certain device/keyboard combinations, the composing regions are specified // with a noticeable delay after the initial character is typed, and in certain // circumstances it does not check that the current state of the text matches the // expectations of it's composing region. // For example, you can be typing: // chrome://f // Chrome will autocomplete to: // chrome://f[lags] // And after the autocomplete has been set, the keyboard will set the composing // region to the last character and it assumes it is 'f' as it was the last // character the keyboard sent. If we commit this composition, the text will // look like: // chrome://flag[f] // And if we use the autocomplete clearing logic below, it will look like: // chrome://f[f] // To work around this, we see if the composition matches all the characters prior // to the autocomplete and just readjust the composing region to be that subset. // // See crbug.com/366732 if (composingEnd == currentText.length() && autoCompleteSpanStart >= text.length() && TextUtils.equals( currentText.subSequence(autoCompleteSpanStart - text.length(), autoCompleteSpanStart), text)) { setComposingRegion( autoCompleteSpanStart - text.length(), autoCompleteSpanStart); } // Once composing text is being modified, the autocomplete text has been accepted // or has to be deleted. mAutocompleteSpan.clearSpan(); Selection.setSelection(currentText, autoCompleteSpanStart); currentText.delete(autoCompleteSpanStart, currentText.length()); } return super.setComposingText(text, newCursorPosition); }
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE; outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI; outAttrs.inputType = inputType; return new BaseInputConnection(this, false) { @Override public boolean performEditorAction(int actionCode) { if (actionCode == EditorInfo.IME_ACTION_DONE) { InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(CanvasView.this.getWindowToken(), 0); return true; } else { return super.performEditorAction(actionCode); } } @Override public boolean commitText(CharSequence text, int newCursorPosition) { if (keyListener != null) { keyListener.insert(keyListener.getCaretPosition(), text); } return true; } @Override public boolean deleteSurroundingText(int leftLength, int rightLength) { if (keyListener != null) { int caret = keyListener.getCaretPosition(); keyListener.delete(caret - leftLength, caret + rightLength); } return true; } @Override public boolean sendKeyEvent(KeyEvent event) { return super.sendKeyEvent(event); } }; }
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { BaseInputConnection inputConnection = new BaseInputConnection(this, true); outAttrs.inputType = InputType.TYPE_CLASS_NUMBER; return inputConnection; }
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { // manage events from the virtual keyboard outAttrs.actionLabel = null; outAttrs.label = "time"; outAttrs.inputType = InputType.TYPE_CLASS_NUMBER; outAttrs.imeOptions = mImeOptions | EditorInfo.IME_FLAG_NO_EXTRACT_UI; if ((outAttrs.imeOptions & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_UNSPECIFIED) { if (focusSearch(FOCUS_DOWN) != null) { outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT; } else { outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE; } } return new BaseInputConnection(this, false) { @Override public boolean performEditorAction(int actionCode) { if (actionCode == EditorInfo.IME_ACTION_DONE) { hideKeyboard(); currentPosition = POSITION_NONE; updateText(); } else if (actionCode == EditorInfo.IME_ACTION_NEXT){ View v = focusSearch(FOCUS_DOWN); if (v!=null) { v.requestFocus(FOCUS_DOWN); } } return true; } @Override public boolean deleteSurroundingText(int beforeLength, int afterLength) { onKeyEvent(KeyEvent.KEYCODE_DEL, null); return true; } @Override public boolean sendKeyEvent(KeyEvent event) { onKeyEvent(event.getKeyCode(), event); return true; } }; }