Search in sources :

Example 11 with SettingsValues

use of com.android.inputmethod.latin.settings.SettingsValues in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class InputLogic method handleSeparatorEvent.

/**
 * Handle input of a separator code point.
 * @param event The event to handle.
 * @param inputTransaction The transaction in progress.
 */
private void handleSeparatorEvent(final Event event, final InputTransaction inputTransaction, final LatinIME.UIHandler handler) {
    final int codePoint = event.mCodePoint;
    final SettingsValues settingsValues = inputTransaction.mSettingsValues;
    final boolean wasComposingWord = mWordComposer.isComposingWord();
    // We avoid sending spaces in languages without spaces if we were composing.
    final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint && !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces && wasComposingWord;
    if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
        // If we are in the middle of a recorrection, we need to commit the recorrection
        // first so that we can insert the separator at the current cursor position.
        // We also need to unlearn the original word that is now being corrected.
        unlearnWord(mWordComposer.getTypedWord(), inputTransaction.mSettingsValues, Constants.EVENT_BACKSPACE);
        resetEntireInputState(mConnection.getExpectedSelectionStart(), mConnection.getExpectedSelectionEnd(), true);
    }
    // isComposingWord() may have changed since we stored wasComposing
    if (mWordComposer.isComposingWord()) {
        if (settingsValues.mAutoCorrectionEnabledPerUserSettings) {
            final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR : StringUtils.newSingleCodePointString(codePoint);
            commitCurrentAutoCorrection(settingsValues, separator, handler);
            inputTransaction.setDidAutoCorrect();
        } else {
            commitTyped(settingsValues, StringUtils.newSingleCodePointString(codePoint));
        }
    }
    final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event, inputTransaction);
    final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint && mConnection.isInsideDoubleQuoteOrAfterDigit();
    final boolean needsPrecedingSpace;
    if (SpaceState.PHANTOM != inputTransaction.mSpaceState) {
        needsPrecedingSpace = false;
    } else if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
        // Double quotes behave like they are usually preceded by space iff we are
        // not inside a double quote or after a digit.
        needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit;
    } else if (settingsValues.mSpacingAndPunctuations.isClusteringSymbol(codePoint) && settingsValues.mSpacingAndPunctuations.isClusteringSymbol(mConnection.getCodePointBeforeCursor())) {
        needsPrecedingSpace = false;
    } else {
        needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(codePoint);
    }
    if (needsPrecedingSpace) {
        insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues);
    }
    if (tryPerformDoubleSpacePeriod(event, inputTransaction)) {
        mSpaceState = SpaceState.DOUBLE;
        inputTransaction.setRequiresUpdateSuggestions();
        StatsUtils.onDoubleSpacePeriod();
    } else if (swapWeakSpace && trySwapSwapperAndSpace(event, inputTransaction)) {
        mSpaceState = SpaceState.SWAP_PUNCTUATION;
        mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
    } else if (Constants.CODE_SPACE == codePoint) {
        if (!mSuggestedWords.isPunctuationSuggestions()) {
            mSpaceState = SpaceState.WEAK;
        }
        startDoubleSpacePeriodCountdown(inputTransaction);
        if (wasComposingWord || mSuggestedWords.isEmpty()) {
            inputTransaction.setRequiresUpdateSuggestions();
        }
        if (!shouldAvoidSendingCode) {
            sendKeyCodePoint(settingsValues, codePoint);
        }
    } else {
        if ((SpaceState.PHANTOM == inputTransaction.mSpaceState && settingsValues.isUsuallyFollowedBySpace(codePoint)) || (Constants.CODE_DOUBLE_QUOTE == codePoint && isInsideDoubleQuoteOrAfterDigit)) {
            // If we are in phantom space state, and the user presses a separator, we want to
            // stay in phantom space state so that the next keypress has a chance to add the
            // space. For example, if I type "Good dat", pick "day" from the suggestion strip
            // then insert a comma and go on to typing the next word, I want the space to be
            // inserted automatically before the next word, the same way it is when I don't
            // input the comma. A double quote behaves like it's usually followed by space if
            // we're inside a double quote.
            // The case is a little different if the separator is a space stripper. Such a
            // separator does not normally need a space on the right (that's the difference
            // between swappers and strippers), so we should not stay in phantom space state if
            // the separator is a stripper. Hence the additional test above.
            mSpaceState = SpaceState.PHANTOM;
        }
        sendKeyCodePoint(settingsValues, codePoint);
        // Set punctuation right away. onUpdateSelection will fire but tests whether it is
        // already displayed or not, so it's okay.
        mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
    }
    inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
}
Also used : SettingsValues(com.android.inputmethod.latin.settings.SettingsValues) SpannableString(android.text.SpannableString)

