diff options
Diffstat (limited to 'java')
21 files changed, 302 insertions, 267 deletions
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index 1f7736d9c..8bd25c00d 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -120,6 +120,7 @@ <!-- Title for Latin keyboard debug settings activity / dialog --> <string name="english_ime_debug_settings">Android keyboard Debug settings</string> <string name="prefs_debug_mode">Debug Mode</string> + <string name="prefs_force_non_distinct_multitouch">Force non-distinct multitouch</string> <!-- Keyboard theme names --> <string name="layout_basic">Basic</string> @@ -161,6 +162,8 @@ <!-- Generic subtype label --> <string name="subtype_generic">%s</string> + <!-- Description for generic QWERTY keyboard subtype --> + <string name="subtype_generic_qwerty">%s (QWERTY)</string> <!-- dictionary pack package name /settings activity (for shared prefs and settings) --> <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index d860a1b23..f7d8b4533 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -335,8 +335,6 @@ <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]--> <string name="keyboard_layout">Keyboard theme</string> - <!-- Description for German QWERTY keyboard subtype [CHAR LIMIT=22] --> - <string name="subtype_de_qwerty">German QWERTY</string> <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=22] --> <string name="subtype_en_GB">English (UK)</string> <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=22] --> diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index a3b1d5859..6c827363c 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -71,7 +71,7 @@ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" /> <subtype android:icon="@drawable/ic_subtype_keyboard" - android:label="@string/subtype_de_qwerty" + android:label="@string/subtype_generic_qwerty" android:imeSubtypeLocale="de" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ,SupportTouchPositionCorrection" diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml index 80613a56f..f38b85f0b 100644 --- a/java/res/xml/prefs_for_debug.xml +++ b/java/res/xml/prefs_for_debug.xml @@ -42,4 +42,10 @@ android:defaultValue="false" /> + <CheckBoxPreference + android:key="force_non_distinct_multitouch" + android:title="@string/prefs_force_non_distinct_multitouch" + android:persistent="true" + android:defaultValue="false" + /> </PreferenceScreen> diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java index bcdcef7dc..e1db36088 100644 --- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java @@ -26,12 +26,16 @@ public class EditorInfoCompatUtils { EditorInfo.class, "IME_FLAG_NAVIGATE_NEXT"); private static final Field FIELD_IME_FLAG_NAVIGATE_PREVIOUS = CompatUtils.getField( EditorInfo.class, "IME_FLAG_NAVIGATE_PREVIOUS"); + private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField( + EditorInfo.class, "IME_FLAG_FORCE_ASCII"); private static final Field FIELD_IME_ACTION_PREVIOUS = CompatUtils.getField( EditorInfo.class, "IME_ACTION_PREVIOUS"); private static final Integer OBJ_IME_FLAG_NAVIGATE_NEXT = (Integer) CompatUtils .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_NEXT); private static final Integer OBJ_IME_FLAG_NAVIGATE_PREVIOUS = (Integer) CompatUtils .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_PREVIOUS); + private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII); private static final Integer OBJ_IME_ACTION_PREVIOUS = (Integer) CompatUtils .getFieldValue(null, null, FIELD_IME_ACTION_PREVIOUS); @@ -47,6 +51,12 @@ public class EditorInfoCompatUtils { return (imeOptions & OBJ_IME_FLAG_NAVIGATE_PREVIOUS) != 0; } + public static boolean hasFlagForceAscii(int imeOptions) { + if (OBJ_IME_FLAG_FORCE_ASCII == null) + return false; + return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0; + } + public static void performEditorActionNext(InputConnection ic) { ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); } @@ -93,10 +103,19 @@ public class EditorInfoCompatUtils { break; } } + final StringBuilder flags = new StringBuilder(); if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { - return "flagNoEnterAction|" + action; - } else { - return action; + flags.append("flagNoEnterAction|"); + } + if (hasFlagNavigateNext(imeOptions)) { + flags.append("flagNavigateNext|"); + } + if (hasFlagNavigatePrevious(imeOptions)) { + flags.append("flagNavigatePrevious|"); + } + if (hasFlagForceAscii(imeOptions)) { + flags.append("flagForceAscii|"); } + return flags + action; } } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index c1d024cef..5816e5680 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -434,9 +434,23 @@ public class Keyboard { case CODE_SHORTCUT: return "shortcut"; case CODE_UNSPECIFIED: return "unspec"; default: - if (code < 0) Log.w(TAG, "Unknow negative key code=" + code); - if (code < 0x100) return String.format("\\u%02x", code); - return String.format("\\u04x", code); + if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code); + if (code < CODE_SPACE) return String.format("'\\u%02x'", code); + if (code < 0x100) return String.format("'%c'", code); + return String.format("'\\u%04x'", code); + } + } + + public static String toThemeName(int themeId) { + // This should be aligned with theme-*.xml resource files' themeId attribute. + switch (themeId) { + case 0: return "Basic"; + case 1: return "BasicHighContrast"; + case 5: return "IceCreamSandwich"; + case 6: return "Stone"; + case 7: return "StoneBold"; + case 8: return "GingerBread"; + default: return null; } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index 6f5420882..dce2c37f2 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -24,10 +24,8 @@ public interface KeyboardActionListener { * * @param primaryCode the unicode of the key being pressed. If the touch is not on a valid key, * the value will be zero. - * @param withSliding true if pressing has occurred because the user slid finger from other key - * to this key without releasing the finger. */ - public void onPress(int primaryCode, boolean withSliding); + public void onPressKey(int primaryCode); /** * Called when the user releases a key. This is sent after the {@link #onCodeInput} is called. @@ -37,7 +35,7 @@ public interface KeyboardActionListener { * @param withSliding true if releasing has occurred because the user slid finger from the key * to other key without releasing the finger. */ - public void onRelease(int primaryCode, boolean withSliding); + public void onReleaseKey(int primaryCode, boolean withSliding); /** * Send a key code to the listener. @@ -79,9 +77,9 @@ public interface KeyboardActionListener { public static class Adapter implements KeyboardActionListener { @Override - public void onPress(int primaryCode, boolean withSliding) {} + public void onPressKey(int primaryCode) {} @Override - public void onRelease(int primaryCode, boolean withSliding) {} + public void onReleaseKey(int primaryCode, boolean withSliding) {} @Override public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {} @Override diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index a2e784c99..285252044 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -17,6 +17,7 @@ package com.android.inputmethod.keyboard; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; @@ -24,12 +25,11 @@ import android.util.Log; import android.util.Xml; import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LocaleUtils; 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 com.android.inputmethod.latin.XmlParseUtils; @@ -61,6 +61,7 @@ public class KeyboardSet { int mMode; int mInputType; int mImeOptions; + boolean mTouchPositionCorrectionEnabled; boolean mSettingsKeyEnabled; boolean mVoiceKeyEnabled; boolean mVoiceKeyOnMain; @@ -115,9 +116,8 @@ public class KeyboardSet { return Builder.getKeyboardId(elementState, false, mParams); } - private static Keyboard getKeyboard(Context context, int xmlId, KeyboardId id) { + private Keyboard getKeyboard(Context context, int xmlId, KeyboardId id) { final Resources res = context.getResources(); - final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance(); final SoftReference<Keyboard> ref = sKeyboardCache.get(id); Keyboard keyboard = (ref == null) ? null : ref.get(); if (keyboard == null) { @@ -126,9 +126,7 @@ public class KeyboardSet { final Keyboard.Builder<Keyboard.Params> builder = new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params()); builder.load(xmlId, id); - builder.setTouchPositionCorrectionEnabled( - subtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); + builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled); keyboard = builder.build(); } finally { LocaleUtils.setSystemLocale(res, savedLocale); @@ -151,15 +149,17 @@ public class KeyboardSet { public static class Builder { private final Context mContext; + private final String mPackageName; private final Resources mResources; + private final EditorInfo mEditorInfo; private final Params mParams = new Params(); - public Builder(Context context, EditorInfo editorInfo, SettingsValues settingsValues) { + public Builder(Context context, EditorInfo editorInfo) { mContext = context; + mPackageName = context.getPackageName(); mResources = context.getResources(); - final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance(); - final String packageName = context.getPackageName(); + mEditorInfo = editorInfo; final Params params = mParams; params.mMode = Utils.getKeyboardMode(editorInfo); @@ -167,27 +167,46 @@ public class KeyboardSet { params.mInputType = editorInfo.inputType; params.mImeOptions = editorInfo.imeOptions; } - params.mSettingsKeyEnabled = settingsValues.isSettingsKeyEnabled(); + params.mNoSettingsKey = Utils.inPrivateImeOptions( + mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo); + } + + public Builder setScreenGeometry(int orientation, int widthPixels) { + mParams.mOrientation = orientation; + mParams.mWidth = widthPixels; + return this; + } + + // TODO: Use InputMethodSubtype object as argument. + public Builder setSubtype(Locale inputLocale, boolean asciiCapable, + boolean touchPositionCorrectionEnabled) { + final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(mParams.mImeOptions) + || Utils.inPrivateImeOptions( + mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); + mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale; + mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled; + return this; + } + + public Builder setOptions(boolean settingsKeyEnabled, boolean voiceKeyEnabled, + boolean voiceKeyOnMain) { + mParams.mSettingsKeyEnabled = settingsKeyEnabled; @SuppressWarnings("deprecation") final boolean noMicrophone = Utils.inPrivateImeOptions( - packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo) + mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, mEditorInfo) || Utils.inPrivateImeOptions( - null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo); - params.mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone; - params.mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain(); - params.mNoSettingsKey = Utils.inPrivateImeOptions( - packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo); - final boolean forceAscii = Utils.inPrivateImeOptions( - packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo); - final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE); - params.mLocale = (forceAscii && !asciiCapable) - ? Locale.US : subtypeSwitcher.getInputLocale(); - params.mOrientation = mResources.getConfiguration().orientation; - params.mWidth = mResources.getDisplayMetrics().widthPixels; + null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); + mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone; + mParams.mVoiceKeyOnMain = voiceKeyOnMain; + return this; } public KeyboardSet build() { + if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED) + throw new RuntimeException("Screen geometry is not specified"); + if (mParams.mLocale == null) + throw new RuntimeException("KeyboardSet subtype is not specified"); + final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mParams.mLocale); try { parseKeyboardSet(mResources, R.xml.keyboard_set); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index e5097152b..22ab3e4e5 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -28,6 +28,7 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.DebugSettings; import com.android.inputmethod.latin.InputView; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; @@ -53,6 +54,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, private SubtypeSwitcher mSubtypeSwitcher; private SharedPreferences mPrefs; + private boolean mForceNonDistinctMultitouch; private InputView mCurrentInputView; private LatinKeyboardView mKeyboardView; @@ -92,6 +94,8 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, mState = new KeyboardState(this); setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs)); prefs.registerOnSharedPreferenceChangeListener(this); + mForceNonDistinctMultitouch = prefs.getBoolean( + DebugSettings.FORCE_NON_DISTINCT_MULTITOUCH_KEY, false); } private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) { @@ -117,8 +121,20 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, } public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) { - mKeyboardSet = new KeyboardSet.Builder(mThemeContext, editorInfo, settingsValues) - .build(); + final KeyboardSet.Builder builder = new KeyboardSet.Builder(mThemeContext, editorInfo); + builder.setScreenGeometry(mThemeContext.getResources().getConfiguration().orientation, + mThemeContext.getResources().getDisplayMetrics().widthPixels); + builder.setSubtype( + mSubtypeSwitcher.getInputLocale(), + mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( + LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE), + mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( + LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); + builder.setOptions( + settingsValues.isSettingsKeyEnabled(), + settingsValues.isVoiceKeyEnabled(editorInfo), + settingsValues.isVoiceKeyOnMain()); + mKeyboardSet = builder.build(); final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId(); try { mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols), @@ -132,7 +148,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted // respectively. if (mainKeyboardId.isPhoneKeyboard()) { - mState.onToggleAlphabetAndSymbols(); + mState.setSymbolsKeyboard(); } updateShiftState(); } @@ -209,18 +225,16 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, Keyboard keyboard = getKeyboard(); if (keyboard == null) return; - if (shiftMode == AUTOMATIC_SHIFT) { + switch (shiftMode) { + case AUTOMATIC_SHIFT: keyboard.setAutomaticTemporaryUpperCase(); - } else { - final boolean shifted = (shiftMode == MANUAL_SHIFT); - // On non-distinct multi touch panel device, we should also turn off the shift locked - // state when shift key is pressed to go to normal mode. - // On the other hand, on distinct multi touch panel device, turning off the shift - // locked state with shift key pressing is handled by onReleaseShift(). - if (!hasDistinctMultitouch() && !shifted && mState.isShiftLocked()) { - keyboard.setShiftLocked(false); - } - keyboard.setShifted(shifted); + break; + case MANUAL_SHIFT: + keyboard.setShifted(true); + break; + case UNSHIFT: + keyboard.setShifted(false); + break; } mKeyboardView.invalidateAllKeys(); } @@ -243,51 +257,18 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, } /** - * Toggle keyboard shift state triggered by user touch event. - */ - public void toggleShift() { - mState.onToggleShift(); - } - - /** - * Toggle caps lock state triggered by user touch event. - */ - public void toggleCapsLock() { - mState.onToggleCapsLock(); - } - - /** - * Toggle between alphabet and symbols modes triggered by user touch event. - */ - public void toggleAlphabetAndSymbols() { - mState.onToggleAlphabetAndSymbols(); - } - - /** * Update keyboard shift state triggered by connected EditText status change. */ public void updateShiftState() { mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState()); } - public void onPressShift(boolean withSliding) { - mState.onPressShift(withSliding); - } - - public void onReleaseShift(boolean withSliding) { - mState.onReleaseShift(withSliding); - } - - public void onPressSymbol() { - mState.onPressSymbol(); + public void onPressKey(int code) { + mState.onPressKey(code); } - public void onReleaseSymbol() { - mState.onReleaseSymbol(); - } - - public void onOtherKeyPressed() { - mState.onOtherKeyPressed(); + public void onReleaseKey(int code, boolean withSliding) { + mState.onReleaseKey(code, withSliding); } public void onCancelInput() { @@ -312,6 +293,12 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard()); } + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void requestUpdatingShiftState() { + mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState()); + } + public boolean isInMomentarySwitchState() { return mState.isInMomentarySwitchState(); } @@ -373,6 +360,9 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view); mKeyboardView.setKeyboardActionListener(mInputMethodService); + if (mForceNonDistinctMultitouch) { + mKeyboardView.setDistinctMultitouch(false); + } // This always needs to be set since the accessibility state can // potentially change without the input view being re-created. @@ -418,17 +408,4 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, } } } - - private static String themeName(int themeId) { - // This should be aligned with theme-*.xml resource files' themeId attribute. - switch (themeId) { - case 0: return "Basic"; - case 1: return "BasicHighContrast"; - case 5: return "IceCreamSandwich"; - case 6: return "Stone"; - case 7: return "StoneBold"; - case 8: return "GingerBread"; - default: return null; - } - } } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 3433cd455..aa0f9751d 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -115,7 +115,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke /** Listener for {@link KeyboardActionListener}. */ private KeyboardActionListener mKeyboardActionListener; - private final boolean mHasDistinctMultitouch; + private boolean mHasDistinctMultitouch; private int mOldPointerCount = 1; private Key mOldKey; @@ -371,6 +371,10 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke return mHasDistinctMultitouch; } + public void setDistinctMultitouch(boolean hasDistinctMultitouch) { + mHasDistinctMultitouch = hasDistinctMultitouch; + } + /** * When enabled, calls to {@link KeyboardActionListener#onCodeInput} will include key * codes for adjacent keys. When disabled, only the primary key code will be @@ -413,9 +417,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // the second tap is treated as this double tap event, so that we need not mark tracker // calling setAlreadyProcessed() nor remove the tracker from mPointerQueue. if (ignore) { - mKeyboardActionListener.onCustomRequest(LatinIME.CODE_HAPTIC_AND_AUDIO_FEEDBACK); + invokeCustomRequest(LatinIME.CODE_HAPTIC_AND_AUDIO_FEEDBACK); } else { - mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0); + invokeCodeInput(Keyboard.CODE_CAPSLOCK); } } @@ -475,17 +479,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } private boolean invokeCustomRequest(int code) { - return getKeyboardActionListener().onCustomRequest(code); + return mKeyboardActionListener.onCustomRequest(code); } private void invokeCodeInput(int primaryCode) { - getKeyboardActionListener().onCodeInput(primaryCode, null, + mKeyboardActionListener.onCodeInput(primaryCode, null, KeyboardActionListener.NOT_A_TOUCH_COORDINATE, KeyboardActionListener.NOT_A_TOUCH_COORDINATE); } private void invokeReleaseKey(int primaryCode) { - getKeyboardActionListener().onRelease(primaryCode, false); + mKeyboardActionListener.onReleaseKey(primaryCode, false); } private boolean openMoreKeysPanel(Key parentKey, PointerTracker tracker) { @@ -510,7 +514,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke : parentKey.mX + parentKey.mWidth / 2; final int pointY = parentKey.mY - keyboard.mVerticalGap; moreKeysPanel.showMoreKeysPanel( - this, this, pointX, pointY, mMoreKeysWindow, getKeyboardActionListener()); + this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener); final int translatedX = moreKeysPanel.translateX(tracker.getLastX()); final int translatedY = moreKeysPanel.translateY(tracker.getLastY()); tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel); @@ -806,7 +810,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke return bounds.width(); } - // Layout local language name and left and right arrow on spacebar. + // Layout locale language name on spacebar. private static String layoutSpacebar(Paint paint, Locale locale, int width, float origTextSize) { final Rect bounds = new Rect(); diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java index 8e9929681..1f9ed5e91 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java @@ -61,12 +61,13 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { } @Override - public void onPress(int primaryCode, boolean withSliding) { - mListener.onPress(primaryCode, withSliding); + public void onPressKey(int primaryCode) { + mListener.onPressKey(primaryCode); } + @Override - public void onRelease(int primaryCode, boolean withSliding) { - mListener.onRelease(primaryCode, withSliding); + public void onReleaseKey(int primaryCode, boolean withSliding) { + mListener.onReleaseKey(primaryCode, withSliding); } }; diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 2183e8ed6..274bd0b31 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -237,18 +237,18 @@ public class PointerTracker { } // Returns true if keyboard has been changed by this callback. - private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key, boolean withSliding) { + private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) { final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); if (DEBUG_LISTENER) { Log.d(TAG, "onPress : " + KeyDetector.printableCode(key) - + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + + " ignoreModifier=" + ignoreModifierKey + " enabled=" + key.isEnabled()); } if (ignoreModifierKey) { return false; } if (key.isEnabled()) { - mListener.onPress(key.mCode, withSliding); + mListener.onPressKey(key.mCode); final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged; mKeyboardLayoutHasBeenChanged = false; return keyboardLayoutHasBeenChanged; @@ -296,7 +296,7 @@ public class PointerTracker { return; } if (key.isEnabled()) { - mListener.onRelease(primaryCode, withSliding); + mListener.onReleaseKey(primaryCode, withSliding); } } @@ -495,7 +495,7 @@ public class PointerTracker { // This onPress call may have changed keyboard layout. Those cases are detected at // {@link #setKeyboard}. In those cases, we should update key according to the new // keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(key, false)) { + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { key = onDownKey(x, y, eventTime); } @@ -529,7 +529,7 @@ public class PointerTracker { // This onPress call may have changed keyboard layout. Those cases are detected at // {@link #setKeyboard}. In those cases, we should update key according to the // new keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(key, true)) { + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { key = onMoveKey(x, y); } onMoveToNewKey(key, x, y); @@ -548,7 +548,7 @@ public class PointerTracker { // This onPress call may have changed keyboard layout. Those cases are detected // at {@link #setKeyboard}. In those cases, we should update key according // to the new keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(key, true)) { + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { key = onMoveKey(x, y); } onMoveToNewKey(key, x, y); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index f54bdbb05..c43b9852b 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -21,24 +21,22 @@ import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; -// TODO: Add unit tests /** * Keyboard state machine. * * This class contains all keyboard state transition logic. * * The input events are {@link #onLoadKeyboard(String, boolean)}, {@link #onSaveKeyboardState()}, - * {@link #onPressShift(boolean)}, {@link #onReleaseShift(boolean)}, {@link #onPressSymbol()}, - * {@link #onReleaseSymbol()}, {@link #onOtherKeyPressed()}, + * {@link #onPressKey(int)}, {@link #onReleaseKey(int, boolean)}, * {@link #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)}, - * {@link #onUpdateShiftState(boolean)}, {@link #onToggleShift()}, {@link #onToggleCapsLock()}, - * and {@link #onToggleAlphabetAndSymbols()}. + * {@link #onUpdateShiftState(boolean)}. * * The actions are {@link SwitchActions}'s methods. */ public class KeyboardState { private static final String TAG = KeyboardState.class.getSimpleName(); - private static final boolean DEBUG_STATE = false; + private static final boolean DEBUG_EVENT = false; + private static final boolean DEBUG_ACTION = false; public interface SwitchActions { public void setAlphabetKeyboard(); @@ -53,6 +51,11 @@ public class KeyboardState { public void setSymbolsKeyboard(); public void setSymbolsShiftedKeyboard(); + + /** + * Request to call back {@link KeyboardState#onUpdateShiftState(boolean)}. + */ + public void requestUpdatingShiftState(); } private KeyboardShiftState mKeyboardShiftState = new KeyboardShiftState(); @@ -93,7 +96,7 @@ public class KeyboardState { } public void onLoadKeyboard(String layoutSwitchBackSymbols, boolean hasDistinctMultitouch) { - if (DEBUG_STATE) { + if (DEBUG_EVENT) { Log.d(TAG, "onLoadKeyboard"); } mLayoutSwitchBackSymbols = layoutSwitchBackSymbols; @@ -118,7 +121,7 @@ public class KeyboardState { state.mIsShifted = mIsSymbolShifted; } state.mIsValid = true; - if (DEBUG_STATE) { + if (DEBUG_EVENT) { Log.d(TAG, "onSaveKeyboardState: alphabet=" + state.mIsAlphabetMode + " shiftLocked=" + state.mIsShiftLocked + " shift=" + state.mIsShifted); } @@ -126,7 +129,7 @@ public class KeyboardState { private void onRestoreKeyboardState() { final SavedKeyboardState state = mSavedKeyboardState; - if (DEBUG_STATE) { + if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: valid=" + state.mIsValid + " alphabet=" + state.mIsAlphabetMode + " shiftLocked=" + state.mIsShiftLocked + " shift=" + state.mIsShifted); @@ -158,20 +161,19 @@ public class KeyboardState { } private void setShifted(int shiftMode) { - if (DEBUG_STATE) { + if (DEBUG_ACTION) { Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode)); } if (shiftMode == SwitchActions.AUTOMATIC_SHIFT) { mKeyboardShiftState.setAutomaticTemporaryUpperCase(); } else { - // TODO: Duplicated logic in KeyboardSwitcher#setShifted() final boolean shifted = (shiftMode == SwitchActions.MANUAL_SHIFT); // On non-distinct multi touch panel device, we should also turn off the shift locked // state when shift key is pressed to go to normal mode. // On the other hand, on distinct multi touch panel device, turning off the shift // locked state with shift key pressing is handled by onReleaseShift(). if (!mHasDistinctMultitouch && !shifted && mKeyboardShiftState.isShiftLocked()) { - mKeyboardShiftState.setShiftLocked(false); + mSwitchActions.setShiftLocked(false); } mKeyboardShiftState.setShifted(shifted); } @@ -179,7 +181,7 @@ public class KeyboardState { } private void setShiftLocked(boolean shiftLocked) { - if (DEBUG_STATE) { + if (DEBUG_ACTION) { Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked); } mKeyboardShiftState.setShiftLocked(shiftLocked); @@ -203,7 +205,7 @@ public class KeyboardState { } private void setAlphabetKeyboard() { - if (DEBUG_STATE) { + if (DEBUG_ACTION) { Log.d(TAG, "setAlphabetKeyboard"); } mSwitchActions.setAlphabetKeyboard(); @@ -212,10 +214,12 @@ public class KeyboardState { mSwitchState = SWITCH_STATE_ALPHA; setShiftLocked(mPrevMainKeyboardWasShiftLocked); mPrevMainKeyboardWasShiftLocked = false; + mSwitchActions.requestUpdatingShiftState(); } - private void setSymbolsKeyboard() { - if (DEBUG_STATE) { + // TODO: Make this method private + public void setSymbolsKeyboard() { + if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsKeyboard"); } mPrevMainKeyboardWasShiftLocked = mKeyboardShiftState.isShiftLocked(); @@ -226,7 +230,7 @@ public class KeyboardState { } private void setSymbolsShiftedKeyboard() { - if (DEBUG_STATE) { + if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsShiftedKeyboard"); } mSwitchActions.setSymbolsShiftedKeyboard(); @@ -235,19 +239,40 @@ public class KeyboardState { mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; } - public void onPressSymbol() { - if (DEBUG_STATE) { - Log.d(TAG, "onPressSymbol: " + this); + public void onPressKey(int code) { + if (DEBUG_EVENT) { + Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this); + } + if (code == Keyboard.CODE_SHIFT) { + onPressShift(); + } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + onPressSymbol(); + } else { + mShiftKeyState.onOtherKeyPressed(); + mSymbolKeyState.onOtherKeyPressed(); + } + } + + public void onReleaseKey(int code, boolean withSliding) { + if (DEBUG_EVENT) { + Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + + " sliding=" + withSliding + " " + this); } + if (code == Keyboard.CODE_SHIFT) { + onReleaseShift(withSliding); + } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + // TODO: Make use of withSliding instead of relying on mSwitchState. + onReleaseSymbol(); + } + } + + private void onPressSymbol() { toggleAlphabetAndSymbols(); mSymbolKeyState.onPress(); mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; } - public void onReleaseSymbol() { - if (DEBUG_STATE) { - Log.d(TAG, "onReleaseSymbol: " + this); - } + private void onReleaseSymbol() { // Snap back to the previous keyboard mode if the user chords the mode change key and // another key, then releases the mode change key. if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { @@ -256,16 +281,8 @@ public class KeyboardState { mSymbolKeyState.onRelease(); } - public void onOtherKeyPressed() { - if (DEBUG_STATE) { - Log.d(TAG, "onOtherKeyPressed: " + this); - } - mShiftKeyState.onOtherKeyPressed(); - mSymbolKeyState.onOtherKeyPressed(); - } - public void onUpdateShiftState(boolean autoCaps) { - if (DEBUG_STATE) { + if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } onUpdateShiftStateInternal(autoCaps); @@ -289,10 +306,7 @@ public class KeyboardState { } } - public void onPressShift(boolean withSliding) { - if (DEBUG_STATE) { - Log.d(TAG, "onPressShift: sliding=" + withSliding + " " + this); - } + private void onPressShift() { if (mIsAlphabetMode) { if (mKeyboardShiftState.isShiftLocked()) { // Shift key is pressed while caps lock state, we will treat this state as shifted @@ -321,10 +335,7 @@ public class KeyboardState { } } - public void onReleaseShift(boolean withSliding) { - if (DEBUG_STATE) { - Log.d(TAG, "onReleaseShift: sliding=" + withSliding + " " + this); - } + private void onReleaseShift(boolean withSliding) { if (mIsAlphabetMode) { final boolean isShiftLocked = mKeyboardShiftState.isShiftLocked(); if (mShiftKeyState.isMomentary()) { @@ -358,8 +369,8 @@ public class KeyboardState { } public void onCancelInput(boolean isSinglePointer) { - if (DEBUG_STATE) { - Log.d(TAG, "onCancelInput: isSinglePointer=" + isSinglePointer + " " + this); + if (DEBUG_EVENT) { + Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); } // Snap back to the previous keyboard mode if the user cancels sliding input. if (isSinglePointer) { @@ -387,10 +398,23 @@ public class KeyboardState { } public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) { - if (DEBUG_STATE) { - Log.d(TAG, "onCodeInput: code=" + code + " isSinglePointer=" + isSinglePointer + if (DEBUG_EVENT) { + Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code) + + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } + + if (mIsAlphabetMode && code == Keyboard.CODE_CAPSLOCK) { + if (mKeyboardShiftState.isShiftLocked()) { + setShiftLocked(false); + // Shift key is long pressed or double tapped while caps lock state, we will + // toggle back to normal state. And mark as if shift key is released. + mShiftKeyState.onRelease(); + } else { + setShiftLocked(true); + } + } + switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: // Only distinct multi touch devices can be in this state. @@ -459,41 +483,6 @@ public class KeyboardState { } } - public void onToggleShift() { - if (DEBUG_STATE) { - Log.d(TAG, "onToggleShift: " + this); - } - if (mIsAlphabetMode) { - setShifted(mKeyboardShiftState.isShiftedOrShiftLocked() - ? SwitchActions.UNSHIFT : SwitchActions.MANUAL_SHIFT); - } else { - toggleShiftInSymbols(); - } - } - - public void onToggleCapsLock() { - if (DEBUG_STATE) { - Log.d(TAG, "onToggleCapsLock: " + this); - } - if (mIsAlphabetMode) { - if (mKeyboardShiftState.isShiftLocked()) { - setShiftLocked(false); - // Shift key is long pressed while caps lock state, we will toggle back to normal - // state. And mark as if shift key is released. - mShiftKeyState.onRelease(); - } else { - setShiftLocked(true); - } - } - } - - public void onToggleAlphabetAndSymbols() { - if (DEBUG_STATE) { - Log.d(TAG, "onToggleAlphabetAndSymbols: " + this); - } - toggleAlphabetAndSymbols(); - } - private static String shiftModeToString(int shiftMode) { switch (shiftMode) { case SwitchActions.UNSHIFT: return "UNSHIFT"; diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index 2f1e7c2b8..3805da154 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -30,6 +30,7 @@ public class DebugSettings extends PreferenceActivity private static final String TAG = "DebugSettings"; private static final String DEBUG_MODE_KEY = "debug_mode"; + public static final String FORCE_NON_DISTINCT_MULTITOUCH_KEY = "force_non_distinct_multitouch"; private boolean mServiceNeedsRestart = false; private CheckBoxPreference mDebugMode; @@ -60,6 +61,8 @@ public class DebugSettings extends PreferenceActivity updateDebugMode(); mServiceNeedsRestart = true; } + } else if (key.equals(FORCE_NON_DISTINCT_MULTITOUCH_KEY)) { + mServiceNeedsRestart = true; } } diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index 634dbbdfc..1e8ad1840 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -87,23 +87,6 @@ public class EditingUtils { } /** - * Removes the word surrounding the cursor. Parameters are identical to - * getWordAtCursor. - */ - public static void deleteWordAtCursor(InputConnection connection, String separators) { - // getWordRangeAtCursor returns null if the connection is null - Range range = getWordRangeAtCursor(connection, separators); - if (range == null) return; - - connection.finishComposingText(); - // Move cursor to beginning of word, to avoid crash when cursor is outside - // of valid range after deleting text. - int newCursor = getCursorPosition(connection) - range.mCharsBefore; - connection.setSelection(newCursor, newCursor); - connection.deleteSurroundingText(0, range.mCharsBefore + range.mCharsAfter); - } - - /** * Represents a range of text, relative to the current cursor position. */ public static class Range { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 59de798d8..d11aaeb96 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -104,10 +104,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar */ public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; + // TODO: Remove this private option. /** * The private IME option used to indicate that the given text field needs * ASCII code points input. + * + * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}. */ + @SuppressWarnings("dep-ann") public static final String IME_OPTION_FORCE_ASCII = "forceAscii"; /** @@ -1019,7 +1023,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public boolean onEvaluateFullscreenMode() { - return super.onEvaluateFullscreenMode() && mSettingsValues.mUseFullScreenMode; + // Reread resource value here, because this method is called by framework anytime as needed. + final boolean isFullscreenModeAllowed = + mSettingsValues.isFullscreenModeAllowed(getResources()); + return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; } @Override @@ -1232,7 +1239,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } mLastKeyTime = when; final KeyboardSwitcher switcher = mKeyboardSwitcher; - final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); // The space state depends only on the last character pressed and its own previous // state. Here, we revert the space state to neutral if the key is actually modifying // the input contents (any non-shift key), which is what we should do for @@ -1254,22 +1260,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.logOnDelete(); break; case Keyboard.CODE_SHIFT: - // Shift key is handled in onPress() when device has distinct multi-touch panel. - if (!distinctMultiTouch) { - switcher.toggleShift(); - } - break; case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: - // Symbol key is handled in onPress() when device has distinct multi-touch panel. - if (!distinctMultiTouch) { - switcher.toggleAlphabetAndSymbols(); - } + // Shift and symbol key is handled in onPressKey() and onReleaseKey(). break; case Keyboard.CODE_SETTINGS: onSettingsKeyPressed(); break; case Keyboard.CODE_CAPSLOCK: - switcher.toggleCapsLock(); + // Caps lock code is handled in KeyboardSwitcher.onCodeInput() below. hapticAndAudioFeedback(primaryCode); break; case Keyboard.CODE_SHORTCUT: @@ -1369,6 +1367,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.deleteSurroundingText(1, 0); } } else { + // We should be very careful about auto-correction cancellation and suggestion + // resuming here. The behavior needs to be different according to text field types, + // and it would be much clearer to test for them explicitly here rather than + // relying on implicit values like "whether the suggestion strip is displayed". if (mWordComposer.didAutoCorrectToAnotherWord()) { Utils.Stats.onAutoCorrectionCancellation(); cancelAutoCorrect(ic); @@ -1388,10 +1390,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + // See the comment above: must be careful about resuming auto-suggestion. if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { // Go back to the suggestion mode if the user canceled the // "Touch again to save". - // NOTE: In gerenal, we don't revert the word when backspacing + // NOTE: In general, we don't revert the word when backspacing // from a manual suggestion pick. We deliberately chose a // different behavior only in the case of picking the first // suggestion (typed word). It's intentional to have made this @@ -1402,7 +1405,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (mDeleteCount > DELETE_ACCELERATE_AT) { ic.deleteSurroundingText(1, 0); } - restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); + if (isSuggestionsRequested()) { + restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); + } } } } @@ -1694,6 +1699,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Check if we have a suggestion engine attached. if ((mSuggest == null || !isSuggestionsRequested()) && !mVoiceProxy.isVoiceInputHighlighted()) { + if (mWordComposer.isComposingWord()) { + Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); + mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); + } return; } @@ -2081,10 +2090,23 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return; // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) - // Example: " '|" gets rejected here but "I'|" and "I|" are okay - final CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); + // Example: " -|" gets rejected here but "e-|" and "e|" are okay + CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); + // We don't suggest on leading single quotes, so we have to remove them from the word if + // it starts with single quotes. + while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { + word = word.subSequence(1, word.length()); + } if (TextUtils.isEmpty(word)) return; - if (word.length() == 1 && !Character.isLetter(word.charAt(0))) return; + final char firstChar = word.charAt(0); // we just tested that word is not empty + if (word.length() == 1 && !Character.isLetter(firstChar)) return; + + // We only suggest on words that start with a letter or a symbol that is excluded from + // word separators (see #handleCharacterWhileInBatchEdit). + if (!(isAlphabet(firstChar) + || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) { + return; + } // Okay, we are at the end of a word. Restart suggestions. restartSuggestionsOnWordBeforeCursor(ic, word); @@ -2235,31 +2257,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } @Override - public void onPress(int primaryCode, boolean withSliding) { + public void onPressKey(int primaryCode) { final KeyboardSwitcher switcher = mKeyboardSwitcher; if (switcher.isVibrateAndSoundFeedbackRequired()) { hapticAndAudioFeedback(primaryCode); } - final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { - switcher.onPressShift(withSliding); - } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - switcher.onPressSymbol(); - } else { - switcher.onOtherKeyPressed(); - } + switcher.onPressKey(primaryCode); } @Override - public void onRelease(int primaryCode, boolean withSliding) { - KeyboardSwitcher switcher = mKeyboardSwitcher; - // Reset any drag flags in the keyboard - final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { - switcher.onReleaseShift(withSliding); - } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - switcher.onReleaseSymbol(); - } + public void onReleaseKey(int primaryCode, boolean withSliding) { + mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 83b27f7fe..0ae28d3fc 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -41,7 +41,6 @@ public class SettingsValues { private final String mSymbolsExcludedFromWordSeparators; public final String mWordSeparators; public final CharSequence mHintToSaveText; - public final boolean mUseFullScreenMode; // From preferences, in the same order as xml/prefs.xml: public final boolean mAutoCap; @@ -107,7 +106,6 @@ public class SettingsValues { mWordSeparators = createWordSeparators(mMagicSpaceStrippers, mMagicSpaceSwappers, mSymbolsExcludedFromWordSeparators, res); mHintToSaveText = context.getText(R.string.hint_add_to_dictionary); - mUseFullScreenMode = res.getBoolean(R.bool.config_use_fullscreen_mode); // Get the settings preferences mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); @@ -294,6 +292,10 @@ public class SettingsValues { return mVoiceKeyOnMain; } + public boolean isFullscreenModeAllowed(Resources res) { + return res.getBoolean(R.bool.config_use_fullscreen_mode); + } + // Accessed from the settings interface, hence public public static float getCurrentKeypressSoundVolume(final SharedPreferences sp, final Resources res) { diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 42111822d..f5778167a 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -46,8 +46,8 @@ public class SubtypeSwitcher { private static boolean DBG = LatinImeLogger.sDBG; private static final String TAG = SubtypeSwitcher.class.getSimpleName(); + public static final String KEYBOARD_MODE = "keyboard"; private static final char LOCALE_SEPARATER = '_'; - private static final String KEYBOARD_MODE = "keyboard"; private static final String VOICE_MODE = "voice"; private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index e9ca390d3..8e0d031f4 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -115,7 +115,7 @@ public class Suggest implements Dictionary.WordCallback { /* package for test */ Suggest(final Context context, final File dictionary, final long startOffset, final long length, final Flag[] flagArray, final Locale locale) { - initSynchronously(null, DictionaryFactory.createDictionaryForTest(context, dictionary, + initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary, startOffset, length, flagArray), locale); } diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 38148438b..8e0cfa122 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -154,10 +154,21 @@ public class Utils { } } - return filteredImisCount > 1 - // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled - // input method subtype (The current IME should be LatinIME.) - || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1; + if (filteredImisCount > 1) { + return true; + } + final List<InputMethodSubtypeCompatWrapper> subtypes = + imm.getEnabledInputMethodSubtypeList(null, true); + int keyboardCount = 0; + // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's + // both explicitly and implicitly enabled input method subtype. + // (The current IME should be LatinIME.) + for (InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (SubtypeSwitcher.KEYBOARD_MODE.equals(subtype.getMode())) { + ++keyboardCount; + } + } + return keyboardCount > 1; } public static String getInputMethodId(InputMethodManagerCompatWrapper imm, String packageName) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index b5f67ace0..600f14e04 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -56,13 +56,13 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { private final KeyboardActionListener mSuggestionsPaneListener = new KeyboardActionListener.Adapter() { @Override - public void onPress(int primaryCode, boolean withSliding) { - mListener.onPress(primaryCode, withSliding); + public void onPressKey(int primaryCode) { + mListener.onPressKey(primaryCode); } @Override - public void onRelease(int primaryCode, boolean withSliding) { - mListener.onRelease(primaryCode, withSliding); + public void onReleaseKey(int primaryCode, boolean withSliding) { + mListener.onReleaseKey(primaryCode, withSliding); } @Override |