diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java index 828aea41f..7d8c745c3 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java @@ -16,12 +16,12 @@ package com.android.inputmethod.compat; -import com.android.inputmethod.deprecated.LanguageSwitcherProxy; -import com.android.inputmethod.latin.SubtypeSwitcher; - import android.inputmethodservice.InputMethodService; import android.view.inputmethod.InputMethodSubtype; +import com.android.inputmethod.deprecated.LanguageSwitcherProxy; +import com.android.inputmethod.latin.SubtypeSwitcher; + public class InputMethodServiceCompatWrapper extends InputMethodService { // CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10 // or previous. Note that InputMethodSubtype was added in the API level 11. diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index af2220811..8657768ee 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -43,7 +43,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; public static final boolean DEBUG_STATE = false; - private static String sConfigDefaultKeyboardThemeId; public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; private static final int[] KEYBOARD_THEMES = { R.style.KeyboardTheme, @@ -102,7 +101,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha // Default is SETTINGS_KEY_MODE_AUTO. private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; - private int mThemeIndex; + private int mThemeIndex = -1; + private Context mThemeContext; private int mKeyboardWidth; private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); @@ -119,19 +119,32 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha sInstance.mInputMethodService = ims; sInstance.mPrefs = prefs; sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - - try { - sConfigDefaultKeyboardThemeId = ims.getString( - R.string.config_default_keyboard_theme_id); - sInstance.mThemeIndex = Integer.valueOf( - prefs.getString(PREF_KEYBOARD_LAYOUT, sConfigDefaultKeyboardThemeId)); - } catch (NumberFormatException e) { - sConfigDefaultKeyboardThemeId = "0"; - sInstance.mThemeIndex = 0; - } + sInstance.setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs)); prefs.registerOnSharedPreferenceChangeListener(sInstance); } + private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) { + final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id); + final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId); + try { + final int themeIndex = Integer.valueOf(themeId); + if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length) + return themeIndex; + } catch (NumberFormatException e) { + // Format error, keyboard theme is default to 0. + } + Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0"); + return 0; + } + + private void setContextThemeWrapper(Context context, int themeIndex) { + if (mThemeIndex != themeIndex) { + mThemeIndex = themeIndex; + mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]); + mKeyboardCache.clear(); + } + } + public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled, boolean voiceButtonOnPrimary) { mSwitchState = SWITCH_STATE_ALPHA; @@ -202,9 +215,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha final Locale savedLocale = Utils.setSystemLocale(res, mSubtypeSwitcher.getInputLocale()); - final Context themeContext = new ContextThemeWrapper(mInputMethodService, - KEYBOARD_THEMES[mThemeIndex]); - keyboard = new LatinKeyboard(themeContext, id, id.mWidth); + keyboard = new LatinKeyboard(mThemeContext, id, id.mWidth); if (id.mEnableShiftLock) { keyboard.enableShiftLock(); @@ -724,30 +735,29 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha if (mKeyboardView != null) { mKeyboardView.closing(); } - final int themeIndex = (newThemeIndex < KEYBOARD_THEMES.length) ? newThemeIndex - : Integer.valueOf(sConfigDefaultKeyboardThemeId); + final int oldThemeIndex = mThemeIndex; Utils.GCUtils.getInstance().reset(); boolean tryGC = true; for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { try { - final Context themeContext = new ContextThemeWrapper(mInputMethodService, - KEYBOARD_THEMES[themeIndex]); - mCurrentInputView = LayoutInflater.from(themeContext).inflate( + setContextThemeWrapper(mInputMethodService, newThemeIndex); + mCurrentInputView = LayoutInflater.from(mThemeContext).inflate( R.layout.input_view, null); tryGC = false; } catch (OutOfMemoryError e) { Log.w(TAG, "load keyboard failed: " + e); - tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait( + oldThemeIndex + "," + newThemeIndex, e); } catch (InflateException e) { Log.w(TAG, "load keyboard failed: " + e); - tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait( + oldThemeIndex + "," + newThemeIndex, e); } } mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view); mKeyboardView.setOnKeyboardActionListener(mInputMethodService); - mThemeIndex = themeIndex; return mCurrentInputView; } @@ -766,8 +776,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (PREF_KEYBOARD_LAYOUT.equals(key)) { - final int layoutId = Integer.valueOf( - sharedPreferences.getString(key, sConfigDefaultKeyboardThemeId)); + final int layoutId = getKeyboardThemeIndex(mInputMethodService, sharedPreferences); postSetInputView(createInputView(layoutId, false)); } else if (Settings.PREF_SETTINGS_KEY.equals(key)) { mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences, diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 44f2ff3ff..f73cdc083 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -626,8 +626,14 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mDirtyRect.union(0, 0, width, height); } if (mBuffer == null || mBuffer.getWidth() != width || mBuffer.getHeight() != height) { + if (mBuffer != null) + mBuffer.recycle(); mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - mCanvas = new Canvas(mBuffer); + if (mCanvas != null) { + mCanvas.setBitmap(mBuffer); + } else { + mCanvas = new Canvas(mBuffer); + } } final Canvas canvas = mCanvas; canvas.clipRect(mDirtyRect, Op.REPLACE); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index a6ac76751..473006deb 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -16,9 +16,6 @@ package com.android.inputmethod.keyboard; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; - import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -36,6 +33,9 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.SubtypeSwitcher; + import java.lang.ref.SoftReference; import java.util.Arrays; import java.util.HashMap; @@ -49,7 +49,8 @@ public class LatinKeyboard extends Keyboard { public static final int CODE_NEXT_LANGUAGE = -100; public static final int CODE_PREV_LANGUAGE = -101; - private final Context mContext; + private final Resources mRes; + private final Theme mTheme; private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance(); /* Space key and its icons, drawables and colors. */ @@ -65,7 +66,7 @@ public class LatinKeyboard extends Keyboard { private float mSpacebarTextFadeFactor = 0.0f; private final int mSpacebarLanguageSwitchThreshold; private int mSpacebarSlidingLanguageSwitchDiff; - private SlidingLocaleDrawable mSlidingLocaleIcon; + private final SlidingLocaleDrawable mSlidingLocaleIcon; private final HashMap> mSpaceDrawableCache = new HashMap>(); @@ -90,7 +91,8 @@ public class LatinKeyboard extends Keyboard { public LatinKeyboard(Context context, KeyboardId id, int width) { super(context, id.getXmlId(), id, width); - mContext = context; + mRes = context.getResources(); + mTheme = context.getTheme(); final List keys = getKeys(); int spaceKeyIndex = -1; @@ -133,6 +135,13 @@ public class LatinKeyboard extends Keyboard { // The threshold is "key width" x 1.25 mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 5) / 4; + + final int spaceKeyWidth = Math.max(mSpaceKey.mWidth, + (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO)); + final int spaceKeyheight = mSpacePreviewIcon.getIntrinsicHeight(); + mSlidingLocaleIcon = new SlidingLocaleDrawable( + context, mSpacePreviewIcon, spaceKeyWidth, spaceKeyheight); + mSlidingLocaleIcon.setBounds(0, 0, spaceKeyWidth, spaceKeyheight); } public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) { @@ -250,7 +259,7 @@ public class LatinKeyboard extends Keyboard { final SoftReference ref = mSpaceDrawableCache.get(hashCode); BitmapDrawable drawable = (ref == null) ? null : ref.get(); if (drawable == null) { - drawable = new BitmapDrawable(mContext.getResources(), drawSpacebar( + drawable = new BitmapDrawable(mRes, drawSpacebar( locale, isAutoCorrection, mSpacebarTextFadeFactor)); mSpaceDrawableCache.put(hashCode, new SoftReference(drawable)); } @@ -263,7 +272,7 @@ public class LatinKeyboard extends Keyboard { final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight; final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(buffer); - final Resources res = mContext.getResources(); + final Resources res = mRes; canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); // If application locales are explicitly selected. @@ -287,7 +296,7 @@ public class LatinKeyboard extends Keyboard { final String language = layoutSpacebar(paint, inputLocale, mSpacebarArrowLeftIcon, mSpacebarArrowRightIcon, width, height, - getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize)); + getTextSizeFromTheme(mTheme, textStyle, defaultTextSize)); // Draw language text with shadow // In case there is no space icon, we will place the language text at the center of @@ -341,14 +350,6 @@ public class LatinKeyboard extends Keyboard { if (mSpacebarSlidingLanguageSwitchDiff == diff) return; mSpacebarSlidingLanguageSwitchDiff = diff; - if (mSlidingLocaleIcon == null) { - final int width = Math.max(mSpaceKey.mWidth, - (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO)); - final int height = mSpacePreviewIcon.getIntrinsicHeight(); - mSlidingLocaleIcon = - new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height); - mSlidingLocaleIcon.setBounds(0, 0, width, height); - } mSlidingLocaleIcon.setDiff(diff); if (Math.abs(diff) == Integer.MAX_VALUE) { mSpaceKey.setPreviewIcon(mSpacePreviewIcon); @@ -403,7 +404,7 @@ public class LatinKeyboard extends Keyboard { Math.max(0, Math.min(y, getHeight() - 1))); } - private static int getTextSizeFromTheme(Theme theme, int style, int defValue) { + public static int getTextSizeFromTheme(Theme theme, int style, int defValue) { TypedArray array = theme.obtainStyledAttributes( style, new int[] { android.R.attr.textSize }); int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue); diff --git a/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java b/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java index a20bf1cd3..dd271de64 100644 --- a/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java +++ b/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java @@ -60,8 +60,8 @@ public class SlidingLocaleDrawable extends Drawable { mWidth = width; mHeight = height; final TextPaint textPaint = new TextPaint(); - textPaint.setTextSize(getTextSizeFromTheme( - context, android.R.style.TextAppearance_Medium, 18)); + textPaint.setTextSize(LatinKeyboard.getTextSizeFromTheme( + context.getTheme(), android.R.style.TextAppearance_Medium, 18)); textPaint.setColor(Color.TRANSPARENT); textPaint.setTextAlign(Align.CENTER); textPaint.setAntiAlias(true); @@ -78,13 +78,6 @@ public class SlidingLocaleDrawable extends Drawable { mThreshold = ViewConfiguration.get(context).getScaledTouchSlop(); } - private static int getTextSizeFromTheme(Context context, int style, int defValue) { - TypedArray array = context.getTheme().obtainStyledAttributes( - style, new int[] { android.R.attr.textSize }); - int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue); - return textSize; - } - void setDiff(int diff) { if (diff == Integer.MAX_VALUE) { mHitThreshold = false; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7446aff9e..fd4a47c39 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1871,7 +1871,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } // The following is necessary because on API levels < 10, we don't get notified when // subtype changes. - onRefreshKeyboard(); + if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) + onRefreshKeyboard(); } @Override