Example 12 with SettingsValues

use of com.android.inputmethod.latin.settings.SettingsValues in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class LatinIME method onUpdateSelection.

@Override
public void onUpdateSelection(final int oldSelStart, final int oldSelEnd, final int newSelStart, final int newSelEnd, final int composingSpanStart, final int composingSpanEnd) {
    super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd);
    if (DebugFlags.DEBUG_ENABLED) {
        Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd + ", nss=" + newSelStart + ", nse=" + newSelEnd + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
    }
    // This call happens whether our view is displayed or not, but if it's not then we should
    // not attempt recorrection. This is true even with a hardware keyboard connected: if the
    // view is not displayed we have no means of showing suggestions anyway, and if it is then
    // we want to show suggestions anyway.
    final SettingsValues settingsValues = mSettings.getCurrent();
    if (isInputViewShown() && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, settingsValues)) {
        mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
    }
}
Also used : SettingsValues(com.android.inputmethod.latin.settings.SettingsValues)

Example 13 with SettingsValues

use of com.android.inputmethod.latin.settings.SettingsValues in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class LatinIME method onStartInputViewInternal.

@SuppressWarnings("deprecation")
void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
    super.onStartInputView(editorInfo, restarting);
    mDictionaryFacilitator.onStartInput();
    // Switch to the null consumer to handle cases leading to early exit below, for which we
    // also wouldn't be consuming gesture data.
    mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
    mRichImm.refreshSubtypeCaches();
    final KeyboardSwitcher switcher = mKeyboardSwitcher;
    switcher.updateKeyboardTheme();
    final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
    // If we are starting input in a different text field from before, we'll have to reload
    // settings, so currentSettingsValues can't be final.
    SettingsValues currentSettingsValues = mSettings.getCurrent();
    if (editorInfo == null) {
        Log.e(TAG, "Null EditorInfo in onStartInputView()");
        if (DebugFlags.DEBUG_ENABLED) {
            throw new NullPointerException("Null EditorInfo in onStartInputView()");
        }
        return;
    }
    if (DebugFlags.DEBUG_ENABLED) {
        Log.d(TAG, "onStartInputView: editorInfo:" + String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions));
        Log.d(TAG, "All caps = " + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) + ", sentence caps = " + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) + ", word caps = " + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0));
    }
    Log.i(TAG, "Starting input. Cursor position = " + editorInfo.initialSelStart + "," + editorInfo.initialSelEnd);
    // TODO: Consolidate these checks with {@link InputAttributes}.
    if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
        Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions);
        Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead");
    }
    if (InputAttributes.inPrivateImeOptions(getPackageName(), FORCE_ASCII, editorInfo)) {
        Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions);
        Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
    }
    // In landscape mode, this method gets called without the input view being created.
    if (mainKeyboardView == null) {
        return;
    }
    // Update to a gesture consumer with the current editor and IME state.
    mGestureConsumer = GestureConsumer.newInstance(editorInfo, mInputLogic.getPrivateCommandPerformer(), mRichImm.getCurrentSubtypeLocale(), switcher.getKeyboard());
    // Forward this event to the accessibility utilities, if enabled.
    final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
    if (accessUtils.isTouchExplorationEnabled()) {
        accessUtils.onStartInputViewInternal(mainKeyboardView, editorInfo, restarting);
    }
    final boolean inputTypeChanged = !currentSettingsValues.isSameInputType(editorInfo);
    final boolean isDifferentTextField = !restarting || inputTypeChanged;
    StatsUtils.onStartInputView(editorInfo.inputType, Settings.getInstance().getCurrent().mDisplayOrientation, !isDifferentTextField);
    // The EditorInfo might have a flag that affects fullscreen mode.
    // Note: This call should be done by InputMethodService?
    updateFullscreenMode();
    // ALERT: settings have not been reloaded and there is a chance they may be stale.
    // In the practice, if it is, we should have gotten onConfigurationChanged so it should
    // be fine, but this is horribly confusing and must be fixed AS SOON AS POSSIBLE.
    // In some cases the input connection has not been reset yet and we can't access it. In
    // this case we will need to call loadKeyboard() later, when it's accessible, so that we
    // can go into the correct mode, so we need to do some housekeeping here.
    final boolean needToCallLoadKeyboardLater;
    final Suggest suggest = mInputLogic.mSuggest;
    if (!isImeSuppressedByHardwareKeyboard()) {
        // The app calling setText() has the effect of clearing the composing
        // span, so we should reset our state unconditionally, even if restarting is true.
        // We also tell the input logic about the combining rules for the current subtype, so
        // it can adjust its combiners if needed.
        mInputLogic.startInput(mRichImm.getCombiningRulesExtraValueOfCurrentSubtype(), currentSettingsValues);
        resetDictionaryFacilitatorIfNecessary();
        // TODO[IL]: Can the following be moved to InputLogic#startInput?
        if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(editorInfo.initialSelStart, editorInfo.initialSelEnd, false)) {
            // Sometimes, while rotating, for some reason the framework tells the app we are not
            // connected to it and that means we can't refresh the cache. In this case, schedule
            // a refresh later.
            // We try resetting the caches up to 5 times before giving up.
            mHandler.postResetCaches(isDifferentTextField, 5);
            // mLastSelection{Start,End} are reset later in this method, no need to do it here
            needToCallLoadKeyboardLater = true;
        } else {
            // When rotating, and when input is starting again in a field from where the focus
            // didn't move (the keyboard having been closed with the back key),
            // initialSelStart and initialSelEnd sometimes are lying. Make a best effort to
            // work around this bug.
            mInputLogic.mConnection.tryFixLyingCursorPosition();
            mHandler.postResumeSuggestionsForStartInput(true);
            needToCallLoadKeyboardLater = false;
        }
    } else {
        // If we have a hardware keyboard we don't need to call loadKeyboard later anyway.
        needToCallLoadKeyboardLater = false;
    }
    if (isDifferentTextField || !currentSettingsValues.hasSameOrientation(getResources().getConfiguration())) {
        loadSettings();
    }
    if (isDifferentTextField) {
        mainKeyboardView.closing();
        currentSettingsValues = mSettings.getCurrent();
        if (currentSettingsValues.mAutoCorrectionEnabledPerUserSettings) {
            suggest.setAutoCorrectionThreshold(currentSettingsValues.mAutoCorrectionThreshold);
        }
        suggest.setPlausibilityThreshold(currentSettingsValues.mPlausibilityThreshold);
        switcher.loadKeyboard(editorInfo, currentSettingsValues, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
        if (needToCallLoadKeyboardLater) {
            // If we need to call loadKeyboard again later, we need to save its state now. The
            // later call will be done in #retryResetCaches.
            switcher.saveKeyboardState();
        }
    } else if (restarting) {
        // TODO: Come up with a more comprehensive way to reset the keyboard layout when
        // a keyboard layout set doesn't get reloaded in this method.
        switcher.resetKeyboardStateToAlphabet(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
        // In apps like Talk, we come here when the text is sent and the field gets emptied and
        // we need to re-evaluate the shift state, but not the whole layout which would be
        // disruptive.
        // Space state must be updated before calling updateShiftState
        switcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
    }
    // This will set the punctuation suggestions if next word suggestion is off;
    // otherwise it will clear the suggestion strip.
    setNeutralSuggestionStrip();
    mHandler.cancelUpdateSuggestionStrip();
    mainKeyboardView.setMainDictionaryAvailability(mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary());
    mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn, currentSettingsValues.mKeyPreviewPopupDismissDelay);
    mainKeyboardView.setSlidingKeyInputPreviewEnabled(currentSettingsValues.mSlidingKeyInputPreviewEnabled);
    mainKeyboardView.setGestureHandlingEnabledByUser(currentSettingsValues.mGestureInputEnabled, currentSettingsValues.mGestureTrailEnabled, currentSettingsValues.mGestureFloatingPreviewTextEnabled);
    if (TRACE)
        Debug.startMethodTracing("/data/trace/latinime");
}
Also used : MainKeyboardView(com.android.inputmethod.keyboard.MainKeyboardView) SettingsValues(com.android.inputmethod.latin.settings.SettingsValues) KeyboardSwitcher(com.android.inputmethod.keyboard.KeyboardSwitcher) AccessibilityUtils(com.android.inputmethod.accessibility.AccessibilityUtils)

