Home | History | Annotate | Download | only in latin
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.android.inputmethod.latin;
     18 
     19 import android.content.SharedPreferences;
     20 import android.content.res.Configuration;
     21 import android.content.res.Resources;
     22 import android.preference.PreferenceManager;
     23 import android.view.InflateException;
     24 
     25 import java.lang.ref.SoftReference;
     26 import java.util.Arrays;
     27 import java.util.HashMap;
     28 import java.util.Locale;
     29 
     30 public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener {
     31 
     32     public static final int MODE_NONE = 0;
     33     public static final int MODE_TEXT = 1;
     34     public static final int MODE_SYMBOLS = 2;
     35     public static final int MODE_PHONE = 3;
     36     public static final int MODE_URL = 4;
     37     public static final int MODE_EMAIL = 5;
     38     public static final int MODE_IM = 6;
     39     public static final int MODE_WEB = 7;
     40 
     41     // Main keyboard layouts without the settings key
     42     public static final int KEYBOARDMODE_NORMAL = R.id.mode_normal;
     43     public static final int KEYBOARDMODE_URL = R.id.mode_url;
     44     public static final int KEYBOARDMODE_EMAIL = R.id.mode_email;
     45     public static final int KEYBOARDMODE_IM = R.id.mode_im;
     46     public static final int KEYBOARDMODE_WEB = R.id.mode_webentry;
     47     // Main keyboard layouts with the settings key
     48     public static final int KEYBOARDMODE_NORMAL_WITH_SETTINGS_KEY =
     49             R.id.mode_normal_with_settings_key;
     50     public static final int KEYBOARDMODE_URL_WITH_SETTINGS_KEY =
     51             R.id.mode_url_with_settings_key;
     52     public static final int KEYBOARDMODE_EMAIL_WITH_SETTINGS_KEY =
     53             R.id.mode_email_with_settings_key;
     54     public static final int KEYBOARDMODE_IM_WITH_SETTINGS_KEY =
     55             R.id.mode_im_with_settings_key;
     56     public static final int KEYBOARDMODE_WEB_WITH_SETTINGS_KEY =
     57             R.id.mode_webentry_with_settings_key;
     58 
     59     // Symbols keyboard layout without the settings key
     60     public static final int KEYBOARDMODE_SYMBOLS = R.id.mode_symbols;
     61     // Symbols keyboard layout with the settings key
     62     public static final int KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY =
     63             R.id.mode_symbols_with_settings_key;
     64 
     65     public static final String DEFAULT_LAYOUT_ID = "4";
     66     public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
     67     private static final int[] THEMES = new int [] {
     68         R.layout.input_basic, R.layout.input_basic_highcontrast, R.layout.input_stone_normal,
     69         R.layout.input_stone_bold, R.layout.input_gingerbread};
     70 
     71     // Ids for each characters' color in the keyboard
     72     private static final int CHAR_THEME_COLOR_WHITE = 0;
     73     private static final int CHAR_THEME_COLOR_BLACK = 1;
     74 
     75     // Tables which contains resource ids for each character theme color
     76     private static final int[] KBD_PHONE = new int[] {R.xml.kbd_phone, R.xml.kbd_phone_black};
     77     private static final int[] KBD_PHONE_SYMBOLS = new int[] {
     78         R.xml.kbd_phone_symbols, R.xml.kbd_phone_symbols_black};
     79     private static final int[] KBD_SYMBOLS = new int[] {
     80         R.xml.kbd_symbols, R.xml.kbd_symbols_black};
     81     private static final int[] KBD_SYMBOLS_SHIFT = new int[] {
     82         R.xml.kbd_symbols_shift, R.xml.kbd_symbols_shift_black};
     83     private static final int[] KBD_QWERTY = new int[] {R.xml.kbd_qwerty, R.xml.kbd_qwerty_black};
     84 
     85     private static final int SYMBOLS_MODE_STATE_NONE = 0;
     86     private static final int SYMBOLS_MODE_STATE_BEGIN = 1;
     87     private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
     88 
     89     private LatinKeyboardView mInputView;
     90     private static final int[] ALPHABET_MODES = {
     91         KEYBOARDMODE_NORMAL,
     92         KEYBOARDMODE_URL,
     93         KEYBOARDMODE_EMAIL,
     94         KEYBOARDMODE_IM,
     95         KEYBOARDMODE_WEB,
     96         KEYBOARDMODE_NORMAL_WITH_SETTINGS_KEY,
     97         KEYBOARDMODE_URL_WITH_SETTINGS_KEY,
     98         KEYBOARDMODE_EMAIL_WITH_SETTINGS_KEY,
     99         KEYBOARDMODE_IM_WITH_SETTINGS_KEY,
    100         KEYBOARDMODE_WEB_WITH_SETTINGS_KEY };
    101 
    102     private final LatinIME mInputMethodService;
    103 
    104     private KeyboardId mSymbolsId;
    105     private KeyboardId mSymbolsShiftedId;
    106 
    107     private KeyboardId mCurrentId;
    108     private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboards;
    109 
    110     private int mMode = MODE_NONE; /** One of the MODE_XXX values */
    111     private int mImeOptions;
    112     private boolean mIsSymbols;
    113     /** mIsAutoCompletionActive indicates that auto completed word will be input instead of
    114      * what user actually typed. */
    115     private boolean mIsAutoCompletionActive;
    116     private boolean mHasVoice;
    117     private boolean mVoiceOnPrimary;
    118     private boolean mPreferSymbols;
    119     private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
    120 
    121     // Indicates whether or not we have the settings key
    122     private boolean mHasSettingsKey;
    123     private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto;
    124     private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = R.string.settings_key_mode_always_show;
    125     // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to
    126     // in the source code now.
    127     // Default is SETTINGS_KEY_MODE_AUTO.
    128     private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO;
    129 
    130     private int mLastDisplayWidth;
    131     private LanguageSwitcher mLanguageSwitcher;
    132     private Locale mInputLocale;
    133 
    134     private int mLayoutId;
    135 
    136     public KeyboardSwitcher(LatinIME ims) {
    137         mInputMethodService = ims;
    138 
    139         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ims);
    140         mLayoutId = Integer.valueOf(prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID));
    141         updateSettingsKeyState(prefs);
    142         prefs.registerOnSharedPreferenceChangeListener(this);
    143 
    144         mKeyboards = new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
    145         mSymbolsId = makeSymbolsId(false);
    146         mSymbolsShiftedId = makeSymbolsShiftedId(false);
    147     }
    148 
    149     /**
    150      * Sets the input locale, when there are multiple locales for input.
    151      * If no locale switching is required, then the locale should be set to null.
    152      * @param locale the current input locale, or null for default locale with no locale
    153      * button.
    154      */
    155     public void setLanguageSwitcher(LanguageSwitcher languageSwitcher) {
    156         mLanguageSwitcher = languageSwitcher;
    157         mInputLocale = mLanguageSwitcher.getInputLocale();
    158     }
    159 
    160     private KeyboardId makeSymbolsId(boolean hasVoice) {
    161         return new KeyboardId(KBD_SYMBOLS[getCharColorId()], mHasSettingsKey ?
    162                 KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS,
    163                 false, hasVoice);
    164     }
    165 
    166     private KeyboardId makeSymbolsShiftedId(boolean hasVoice) {
    167         return new KeyboardId(KBD_SYMBOLS_SHIFT[getCharColorId()], mHasSettingsKey ?
    168                 KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS,
    169                 false, hasVoice);
    170     }
    171 
    172     public void makeKeyboards(boolean forceCreate) {
    173         mSymbolsId = makeSymbolsId(mHasVoice && !mVoiceOnPrimary);
    174         mSymbolsShiftedId = makeSymbolsShiftedId(mHasVoice && !mVoiceOnPrimary);
    175 
    176         if (forceCreate) mKeyboards.clear();
    177         // Configuration change is coming after the keyboard gets recreated. So don't rely on that.
    178         // If keyboards have already been made, check if we have a screen width change and
    179         // create the keyboard layouts again at the correct orientation
    180         int displayWidth = mInputMethodService.getMaxWidth();
    181         if (displayWidth == mLastDisplayWidth) return;
    182         mLastDisplayWidth = displayWidth;
    183         if (!forceCreate) mKeyboards.clear();
    184     }
    185 
    186     /**
    187      * Represents the parameters necessary to construct a new LatinKeyboard,
    188      * which also serve as a unique identifier for each keyboard type.
    189      */
    190     private static class KeyboardId {
    191         // TODO: should have locale and portrait/landscape orientation?
    192         public final int mXml;
    193         public final int mKeyboardMode; /** A KEYBOARDMODE_XXX value */
    194         public final boolean mEnableShiftLock;
    195         public final boolean mHasVoice;
    196 
    197         private final int mHashCode;
    198 
    199         public KeyboardId(int xml, int mode, boolean enableShiftLock, boolean hasVoice) {
    200             this.mXml = xml;
    201             this.mKeyboardMode = mode;
    202             this.mEnableShiftLock = enableShiftLock;
    203             this.mHasVoice = hasVoice;
    204 
    205             this.mHashCode = Arrays.hashCode(new Object[] {
    206                xml, mode, enableShiftLock, hasVoice
    207             });
    208         }
    209 
    210         public KeyboardId(int xml, boolean hasVoice) {
    211             this(xml, 0, false, hasVoice);
    212         }
    213 
    214         @Override
    215         public boolean equals(Object other) {
    216             return other instanceof KeyboardId && equals((KeyboardId) other);
    217         }
    218 
    219         private boolean equals(KeyboardId other) {
    220             return other.mXml == this.mXml
    221                 && other.mKeyboardMode == this.mKeyboardMode
    222                 && other.mEnableShiftLock == this.mEnableShiftLock
    223                 && other.mHasVoice == this.mHasVoice;
    224         }
    225 
    226         @Override
    227         public int hashCode() {
    228             return mHashCode;
    229         }
    230     }
    231 
    232     public void setVoiceMode(boolean enableVoice, boolean voiceOnPrimary) {
    233         if (enableVoice != mHasVoice || voiceOnPrimary != mVoiceOnPrimary) {
    234             mKeyboards.clear();
    235         }
    236         mHasVoice = enableVoice;
    237         mVoiceOnPrimary = voiceOnPrimary;
    238         setKeyboardMode(mMode, mImeOptions, mHasVoice, mIsSymbols);
    239     }
    240 
    241     private boolean hasVoiceButton(boolean isSymbols) {
    242         return mHasVoice && (isSymbols != mVoiceOnPrimary);
    243     }
    244 
    245     public void setKeyboardMode(int mode, int imeOptions, boolean enableVoice) {
    246         mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
    247         mPreferSymbols = mode == MODE_SYMBOLS;
    248         if (mode == MODE_SYMBOLS) {
    249             mode = MODE_TEXT;
    250         }
    251         try {
    252             setKeyboardMode(mode, imeOptions, enableVoice, mPreferSymbols);
    253         } catch (RuntimeException e) {
    254             LatinImeLogger.logOnException(mode + "," + imeOptions + "," + mPreferSymbols, e);
    255         }
    256     }
    257 
    258     private void setKeyboardMode(int mode, int imeOptions, boolean enableVoice, boolean isSymbols) {
    259         if (mInputView == null) return;
    260         mMode = mode;
    261         mImeOptions = imeOptions;
    262         if (enableVoice != mHasVoice) {
    263             // TODO clean up this unnecessary recursive call.
    264             setVoiceMode(enableVoice, mVoiceOnPrimary);
    265         }
    266         mIsSymbols = isSymbols;
    267 
    268         mInputView.setPreviewEnabled(mInputMethodService.getPopupOn());
    269         KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
    270         LatinKeyboard keyboard = null;
    271         keyboard = getKeyboard(id);
    272 
    273         if (mode == MODE_PHONE) {
    274             mInputView.setPhoneKeyboard(keyboard);
    275         }
    276 
    277         mCurrentId = id;
    278         mInputView.setKeyboard(keyboard);
    279         keyboard.setShifted(false);
    280         keyboard.setShiftLocked(keyboard.isShiftLocked());
    281         keyboard.setImeOptions(mInputMethodService.getResources(), mMode, imeOptions);
    282         keyboard.setColorOfSymbolIcons(mIsAutoCompletionActive, isBlackSym());
    283         // Update the settings key state because number of enabled IMEs could have been changed
    284         updateSettingsKeyState(PreferenceManager.getDefaultSharedPreferences(mInputMethodService));
    285     }
    286 
    287     private LatinKeyboard getKeyboard(KeyboardId id) {
    288         SoftReference<LatinKeyboard> ref = mKeyboards.get(id);
    289         LatinKeyboard keyboard = (ref == null) ? null : ref.get();
    290         if (keyboard == null) {
    291             Resources orig = mInputMethodService.getResources();
    292             Configuration conf = orig.getConfiguration();
    293             Locale saveLocale = conf.locale;
    294             conf.locale = mInputLocale;
    295             orig.updateConfiguration(conf, null);
    296             keyboard = new LatinKeyboard(mInputMethodService, id.mXml, id.mKeyboardMode);
    297             keyboard.setVoiceMode(hasVoiceButton(id.mXml == R.xml.kbd_symbols
    298                     || id.mXml == R.xml.kbd_symbols_black), mHasVoice);
    299             keyboard.setLanguageSwitcher(mLanguageSwitcher, mIsAutoCompletionActive, isBlackSym());
    300 
    301             if (id.mEnableShiftLock) {
    302                 keyboard.enableShiftLock();
    303             }
    304             mKeyboards.put(id, new SoftReference<LatinKeyboard>(keyboard));
    305 
    306             conf.locale = saveLocale;
    307             orig.updateConfiguration(conf, null);
    308         }
    309         return keyboard;
    310     }
    311 
    312     private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) {
    313         boolean hasVoice = hasVoiceButton(isSymbols);
    314         int charColorId = getCharColorId();
    315         // TODO: generalize for any KeyboardId
    316         int keyboardRowsResId = KBD_QWERTY[charColorId];
    317         if (isSymbols) {
    318             if (mode == MODE_PHONE) {
    319                 return new KeyboardId(KBD_PHONE_SYMBOLS[charColorId], hasVoice);
    320             } else {
    321                 return new KeyboardId(KBD_SYMBOLS[charColorId], mHasSettingsKey ?
    322                         KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS,
    323                         false, hasVoice);
    324             }
    325         }
    326         switch (mode) {
    327             case MODE_NONE:
    328                 LatinImeLogger.logOnWarning(
    329                         "getKeyboardId:" + mode + "," + imeOptions + "," + isSymbols);
    330                 /* fall through */
    331             case MODE_TEXT:
    332                 return new KeyboardId(keyboardRowsResId, mHasSettingsKey ?
    333                         KEYBOARDMODE_NORMAL_WITH_SETTINGS_KEY : KEYBOARDMODE_NORMAL,
    334                         true, hasVoice);
    335             case MODE_SYMBOLS:
    336                 return new KeyboardId(KBD_SYMBOLS[charColorId], mHasSettingsKey ?
    337                         KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS,
    338                         false, hasVoice);
    339             case MODE_PHONE:
    340                 return new KeyboardId(KBD_PHONE[charColorId], hasVoice);
    341             case MODE_URL:
    342                 return new KeyboardId(keyboardRowsResId, mHasSettingsKey ?
    343                         KEYBOARDMODE_URL_WITH_SETTINGS_KEY : KEYBOARDMODE_URL, true, hasVoice);
    344             case MODE_EMAIL:
    345                 return new KeyboardId(keyboardRowsResId, mHasSettingsKey ?
    346                         KEYBOARDMODE_EMAIL_WITH_SETTINGS_KEY : KEYBOARDMODE_EMAIL, true, hasVoice);
    347             case MODE_IM:
    348                 return new KeyboardId(keyboardRowsResId, mHasSettingsKey ?
    349                         KEYBOARDMODE_IM_WITH_SETTINGS_KEY : KEYBOARDMODE_IM, true, hasVoice);
    350             case MODE_WEB:
    351                 return new KeyboardId(keyboardRowsResId, mHasSettingsKey ?
    352                         KEYBOARDMODE_WEB_WITH_SETTINGS_KEY : KEYBOARDMODE_WEB, true, hasVoice);
    353         }
    354         return null;
    355     }
    356 
    357     public int getKeyboardMode() {
    358         return mMode;
    359     }
    360 
    361     public boolean isAlphabetMode() {
    362         if (mCurrentId == null) {
    363             return false;
    364         }
    365         int currentMode = mCurrentId.mKeyboardMode;
    366         for (Integer mode : ALPHABET_MODES) {
    367             if (currentMode == mode) {
    368                 return true;
    369             }
    370         }
    371         return false;
    372     }
    373 
    374     public void setShifted(boolean shifted) {
    375         if (mInputView != null) {
    376             mInputView.setShifted(shifted);
    377         }
    378     }
    379 
    380     public void setShiftLocked(boolean shiftLocked) {
    381         if (mInputView != null) {
    382             mInputView.setShiftLocked(shiftLocked);
    383         }
    384     }
    385 
    386     public void toggleShift() {
    387         if (isAlphabetMode())
    388             return;
    389         if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) {
    390             LatinKeyboard symbolsShiftedKeyboard = getKeyboard(mSymbolsShiftedId);
    391             mCurrentId = mSymbolsShiftedId;
    392             mInputView.setKeyboard(symbolsShiftedKeyboard);
    393             // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To
    394             // enable the indicator, we need to call enableShiftLock() and setShiftLocked(true).
    395             // Thus we can keep the ALT key's Key.on value true while LatinKey.onRelease() is
    396             // called.
    397             symbolsShiftedKeyboard.enableShiftLock();
    398             symbolsShiftedKeyboard.setShiftLocked(true);
    399             symbolsShiftedKeyboard.setImeOptions(mInputMethodService.getResources(),
    400                     mMode, mImeOptions);
    401         } else {
    402             LatinKeyboard symbolsKeyboard = getKeyboard(mSymbolsId);
    403             mCurrentId = mSymbolsId;
    404             mInputView.setKeyboard(symbolsKeyboard);
    405             // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
    406             // indicator, we need to call enableShiftLock() and setShiftLocked(false).
    407             symbolsKeyboard.enableShiftLock();
    408             symbolsKeyboard.setShifted(false);
    409             symbolsKeyboard.setImeOptions(mInputMethodService.getResources(), mMode, mImeOptions);
    410         }
    411     }
    412 
    413     public void toggleSymbols() {
    414         setKeyboardMode(mMode, mImeOptions, mHasVoice, !mIsSymbols);
    415         if (mIsSymbols && !mPreferSymbols) {
    416             mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN;
    417         } else {
    418             mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
    419         }
    420     }
    421 
    422     public boolean hasDistinctMultitouch() {
    423         return mInputView != null && mInputView.hasDistinctMultitouch();
    424     }
    425 
    426     /**
    427      * Updates state machine to figure out when to automatically switch back to alpha mode.
    428      * Returns true if the keyboard needs to switch back
    429      */
    430     public boolean onKey(int key) {
    431         // Switch back to alpha mode if user types one or more non-space/enter characters
    432         // followed by a space/enter
    433         switch (mSymbolsModeState) {
    434             case SYMBOLS_MODE_STATE_BEGIN:
    435                 if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key > 0) {
    436                     mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL;
    437                 }
    438                 break;
    439             case SYMBOLS_MODE_STATE_SYMBOL:
    440                 if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) return true;
    441                 break;
    442         }
    443         return false;
    444     }
    445 
    446     public LatinKeyboardView getInputView() {
    447         return mInputView;
    448     }
    449 
    450     public void recreateInputView() {
    451         changeLatinKeyboardView(mLayoutId, true);
    452     }
    453 
    454     private void changeLatinKeyboardView(int newLayout, boolean forceReset) {
    455         if (mLayoutId != newLayout || mInputView == null || forceReset) {
    456             if (mInputView != null) {
    457                 mInputView.closing();
    458             }
    459             if (THEMES.length <= newLayout) {
    460                 newLayout = Integer.valueOf(DEFAULT_LAYOUT_ID);
    461             }
    462 
    463             LatinIMEUtil.GCUtils.getInstance().reset();
    464             boolean tryGC = true;
    465             for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
    466                 try {
    467                     mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater(
    468                             ).inflate(THEMES[newLayout], null);
    469                     tryGC = false;
    470                 } catch (OutOfMemoryError e) {
    471                     tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait(
    472                             mLayoutId + "," + newLayout, e);
    473                 } catch (InflateException e) {
    474                     tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait(
    475                             mLayoutId + "," + newLayout, e);
    476                 }
    477             }
    478             mInputView.setOnKeyboardActionListener(mInputMethodService);
    479             mLayoutId = newLayout;
    480         }
    481         mInputMethodService.mHandler.post(new Runnable() {
    482             public void run() {
    483                 if (mInputView != null) {
    484                     mInputMethodService.setInputView(mInputView);
    485                 }
    486                 mInputMethodService.updateInputViewShown();
    487             }});
    488     }
    489 
    490     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    491         if (PREF_KEYBOARD_LAYOUT.equals(key)) {
    492             changeLatinKeyboardView(
    493                     Integer.valueOf(sharedPreferences.getString(key, DEFAULT_LAYOUT_ID)), false);
    494         } else if (LatinIMESettings.PREF_SETTINGS_KEY.equals(key)) {
    495             updateSettingsKeyState(sharedPreferences);
    496             recreateInputView();
    497         }
    498     }
    499 
    500     public boolean isBlackSym () {
    501         if (mInputView != null && mInputView.getSymbolColorScheme() == 1) {
    502             return true;
    503         }
    504         return false;
    505     }
    506 
    507     private int getCharColorId () {
    508         if (isBlackSym()) {
    509             return CHAR_THEME_COLOR_BLACK;
    510         } else {
    511             return CHAR_THEME_COLOR_WHITE;
    512         }
    513     }
    514 
    515     public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
    516         if (isAutoCompletion != mIsAutoCompletionActive) {
    517             LatinKeyboardView keyboardView = getInputView();
    518             mIsAutoCompletionActive = isAutoCompletion;
    519             keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard())
    520                     .onAutoCompletionStateChanged(isAutoCompletion));
    521         }
    522     }
    523 
    524     private void updateSettingsKeyState(SharedPreferences prefs) {
    525         Resources resources = mInputMethodService.getResources();
    526         final String settingsKeyMode = prefs.getString(LatinIMESettings.PREF_SETTINGS_KEY,
    527                 resources.getString(DEFAULT_SETTINGS_KEY_MODE));
    528         // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or
    529         // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system
    530         if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW))
    531                 || (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO))
    532                         && LatinIMEUtil.hasMultipleEnabledIMEs(mInputMethodService))) {
    533             mHasSettingsKey = true;
    534         } else {
    535             mHasSettingsKey = false;
    536         }
    537     }
    538 }
    539