Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a88e95e0 authored by Jean Chalard's avatar Jean Chalard
Browse files

[HW13] Split up onCodeInput

Change-Id: I503c5403dcaea5db632eba85ae3fae9ba9a1f946
parent 85b7b967
Loading
Loading
Loading
Loading
+164 −110
Original line number Diff line number Diff line
@@ -426,119 +426,16 @@ public final class InputLogic {
            cancelDoubleSpacePeriodCountdown();
        }

        boolean didAutoCorrect = false;
        final boolean didAutoCorrect;
        if (processedEvent.isConsumed()) {
            // A consumed event may have text to commit and an update to the composing state, so
            // we evaluate both. With some combiners, it's possible than an event contains both
            // and we enter both of the following if clauses.
            final CharSequence textToCommit = processedEvent.getTextToCommit();
            if (!TextUtils.isEmpty(textToCommit)) {
                mConnection.commitText(textToCommit, 1);
                inputTransaction.setDidAffectContents();
            }
            if (mWordComposer.isComposingWord()) {
                mConnection.setComposingText(mWordComposer.getTypedWord(), 1);
                inputTransaction.setDidAffectContents();
                inputTransaction.setRequiresUpdateSuggestions();
            }
            handleConsumedEvent(inputTransaction);
            didAutoCorrect = false;
        } else if (processedEvent.isFunctionalKeyEvent()) {
            // A special key, like delete, shift, emoji, or the settings key.
            switch (processedEvent.mKeyCode) {
            case Constants.CODE_DELETE:
                handleBackspace(inputTransaction, currentKeyboardScriptId);
                // Backspace is a functional key, but it affects the contents of the editor.
                inputTransaction.setDidAffectContents();
                break;
            case Constants.CODE_SHIFT:
                performRecapitalization(inputTransaction.mSettingsValues);
                inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
                if (mSuggestedWords.mIsPrediction) {
                    inputTransaction.setRequiresUpdateSuggestions();
                }
                break;
            case Constants.CODE_CAPSLOCK:
                // Note: Changing keyboard to shift lock state is handled in
                // {@link KeyboardSwitcher#onCodeInput(int)}.
                break;
            case Constants.CODE_SYMBOL_SHIFT:
                // Note: Calling back to the keyboard on the symbol Shift key is handled in
                // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
                break;
            case Constants.CODE_SWITCH_ALPHA_SYMBOL:
                // Note: Calling back to the keyboard on symbol key is handled in
                // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
                break;
            case Constants.CODE_SETTINGS:
                onSettingsKeyPressed();
                break;
            case Constants.CODE_SHORTCUT:
                // We need to switch to the shortcut IME. This is handled by LatinIME since the
                // input logic has no business with IME switching.
                break;
            case Constants.CODE_ACTION_NEXT:
                performEditorAction(EditorInfo.IME_ACTION_NEXT);
                break;
            case Constants.CODE_ACTION_PREVIOUS:
                performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
                break;
            case Constants.CODE_LANGUAGE_SWITCH:
                handleLanguageSwitchKey();
                break;
            case Constants.CODE_EMOJI:
                // Note: Switching emoji keyboard is being handled in
                // {@link KeyboardState#onCodeInput(int,int)}.
                break;
            case Constants.CODE_ALPHA_FROM_EMOJI:
                // Note: Switching back from Emoji keyboard to the main keyboard is being
                // handled in {@link KeyboardState#onCodeInput(int,int)}.
                break;
            case Constants.CODE_SHIFT_ENTER:
                // TODO: remove this object
                final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
                        processedEvent.mKeyCode, processedEvent.mX, processedEvent.mY,
                        processedEvent.isKeyRepeat());
                final InputTransaction tmpTransaction = new InputTransaction(
                        inputTransaction.mSettingsValues, tmpEvent,
                        inputTransaction.mTimestamp, inputTransaction.mSpaceState,
                        inputTransaction.mShiftState);
                didAutoCorrect = handleNonSpecialCharacter(tmpTransaction, handler);
                // Shift + Enter is treated as a functional key but it results in adding a new
                // line, so that does affect the contents of the editor.
                inputTransaction.setDidAffectContents();
                break;
            default:
                throw new RuntimeException("Unknown key code : " + processedEvent.mKeyCode);
            }
        } else {
            inputTransaction.setDidAffectContents();
            switch (processedEvent.mCodePoint) {
            case Constants.CODE_ENTER:
                final EditorInfo editorInfo = getCurrentInputEditorInfo();
                final int imeOptionsActionId =
                        InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
                if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
                    // Either we have an actionLabel and we should performEditorAction with
                    // actionId regardless of its value.
                    performEditorAction(editorInfo.actionId);
                } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
                    // We didn't have an actionLabel, but we had another action to execute.
                    // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
                    // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
                    // means there should be an action and the app didn't bother to set a specific
                    // code for it - presumably it only handles one. It does not have to be treated
                    // in any specific way: anything that is not IME_ACTION_NONE should be sent to
                    // performEditorAction.
                    performEditorAction(imeOptionsActionId);
            didAutoCorrect = handleFunctionalEventAndReturnIfDidAutoCorrect(inputTransaction,
                    currentKeyboardScriptId, handler);
        } else {
                    // No action label, and the action from imeOptions is NONE: this is a regular
                    // enter key that should input a carriage return.
                    didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
                }
                break;
            default:
                didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
                break;
            }
            didAutoCorrect = handleNonFunctionalEventAndReturnIfDidAutoCorrect(inputTransaction,
                    handler);
        }
        if (!didAutoCorrect && processedEvent.mKeyCode != Constants.CODE_SHIFT
                && processedEvent.mKeyCode != Constants.CODE_CAPSLOCK
@@ -685,6 +582,163 @@ public final class InputLogic {
        }
    }

    /**
     * Handle a consumed event.
     *
     * Consumed events represent events that have already been consumed, typically by the
     * combining chain.
     *
     * @param inputTransaction The transaction in progress.
     */
    private void handleConsumedEvent(final InputTransaction inputTransaction) {
        // A consumed event may have text to commit and an update to the composing state, so
        // we evaluate both. With some combiners, it's possible than an event contains both
        // and we enter both of the following if clauses.
        final CharSequence textToCommit = inputTransaction.mEvent.getTextToCommit();
        if (!TextUtils.isEmpty(textToCommit)) {
            mConnection.commitText(textToCommit, 1);
            inputTransaction.setDidAffectContents();
        }
        if (mWordComposer.isComposingWord()) {
            mConnection.setComposingText(mWordComposer.getTypedWord(), 1);
            inputTransaction.setDidAffectContents();
            inputTransaction.setRequiresUpdateSuggestions();
        }
    }

    /**
     * Handle a functional key event.
     *
     * A functional event is a special key, like delete, shift, emoji, or the settings key.
     * Non-special keys are those that generate a single code point.
     * This includes all letters, digits, punctuation, separators, emoji. It excludes keys that
     * manage keyboard-related stuff like shift, language switch, settings, layout switch, or
     * any key that results in multiple code points like the ".com" key.
     *
     * @param inputTransaction The transaction in progress.
     * @return whether this caused an auto-correction to happen.
     */
    private boolean handleFunctionalEventAndReturnIfDidAutoCorrect(
            final InputTransaction inputTransaction,
            // TODO: remove these arguments
            final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
        final Event event = inputTransaction.mEvent;
        boolean didAutoCorrect = false;
        switch (event.mKeyCode) {
            case Constants.CODE_DELETE:
                handleBackspace(inputTransaction, currentKeyboardScriptId);
                // Backspace is a functional key, but it affects the contents of the editor.
                inputTransaction.setDidAffectContents();
                break;
            case Constants.CODE_SHIFT:
                performRecapitalization(inputTransaction.mSettingsValues);
                inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
                if (mSuggestedWords.mIsPrediction) {
                    inputTransaction.setRequiresUpdateSuggestions();
                }
                break;
            case Constants.CODE_CAPSLOCK:
                // Note: Changing keyboard to shift lock state is handled in
                // {@link KeyboardSwitcher#onCodeInput(int)}.
                break;
            case Constants.CODE_SYMBOL_SHIFT:
                // Note: Calling back to the keyboard on the symbol Shift key is handled in
                // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
                break;
            case Constants.CODE_SWITCH_ALPHA_SYMBOL:
                // Note: Calling back to the keyboard on symbol key is handled in
                // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
                break;
            case Constants.CODE_SETTINGS:
                onSettingsKeyPressed();
                break;
            case Constants.CODE_SHORTCUT:
                // We need to switch to the shortcut IME. This is handled by LatinIME since the
                // input logic has no business with IME switching.
                break;
            case Constants.CODE_ACTION_NEXT:
                performEditorAction(EditorInfo.IME_ACTION_NEXT);
                break;
            case Constants.CODE_ACTION_PREVIOUS:
                performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
                break;
            case Constants.CODE_LANGUAGE_SWITCH:
                handleLanguageSwitchKey();
                break;
            case Constants.CODE_EMOJI:
                // Note: Switching emoji keyboard is being handled in
                // {@link KeyboardState#onCodeInput(int,int)}.
                break;
            case Constants.CODE_ALPHA_FROM_EMOJI:
                // Note: Switching back from Emoji keyboard to the main keyboard is being
                // handled in {@link KeyboardState#onCodeInput(int,int)}.
                break;
            case Constants.CODE_SHIFT_ENTER:
                // TODO: remove this object
                final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
                        event.mKeyCode, event.mX, event.mY, event.isKeyRepeat());
                final InputTransaction tmpTransaction = new InputTransaction(
                        inputTransaction.mSettingsValues, tmpEvent,
                        inputTransaction.mTimestamp, inputTransaction.mSpaceState,
                        inputTransaction.mShiftState);
                didAutoCorrect = handleNonSpecialCharacter(tmpTransaction, handler);
                // Shift + Enter is treated as a functional key but it results in adding a new
                // line, so that does affect the contents of the editor.
                inputTransaction.setDidAffectContents();
                break;
            default:
                throw new RuntimeException("Unknown key code : " + event.mKeyCode);
        }
        return didAutoCorrect;
    }

    /**
     * Handle an event that is not a functional event.
     *
     * These events are generally events that cause input, but in some cases they may do other
     * things like trigger an editor action.
     *
     * @param inputTransaction The transaction in progress.
     * @return whether this caused an auto-correction to happen.
     */
    private boolean handleNonFunctionalEventAndReturnIfDidAutoCorrect(
            final InputTransaction inputTransaction,
            // TODO: remove this argument
            final LatinIME.UIHandler handler) {
        final Event event = inputTransaction.mEvent;
        inputTransaction.setDidAffectContents();
        boolean didAutoCorrect = false;
        switch (event.mCodePoint) {
            case Constants.CODE_ENTER:
                final EditorInfo editorInfo = getCurrentInputEditorInfo();
                final int imeOptionsActionId =
                        InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
                if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
                    // Either we have an actionLabel and we should performEditorAction with
                    // actionId regardless of its value.
                    performEditorAction(editorInfo.actionId);
                } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
                    // We didn't have an actionLabel, but we had another action to execute.
                    // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
                    // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
                    // means there should be an action and the app didn't bother to set a specific
                    // code for it - presumably it only handles one. It does not have to be treated
                    // in any specific way: anything that is not IME_ACTION_NONE should be sent to
                    // performEditorAction.
                    performEditorAction(imeOptionsActionId);
                } else {
                    // No action label, and the action from imeOptions is NONE: this is a regular
                    // enter key that should input a carriage return.
                    didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
                }
                break;
            default:
                didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
                break;
        }
        return didAutoCorrect;
    }

    /**
     * Handle inputting a code point to the editor.
     *