diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 492883caf..1e76571be 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -151,16 +151,11 @@ public class Keyboard { * @param context the application or service context * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. * @param id keyboard identifier + * @param width keyboard width */ - public Keyboard(Context context, int xmlLayoutResId, KeyboardId id) { - this(context, xmlLayoutResId, id, - context.getResources().getDisplayMetrics().widthPixels, - context.getResources().getDisplayMetrics().heightPixels); - } - private Keyboard(Context context, int xmlLayoutResId, KeyboardId id, int width, - int height) { - Resources res = context.getResources(); + public Keyboard(Context context, int xmlLayoutResId, KeyboardId id, int width) { + final Resources res = context.getResources(); GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); GRID_SIZE = GRID_WIDTH * GRID_HEIGHT; @@ -168,7 +163,8 @@ public class Keyboard { final int horizontalEdgesPadding = (int)res.getDimension( R.dimen.keyboard_horizontal_edges_padding); mDisplayWidth = width - horizontalEdgesPadding * 2; - mDisplayHeight = height; + // TODO: Adjust the height by referring to the height of area available for drawing as well. + mDisplayHeight = res.getDisplayMetrics().heightPixels; mDefaultHorizontalGap = 0; setKeyWidth(mDisplayWidth / 10); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index f68b68f1d..eabbf709c 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -40,6 +40,7 @@ public class KeyboardId { public final Locale mLocale; public final int mOrientation; + public final int mWidth; public final int mMode; public final int mXmlId; public final int mColorScheme; @@ -49,17 +50,20 @@ public class KeyboardId { public final boolean mHasVoiceKey; public final int mImeAction; public final boolean mEnableShiftLock; + public final String mXmlName; + public final EditorInfo mAttribute; private final int mHashCode; public KeyboardId(String xmlName, int xmlId, int colorScheme, Locale locale, int orientation, - int mode, EditorInfo attribute, boolean hasSettingsKey, boolean voiceKeyEnabled, - boolean hasVoiceKey, boolean enableShiftLock) { + int width, int mode, EditorInfo attribute, boolean hasSettingsKey, + boolean voiceKeyEnabled, boolean hasVoiceKey, boolean enableShiftLock) { final int inputType = (attribute != null) ? attribute.inputType : 0; final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; this.mLocale = locale; this.mOrientation = orientation; + this.mWidth = width; this.mMode = mode; this.mXmlId = xmlId; this.mColorScheme = colorScheme; @@ -73,11 +77,14 @@ public class KeyboardId { this.mImeAction = imeOptions & ( EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION); this.mEnableShiftLock = enableShiftLock; + this.mXmlName = xmlName; + this.mAttribute = attribute; this.mHashCode = Arrays.hashCode(new Object[] { locale, orientation, + width, mode, xmlId, colorScheme, @@ -90,6 +97,18 @@ public class KeyboardId { }); } + public KeyboardId cloneWithNewLayout(String xmlName, int xmlId) { + return new KeyboardId(xmlName, xmlId, mColorScheme, mLocale, mOrientation, mWidth, mMode, + mAttribute, mHasSettingsKey, mVoiceKeyEnabled, mHasVoiceKey, mEnableShiftLock); + } + + public KeyboardId cloneWithNewGeometry(int width) { + if (mWidth == width) + return this; + return new KeyboardId(mXmlName, mXmlId, mColorScheme, mLocale, mOrientation, width, mMode, + mAttribute, mHasSettingsKey, mVoiceKeyEnabled, mHasVoiceKey, mEnableShiftLock); + } + public int getXmlId() { return mXmlId; } @@ -118,6 +137,7 @@ public class KeyboardId { boolean equals(KeyboardId other) { return other.mLocale.equals(this.mLocale) && other.mOrientation == this.mOrientation + && other.mWidth == this.mWidth && other.mMode == this.mMode && other.mXmlId == this.mXmlId && other.mColorScheme == this.mColorScheme @@ -136,10 +156,10 @@ public class KeyboardId { @Override public String toString() { - return String.format("[%s.xml %s %s %s imeAction=%s %s%s%s%s%s%s]", + return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s]", mXmlName, mLocale, - (mOrientation == 1 ? "port" : "land"), + (mOrientation == 1 ? "port" : "land"), mWidth, modeName(mMode), EditorInfoCompatUtils.imeOptionsName(mImeAction), (mPasswordInput ? " passwordInput" : ""), diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 384139112..88823108f 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -37,7 +37,7 @@ import java.util.Locale; public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "KeyboardSwitcher"; - private static final boolean DEBUG = false; + private static final boolean DEBUG_CACHE = false; public static final boolean DEBUG_STATE = false; private static String sConfigDefaultKeyboardThemeId; @@ -99,6 +99,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; private int mLayoutId; + private int mKeyboardWidth; private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); @@ -151,17 +152,39 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha // Update the settings key state because number of enabled IMEs could have been changed mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService); final KeyboardId id = getKeyboardId(attribute, isSymbols); - makeSymbolsKeyboardIds(id.mMode, attribute); - mCurrentId = id; - final Resources res = mInputMethodService.getResources(); - mInputView.setKeyPreviewPopupEnabled(Settings.Values.isKeyPreviewPopupEnabled(mPrefs, res), - Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, res)); + + // Note: This comment is only applied for phone number keyboard layout. + // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch + // between "phone keyboard" and "phone symbols keyboard". But on xlarge device, + // "@integer/key_shift" key code is used for that purpose in order to properly display + // "more" and "locked more" key labels. To achieve these behavior, we should initialize + // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" + // respectively here for xlarge device's layout switching. + mSymbolsId = makeSiblingKeyboardId(id, R.xml.kbd_symbols, R.xml.kbd_phone); + mSymbolsShiftedId = makeSiblingKeyboardId( + id, R.xml.kbd_symbols_shift, R.xml.kbd_phone_symbols); + setKeyboard(getKeyboard(id)); } + public void onSizeChanged() { + final int width = mInputMethodService.getWindow().getWindow().getDecorView().getWidth(); + if (width == 0) + return; + mKeyboardWidth = width; + // Set keyboard with new width. + final KeyboardId newId = mCurrentId.cloneWithNewGeometry(width); + setKeyboard(getKeyboard(newId)); + } + private void setKeyboard(final Keyboard newKeyboard) { final Keyboard oldKeyboard = mInputView.getKeyboard(); mInputView.setKeyboard(newKeyboard); + mCurrentId = newKeyboard.mId; + final Resources res = mInputMethodService.getResources(); + mInputView.setKeyPreviewPopupEnabled( + Settings.Values.isKeyPreviewPopupEnabled(mPrefs, res), + Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, res)); final boolean localeChanged = (oldKeyboard == null) || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); @@ -175,19 +198,19 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha final Locale savedLocale = Utils.setSystemLocale(res, mSubtypeSwitcher.getInputLocale()); - keyboard = new LatinKeyboard(mInputMethodService, id); + keyboard = new LatinKeyboard(mInputMethodService, id, id.mWidth); if (id.mEnableShiftLock) { keyboard.enableShiftLock(); } mKeyboardCache.put(id, new SoftReference(keyboard)); - if (DEBUG) + if (DEBUG_CACHE) Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); Utils.setSystemLocale(res, savedLocale); - } else if (DEBUG) { + } else if (DEBUG_CACHE) { Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); } @@ -244,33 +267,19 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha final boolean hasSettingsKey = hasSettingsKey(attribute); final Resources res = mInputMethodService.getResources(); final int orientation = res.getConfiguration().orientation; + if (mKeyboardWidth == 0) + mKeyboardWidth = res.getDisplayMetrics().widthPixels; final Locale locale = mSubtypeSwitcher.getInputLocale(); return new KeyboardId( - res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, mode, - attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, enableShiftLock); + res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, + mKeyboardWidth, mode, attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, + enableShiftLock); } - private void makeSymbolsKeyboardIds(final int mode, EditorInfo attribute) { - final Locale locale = mSubtypeSwitcher.getInputLocale(); - final Resources res = mInputMethodService.getResources(); - final int orientation = res.getConfiguration().orientation; - final int colorScheme = getColorScheme(); - final boolean hasVoiceKey = mVoiceKeyEnabled && !mVoiceButtonOnPrimary; - final boolean hasSettingsKey = hasSettingsKey(attribute); - // Note: This comment is only applied for phone number keyboard layout. - // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch - // between "phone keyboard" and "phone symbols keyboard". But on xlarge device, - // "@integer/key_shift" key code is used for that purpose in order to properly display - // "more" and "locked more" key labels. To achieve these behavior, we should initialize - // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" - // respectively here for xlarge device's layout switching. - int xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols; - final String xmlName = res.getResourceEntryName(xmlId); - mSymbolsId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode, - attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, false); - xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift; - mSymbolsShiftedId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode, - attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, false); + private KeyboardId makeSiblingKeyboardId(KeyboardId base, int alphabet, int phone) { + final int xmlId = base.mMode == KeyboardId.MODE_PHONE ? phone : alphabet; + final String xmlName = mInputMethodService.getResources().getResourceEntryName(xmlId); + return base.cloneWithNewLayout(xmlName, xmlId); } public int getKeyboardMode() { @@ -561,14 +570,12 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha return; final LatinKeyboard keyboard; if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { - mCurrentId = mSymbolsShiftedId; - keyboard = getKeyboard(mCurrentId); + keyboard = getKeyboard(mSymbolsShiftedId); // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To // enable the indicator, we need to call setShiftLocked(true). keyboard.setShiftLocked(true); } else { - mCurrentId = mSymbolsId; - keyboard = getKeyboard(mCurrentId); + keyboard = getKeyboard(mSymbolsId); // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the // indicator, we need to call setShiftLocked(false). keyboard.setShiftLocked(false); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 4f85c0348..1df6444a0 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -462,6 +462,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { return mKeyboardActionListener; } + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + // TODO: Should notify InputMethodService instead? + KeyboardSwitcher.getInstance().onSizeChanged(); + } + /** * Attaches a keyboard to this view. The keyboard can be switched at any time and the * view will re-layout itself to accommodate the keyboard. diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index c279769f6..16aa59689 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -88,8 +88,8 @@ public class LatinKeyboard extends Keyboard { private static final String SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "small"; private static final String MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "medium"; - public LatinKeyboard(Context context, KeyboardId id) { - super(context, id.getXmlId(), id); + public LatinKeyboard(Context context, KeyboardId id, int width) { + super(context, id.getXmlId(), id, width); final Resources res = context.getResources(); mContext = context; diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java index 5dde15e94..69e9dd8da 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java @@ -23,8 +23,8 @@ import java.util.List; public class MiniKeyboard extends Keyboard { private int mDefaultKeyCoordX; - public MiniKeyboard(Context context, int xmlLayoutResId, KeyboardId id) { - super(context, xmlLayoutResId, id); + public MiniKeyboard(Context context, int xmlLayoutResId, Keyboard parentKeyboard) { + super(context, xmlLayoutResId, null, parentKeyboard.getMinWidth()); } public void setDefaultCoordX(int pos) { diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java index 2b83c3ff5..29f41cd22 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java @@ -185,7 +185,8 @@ public class MiniKeyboardBuilder { Keyboard parentKeyboard) { final Context context = view.getContext(); mRes = context.getResources(); - final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null); + final MiniKeyboard keyboard = new MiniKeyboard( + context, layoutTemplateResId, parentKeyboard); mKeyboard = keyboard; mPopupCharacters = parentKey.mPopupCharacters; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 2c39eba55..4043b3581 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -623,6 +623,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + @Override + public void onWindowHidden() { + super.onWindowHidden(); + KeyboardView inputView = mKeyboardSwitcher.getInputView(); + if (inputView != null) inputView.closing(); + } + @Override public void onFinishInput() { super.onFinishInput(); @@ -809,7 +816,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (isExtractViewShown()) { // No need to have extra space to show the key preview. mCandidateViewContainer.setMinimumHeight(0); - super.setCandidatesViewShown(shown); + super.setCandidatesViewShown(shouldShowCandidates); } else { // We must control the visibility of the suggestion strip in order to avoid clipped // key previews, even when we don't show the suggestion strip. diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java index 8a11ff955..87ea011fa 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java +++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java @@ -36,7 +36,7 @@ public class SuggestHelper { // Use null as the locale for Suggest so as to force it to use the internal dictionary // (and not try to find a dictionary provider for a specified locale) mSuggest = new Suggest(context, dictionaryId, null); - mKeyboard = new LatinKeyboard(context, keyboardId); + mKeyboard = new LatinKeyboard(context, keyboardId, keyboardId.mWidth); mKeyDetector = new KeyDetector(); init(); } @@ -44,7 +44,7 @@ public class SuggestHelper { protected SuggestHelper(Context context, File dictionaryPath, long startOffset, long length, KeyboardId keyboardId) { mSuggest = new Suggest(context, dictionaryPath, startOffset, length, null); - mKeyboard = new LatinKeyboard(context, keyboardId); + mKeyboard = new LatinKeyboard(context, keyboardId, keyboardId.mWidth); mKeyDetector = new KeyDetector(); init(); } diff --git a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java index 64f26743e..cf4ccfeaa 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java +++ b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java @@ -38,10 +38,11 @@ public class SuggestTestsBase extends AndroidTestCase { mTestPackageFile = new File(getTestContext().getApplicationInfo().sourceDir); } - protected static KeyboardId createKeyboardId(Locale locale) { + protected KeyboardId createKeyboardId(Locale locale) { + final int displayWidth = getContext().getResources().getDisplayMetrics().widthPixels; return new KeyboardId(locale.toString() + " keyboard", com.android.inputmethod.latin.R.xml.kbd_qwerty, KeyboardView.COLOR_SCHEME_WHITE, - locale, Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT, + locale, displayWidth, Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT, new EditorInfo(), false, false, false, false); }