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

Commit c42f285b authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Introduce KeyboardSet to hold related KeyboardIds

This change moves
  * KeyboardSwitcher.getKeyboardId to KeyboardSet.<init> and
    KeyboardSet.getKeyboardId.
  * KeyboardSwitcher.getF2KeyMode to KeyboardSet.
This is the first step to get rid of shift state from Keyboard.

Bug: 5002108
Bug: 5679585
Change-Id: I2a5a97e5e89277bc606916d45c1afbc8d105d773
parent 77ecf52a
Loading
Loading
Loading
Loading
+134 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.inputmethod.keyboard;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.view.inputmethod.EditorInfo;

import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SettingsValues;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;

import java.util.Locale;

/**
 * This class has a set of {@link KeyboardId}s. Each of them represents a different keyboard
 * specific to a keyboard state, such as alphabet, symbols, and so on.  Layouts in the same
 * {@link KeyboardSet} are related to each other.
 * A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}.
 */
public class KeyboardSet {
    // TODO: Make these KeyboardId private.
    public final KeyboardId mAlphabetId;
    public final KeyboardId mSymbolsId;
    public final KeyboardId mSymbolsShiftedId;

    KeyboardSet(Builder builder) {
        mAlphabetId = builder.getKeyboardId(false, false);
        mSymbolsId = builder.getKeyboardId(true, false);
        mSymbolsShiftedId = builder.getKeyboardId(true, true);
    }

    public static class Builder {
        private final Resources mResources;
        private final EditorInfo mEditorInfo;

        private final int mMode;
        private final boolean mVoiceKeyEnabled;
        private final boolean mNoSettingsKey;
        private final boolean mHasSettingsKey;
        private final int mF2KeyMode;
        private final boolean mVoiceKeyOnMain;
        private final Locale mLocale;
        private final Configuration mConf;
        private final DisplayMetrics mMetrics;