Example 14 with SettingsValues

use of com.android.inputmethod.latin.settings.SettingsValues in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class LatinIME method onEvaluateFullscreenMode.

@Override
public boolean onEvaluateFullscreenMode() {
    final SettingsValues settingsValues = mSettings.getCurrent();
    if (isImeSuppressedByHardwareKeyboard()) {
        // If there is a hardware keyboard, disable full screen mode.
        return false;
    }
    // Reread resource value here, because this method is called by the framework as needed.
    final boolean isFullscreenModeAllowed = Settings.readUseFullscreenMode(getResources());
    if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) {
        // TODO: Remove this hack. Actually we should not really assume NO_EXTRACT_UI
        // implies NO_FULLSCREEN. However, the framework mistakenly does.  i.e. NO_EXTRACT_UI
        // without NO_FULLSCREEN doesn't work as expected. Because of this we need this
        // hack for now.  Let's get rid of this once the framework gets fixed.
        final EditorInfo ei = getCurrentInputEditorInfo();
        return !(ei != null && ((ei.imeOptions & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0));
    }
    return false;
}
Also used : EditorInfo(android.view.inputmethod.EditorInfo) SettingsValues(com.android.inputmethod.latin.settings.SettingsValues)

Example 15 with SettingsValues

use of com.android.inputmethod.latin.settings.SettingsValues in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class LatinIME method onConfigurationChanged.

