@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); // The Awesome Bar will receive focus when the Awesome Screen first opens or after the user // closes the "Select Input Method" window. If the input method changes to or from Swype, // then toggle the URL mode flag. Swype's URL mode disables the automatic word spacing that // Swype users expect when entering search queries, but does not add any special VKB keys // like ".com" or "/" that would be useful for entering URLs. if (!hasFocus) return; boolean wasUsingSwype = mIsUsingSwype; mIsUsingSwype = sSwypeInputMethods.contains(InputMethods.getCurrentInputMethod(this)); if (mIsUsingSwype == wasUsingSwype) return; int currentInputType = mText.getInputType(); int newInputType = mIsUsingSwype ? (currentInputType & ~InputType.TYPE_TEXT_VARIATION_URI) // URL=OFF : (currentInputType | InputType.TYPE_TEXT_VARIATION_URI); // URL=ON mText.setRawInputType(newInputType); }
private void restartInput() { mLastRestartInputTime = SystemClock.uptimeMillis(); final InputMethodManager imm = getInputMethodManager(); if (imm == null) { return; } final View v = getView(); // InputMethodManager has internal logic to detect if we are restarting input // in an already focused View, which is the case here because all content text // fields are inside one LayerView. When this happens, InputMethodManager will // tell the input method to soft reset instead of hard reset. Stock latin IME // on Android 4.2+ has a quirk that when it soft resets, it does not clear the // composition. The following workaround tricks the IME into clearing the // composition when soft resetting. if (InputMethods.needsSoftResetWorkaround(mCurrentInputMethod)) { // Fake a selection change, because the IME clears the composition when // the selection changes, even if soft-resetting. Offsets here must be // different from the previous selection offsets, and -1 seems to be a // reasonable, deterministic value notifySelectionChange(-1, -1); } imm.restartInput(v); }
private static InputMethodManager getInputMethodManager() { View view = getView(); if (view == null) { return null; } Context context = view.getContext(); return InputMethods.getInputMethodManager(context); }
@Override public boolean commitText(CharSequence text, int newCursorPosition) { if (InputMethods.shouldCommitCharAsKey(mCurrentInputMethod) && text.length() == 1 && newCursorPosition > 0) { if (DEBUG) { Log.d(LOGTAG, "committing \"" + text + "\" as key"); } // mKeyInputConnection is a BaseInputConnection that commits text as keys; // but we first need to replace any composing span with a selection, // so that the new key events will generate characters to replace // text from the old composing span return replaceComposingSpanWithSelection() && mKeyInputConnection.commitText(text, newCursorPosition); } return super.commitText(text, newCursorPosition); }
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { if (mIMEState == IME_STATE_DISABLED) { return null; } outAttrs.inputType = InputType.TYPE_CLASS_TEXT; outAttrs.imeOptions = EditorInfo.IME_ACTION_NONE; outAttrs.actionLabel = null; if (mIMEState == IME_STATE_PASSWORD || "password".equalsIgnoreCase(mIMETypeHint)) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD; else if (mIMEState == IME_STATE_PLUGIN) outAttrs.inputType = InputType.TYPE_NULL; // "send key events" mode else if (mIMETypeHint.equalsIgnoreCase("url")) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_URI; else if (mIMETypeHint.equalsIgnoreCase("email")) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; else if (mIMETypeHint.equalsIgnoreCase("search")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH; else if (mIMETypeHint.equalsIgnoreCase("tel")) outAttrs.inputType = InputType.TYPE_CLASS_PHONE; else if (mIMETypeHint.equalsIgnoreCase("number") || mIMETypeHint.equalsIgnoreCase("range")) outAttrs.inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL; else if (mIMETypeHint.equalsIgnoreCase("week") || mIMETypeHint.equalsIgnoreCase("month")) outAttrs.inputType = InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE; else if (mIMEModeHint.equalsIgnoreCase("numeric")) outAttrs.inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL; else if (mIMEModeHint.equalsIgnoreCase("digit")) outAttrs.inputType = InputType.TYPE_CLASS_NUMBER; else { // TYPE_TEXT_FLAG_IME_MULTI_LINE flag makes the fullscreen IME line wrap outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE; if (mIMETypeHint.equalsIgnoreCase("textarea") || mIMETypeHint.length() == 0) { // empty mIMETypeHint indicates contentEditable/designMode documents outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE; } if (mIMEModeHint.equalsIgnoreCase("uppercase")) outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS; else if (mIMEModeHint.equalsIgnoreCase("titlecase")) outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS; else if (mIMETypeHint.equalsIgnoreCase("text") && !mIMEModeHint.equalsIgnoreCase("autocapitalized")) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_NORMAL; else if (!mIMEModeHint.equalsIgnoreCase("lowercase")) outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; // auto-capitalized mode is the default for types other than text } if (mIMEActionHint.equalsIgnoreCase("go")) outAttrs.imeOptions = EditorInfo.IME_ACTION_GO; else if (mIMEActionHint.equalsIgnoreCase("done")) outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE; else if (mIMEActionHint.equalsIgnoreCase("next")) outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT; else if (mIMEActionHint.equalsIgnoreCase("search")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH; else if (mIMEActionHint.equalsIgnoreCase("send")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEND; else if (mIMEActionHint.length() > 0) { if (DEBUG) Log.w(LOGTAG, "Unexpected mIMEActionHint=\"" + mIMEActionHint + "\""); outAttrs.actionLabel = mIMEActionHint; } Context context = GoannaAppShell.getContext(); DisplayMetrics metrics = context.getResources().getDisplayMetrics(); if (Math.min(metrics.widthPixels, metrics.heightPixels) > INLINE_IME_MIN_DISPLAY_SIZE) { // prevent showing full-screen keyboard only when the screen is tall enough // to show some reasonable amount of the page (see bug 752709) outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN; } if (DEBUG) { Log.d( LOGTAG, "mapped IME states to: inputType = " + Integer.toHexString(outAttrs.inputType) + ", imeOptions = " + Integer.toHexString(outAttrs.imeOptions)); } String prevInputMethod = mCurrentInputMethod; mCurrentInputMethod = InputMethods.getCurrentInputMethod(context); if (DEBUG) { Log.d(LOGTAG, "IME: CurrentInputMethod=" + mCurrentInputMethod); } // If the user has changed IMEs, then notify input method observers. if (!mCurrentInputMethod.equals(prevInputMethod) && GoannaAppShell.getGoannaInterface() != null) { FormAssistPopup popup = GoannaAppShell.getGoannaInterface().getFormAssistPopup(); if (popup != null) { popup.onInputMethodChanged(mCurrentInputMethod); } } if (mIMEState == IME_STATE_PLUGIN) { // Since we are using a temporary string as the editable, the selection is at 0 outAttrs.initialSelStart = 0; outAttrs.initialSelEnd = 0; return mKeyInputConnection; } Editable editable = getEditable(); outAttrs.initialSelStart = Selection.getSelectionStart(editable); outAttrs.initialSelEnd = Selection.getSelectionEnd(editable); return this; }