        public Builder(Context context, EditorInfo editorInfo, SettingsValues settingsValues) {
            mResources = context.getResources();
            mEditorInfo = editorInfo;
            final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
            final String packageName = context.getPackageName();

            mMode = Utils.getKeyboardMode(mEditorInfo);
            final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
            @SuppressWarnings("deprecation")
            final boolean noMicrophone = Utils.inPrivateImeOptions(
                    packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
                    || Utils.inPrivateImeOptions(
                            null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
            mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone;
            mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
            mNoSettingsKey = Utils.inPrivateImeOptions(
                    packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
            mHasSettingsKey = settingsKeyEnabled && !mNoSettingsKey;
            mF2KeyMode = getF2KeyMode(settingsKeyEnabled, mNoSettingsKey);
            final boolean forceAscii = Utils.inPrivateImeOptions(
                    packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
            final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey(
                    LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
            mLocale = (forceAscii && !asciiCapable) ? Locale.US : subtypeSwitcher.getInputLocale();
            mConf = mResources.getConfiguration();
            mMetrics = mResources.getDisplayMetrics();
        }

        public KeyboardSet build() {
            return new KeyboardSet(this);
        }

        KeyboardId getKeyboardId(boolean isSymbols, boolean isShift) {
            final int xmlId = getXmlId(mMode, isSymbols, isShift);
            final boolean hasShortCutKey = mVoiceKeyEnabled && (isSymbols != mVoiceKeyOnMain);
            return new KeyboardId(mResources.getResourceEntryName(xmlId), xmlId, mLocale,
                    mConf.orientation, mMetrics.widthPixels, mMode, mEditorInfo, mHasSettingsKey,
                    mF2KeyMode, mNoSettingsKey, mVoiceKeyEnabled, hasShortCutKey);
        }

        private static int getXmlId(int mode, boolean isSymbols, boolean isShift) {
            switch (mode) {
            case KeyboardId.MODE_PHONE:
                return (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
            case KeyboardId.MODE_NUMBER:
                return R.xml.kbd_number;
            default:
                if (isSymbols) {
                    return isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
                }
                return R.xml.kbd_qwerty;
            }
        }

        private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
            if (noSettingsKey) {
                // Never shows the Settings key
                return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
            }

            if (settingsKeyEnabled) {
                return KeyboardId.F2KEY_MODE_SETTINGS;
            } else {
                // It should be alright to fall back to the Settings key on 7-inch layouts
                // even when the Settings key is not explicitly enabled.
                return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
            }
        }
    }
}
+10 −80
Original line number Diff line number Diff line
@@ -18,9 +18,7 @@ package com.android.inputmethod.keyboard;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.InflateException;
@@ -65,14 +63,11 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
    private InputView mCurrentInputView;
    private LatinKeyboardView mKeyboardView;
    private LatinIME mInputMethodService;
    private String mPackageName;
    private Resources mResources;

    private KeyboardState mState;

    private KeyboardId mMainKeyboardId;
    private KeyboardId mSymbolsKeyboardId;
    private KeyboardId mSymbolsShiftedKeyboardId;
    private KeyboardSet mKeyboardSet;

    private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
            new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
@@ -100,7 +95,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,

    private void initInternal(LatinIME ims, SharedPreferences prefs) {
        mInputMethodService = ims;
        mPackageName = ims.getPackageName();
        mResources = ims.getResources();
        mPrefs = prefs;
        mSubtypeSwitcher = SubtypeSwitcher.getInstance();
@@ -133,20 +127,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,

    public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
        try {
            mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
            mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
            mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
            mKeyboardSet = new KeyboardSet.Builder(mInputMethodService, editorInfo, settingsValues)
                    .build();
            mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
                    hasDistinctMultitouch());
            // TODO: Should get rid of this special case handling for Phone Number layouts once we
            // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
            // respectively.
            if (mMainKeyboardId.isPhoneKeyboard()) {
            if (mKeyboardSet.mAlphabetId.isPhoneKeyboard()) {
                mState.onToggleAlphabetAndSymbols();
            }
        } catch (RuntimeException e) {
            Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
            LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
            Log.w(TAG, "loading keyboard failed: " + mKeyboardSet.mAlphabetId, e);
            LatinImeLogger.logOnException(mKeyboardSet.mAlphabetId.toString(), e);
        }
    }

@@ -177,6 +170,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
        updateShiftState();
    }

    // TODO: Move this method to KeyboardSet.
    private LatinKeyboard getKeyboard(KeyboardId id) {
        final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
        LatinKeyboard keyboard = (ref == null) ? null : ref.get();
@@ -215,55 +209,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
        return keyboard;
    }

    private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols,
            final boolean isShift, SettingsValues settingsValues) {
        final int mode = Utils.getKeyboardMode(editorInfo);
        final int xmlId;
        switch (mode) {
        case KeyboardId.MODE_PHONE:
            xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
            break;
        case KeyboardId.MODE_NUMBER:
            xmlId = R.xml.kbd_number;
            break;
        default:
            if (isSymbols) {
                xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
            } else {
                xmlId = R.xml.kbd_qwerty;
            }
            break;
        }

        final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
        @SuppressWarnings("deprecation")
        final boolean noMicrophone = Utils.inPrivateImeOptions(
                mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
                || Utils.inPrivateImeOptions(
                        null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
        final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo)
                && !noMicrophone;
        final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
        final boolean noSettingsKey = Utils.inPrivateImeOptions(
                mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
        final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey;
        final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
        final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
        final boolean forceAscii = Utils.inPrivateImeOptions(
                mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
        final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
                LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
        final Locale locale = (forceAscii && !asciiCapable)
                ? Locale.US : mSubtypeSwitcher.getInputLocale();
        final Configuration conf = mResources.getConfiguration();
        final DisplayMetrics dm = mResources.getDisplayMetrics();

        return new KeyboardId(
                mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation,
                dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey,
                voiceKeyEnabled, hasShortcutKey);
    }

    public boolean isAlphabetMode() {
        final Keyboard keyboard = getLatinKeyboard();
        return keyboard != null && keyboard.mId.isAlphabetKeyboard();
@@ -393,19 +338,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
    // Implements {@link KeyboardState.SwitchActions}.
    @Override
    public void setSymbolsKeyboard() {
        setKeyboard(getKeyboard(mSymbolsKeyboardId));
        setKeyboard(getKeyboard(mKeyboardSet.mSymbolsId));
    }

    // Implements {@link KeyboardState.SwitchActions}.
    @Override
    public void setAlphabetKeyboard() {
        setKeyboard(getKeyboard(mMainKeyboardId));
        setKeyboard(getKeyboard(mKeyboardSet.mAlphabetId));
    }

    // Implements {@link KeyboardState.SwitchActions}.
    @Override
    public void setSymbolsShiftedKeyboard() {
        final Keyboard keyboard = getKeyboard(mSymbolsShiftedKeyboardId);
        final Keyboard keyboard = getKeyboard(mKeyboardSet.mSymbolsShiftedId);
        setKeyboard(keyboard);
        // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
        // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a.
@@ -518,19 +463,4 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
            }
        }
    }

    private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
        if (noSettingsKey) {
            // Never shows the Settings key
            return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
        }

        if (settingsKeyEnabled) {
            return KeyboardId.F2KEY_MODE_SETTINGS;
        } else {
            // It should be alright to fall back to the Settings key on 7-inch layouts
            // even when the Settings key is not explicitly enabled.
            return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
        }
    }
}