@Override
public void onConfigurationChanged(final Configuration conf) {
    SettingsValues settingsValues = mSettings.getCurrent();
    if (settingsValues.mDisplayOrientation != conf.orientation) {
        mHandler.startOrientationChanging();
        mInputLogic.onOrientationChange(mSettings.getCurrent());
    }
    if (settingsValues.mHasHardwareKeyboard != Settings.readHasHardwareKeyboard(conf)) {
        // If the state of having a hardware keyboard changed, then we want to reload the
        // settings to adjust for that.
        // TODO: we should probably do this unconditionally here, rather than only when we
        // have a change in hardware keyboard configuration.
        loadSettings();
        settingsValues = mSettings.getCurrent();
        if (isImeSuppressedByHardwareKeyboard()) {
            // We call cleanupInternalStateForFinishInput() because it's the right thing to do;
            // however, it seems at the moment the framework is passing us a seemingly valid
            // but actually non-functional InputConnection object. So if this bug ever gets
            // fixed we'll be able to remove the composition, but until it is this code is
            // actually not doing much.
            cleanupInternalStateForFinishInput();
        }
    }
    super.onConfigurationChanged(conf);
}
Also used : SettingsValues(com.android.inputmethod.latin.settings.SettingsValues)

Aggregations

SettingsValues (com.android.inputmethod.latin.settings.SettingsValues)19 EditorInfo (android.view.inputmethod.EditorInfo)3 UsedForTesting (com.android.inputmethod.annotations.UsedForTesting)2 MainKeyboardView (com.android.inputmethod.keyboard.MainKeyboardView)2 SpannableString (android.text.SpannableString)1 PrintWriterPrinter (android.util.PrintWriterPrinter)1 Printer (android.util.Printer)1 View (android.view.View)1 AccessibilityUtils (com.android.inputmethod.accessibility.AccessibilityUtils)1 Keyboard (com.android.inputmethod.keyboard.Keyboard)1 KeyboardSwitcher (com.android.inputmethod.keyboard.KeyboardSwitcher)1 SuggestionStripView (com.android.inputmethod.latin.suggestions.SuggestionStripView)1 Locale (java.util.Locale)1