diff options
Diffstat (limited to 'java/src')
11 files changed, 214 insertions, 265 deletions
diff --git a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java b/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java index 65949357f..2c31c55b0 100644 --- a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java @@ -24,7 +24,7 @@ public abstract class AbstractCompatWrapper { public AbstractCompatWrapper(Object obj) { if (obj == null) { - Log.e(TAG, "Invalid input to AbstructCompatWrapper"); + Log.e(TAG, "Invalid input to AbstractCompatWrapper"); } mObj = obj; } diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java index a6bb83adf..574158825 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java @@ -29,7 +29,7 @@ import java.util.Locale; // TODO: Override this class with the concrete implementation if we need to take care of the // performance. -public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper { +public class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper { private static final boolean DBG = LatinImeLogger.sDBG; private static final String TAG = InputMethodSubtypeCompatWrapper.class.getSimpleName(); private static final String DEFAULT_LOCALE = "en_US"; @@ -65,7 +65,7 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper public InputMethodSubtypeCompatWrapper(Object subtype) { super((CLASS_InputMethodSubtype != null && CLASS_InputMethodSubtype.isInstance(subtype)) - ? subtype : null); + ? subtype : new Object()); mDummyNameResId = 0; mDummyIconResId = 0; mDummyLocale = DEFAULT_LOCALE; @@ -76,7 +76,7 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper // Constructor for creating a dummy subtype. public InputMethodSubtypeCompatWrapper(int nameResId, int iconResId, String locale, String mode, String extraValues) { - super(null); + super(new Object()); if (DBG) { Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper"); } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 320b1bea2..689e322ce 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -388,21 +388,7 @@ public class Keyboard { } } - // TODO: Move this method to KeyboardSwitcher. - 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; - } - } - - /** + /** * Keyboard Building helper. * * This class parses Keyboard XML file and eventually build a Keyboard. diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index efe5aa9cf..599adf21b 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -43,13 +43,26 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions { private static final String TAG = KeyboardSwitcher.class.getSimpleName(); public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916"; - private static final int[] KEYBOARD_THEMES = { - R.style.KeyboardTheme, - R.style.KeyboardTheme_HighContrast, - R.style.KeyboardTheme_Stone, - R.style.KeyboardTheme_Stone_Bold, - R.style.KeyboardTheme_Gingerbread, - R.style.KeyboardTheme_IceCreamSandwich, + + static class KeyboardTheme { + public final String mName; + public final int mThemeId; + public final int mStyleId; + + public KeyboardTheme(String name, int themeId, int styleId) { + mName = name; + mThemeId = themeId; + mStyleId = styleId; + } + } + + private static final KeyboardTheme[] KEYBOARD_THEMES = { + new KeyboardTheme("Basic", 0, R.style.KeyboardTheme), + new KeyboardTheme("HighContrast", 1, R.style.KeyboardTheme_HighContrast), + new KeyboardTheme("Stone", 6, R.style.KeyboardTheme_Stone), + new KeyboardTheme("Stne.Bold", 7, R.style.KeyboardTheme_Stone_Bold), + new KeyboardTheme("GingerBread", 8, R.style.KeyboardTheme_Gingerbread), + new KeyboardTheme("IceCreamSandwich", 5, R.style.KeyboardTheme_IceCreamSandwich), }; private SubtypeSwitcher mSubtypeSwitcher; @@ -69,7 +82,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions { * what user actually typed. */ private boolean mIsAutoCorrectionActive; - private int mThemeIndex = -1; + private KeyboardTheme mKeyboardTheme = KEYBOARD_THEMES[0]; private Context mThemeContext; private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); @@ -92,29 +105,30 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions { mPrefs = prefs; mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mState = new KeyboardState(this); - setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs)); + setContextThemeWrapper(ims, getKeyboardTheme(ims, prefs)); mForceNonDistinctMultitouch = prefs.getBoolean( DebugSettings.FORCE_NON_DISTINCT_MULTITOUCH_KEY, false); } - 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); + private static KeyboardTheme getKeyboardTheme(Context context, SharedPreferences prefs) { + final String defaultIndex = context.getString(R.string.config_default_keyboard_theme_index); + final String themeIndex = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultIndex); try { - final int themeIndex = Integer.valueOf(themeId); - if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length) - return themeIndex; + final int index = Integer.valueOf(themeIndex); + if (index >= 0 && index < KEYBOARD_THEMES.length) { + return KEYBOARD_THEMES[index]; + } } 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; + Log.w(TAG, "Illegal keyboard theme in preference: " + themeIndex + ", default to 0"); + return KEYBOARD_THEMES[0]; } - private void setContextThemeWrapper(Context context, int themeIndex) { - if (mThemeIndex != themeIndex) { - mThemeIndex = themeIndex; - mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]); + private void setContextThemeWrapper(Context context, KeyboardTheme keyboardTheme) { + if (mKeyboardTheme.mThemeId != keyboardTheme.mThemeId) { + mKeyboardTheme = keyboardTheme; + mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId); KeyboardSet.clearKeyboardCache(); } } @@ -347,18 +361,16 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions { boolean tryGC = true; for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { try { - setContextThemeWrapper(mInputMethodService, mThemeIndex); + setContextThemeWrapper(mInputMethodService, mKeyboardTheme); mCurrentInputView = (InputView)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( - Keyboard.toThemeName(mThemeIndex), e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mKeyboardTheme.mName, e); } catch (InflateException e) { Log.w(TAG, "load keyboard failed: " + e); - tryGC = Utils.GCUtils.getInstance().tryGCOrWait( - Keyboard.toThemeName(mThemeIndex), e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mKeyboardTheme.mName, e); } } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index 9970d1d0b..2495b5472 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -136,34 +136,23 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel mController = controller; mListener = listener; final View container = (View)getParent(); - final MoreKeysKeyboard moreKeysKeyboard = (MoreKeysKeyboard)getKeyboard(); - - parentView.getLocationInWindow(mCoordinates); - final int moreKeysKeyboardLeft = pointX - moreKeysKeyboard.getDefaultCoordX() + final MoreKeysKeyboard pane = (MoreKeysKeyboard)getKeyboard(); + final int defaultCoordX = pane.getDefaultCoordX(); + // The coordinates of panel's left-top corner in parentView's coordinate system. + final int x = pointX - defaultCoordX - container.getPaddingLeft() + parentView.getPaddingLeft(); - final int x = wrapUp(Math.max(0, Math.min(moreKeysKeyboardLeft, - parentView.getWidth() - moreKeysKeyboard.mOccupiedWidth)) - - container.getPaddingLeft() + mCoordinates[0], - container.getMeasuredWidth(), 0, parentView.getWidth()); - final int y = pointY - - (container.getMeasuredHeight() - container.getPaddingBottom()) - + parentView.getPaddingTop() + mCoordinates[1]; + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() + + parentView.getPaddingTop(); window.setContentView(container); window.setWidth(container.getMeasuredWidth()); window.setHeight(container.getMeasuredHeight()); - window.showAtLocation(parentView, Gravity.NO_GRAVITY, x, y); - - mOriginX = x + container.getPaddingLeft() - mCoordinates[0]; - mOriginY = y + container.getPaddingTop() - mCoordinates[1]; - } + parentView.getLocationInWindow(mCoordinates); + window.showAtLocation(parentView, Gravity.NO_GRAVITY, + x + mCoordinates[0], y + mCoordinates[1]); - private static int wrapUp(int x, int width, int left, int right) { - if (x < left) - return left; - if (x + width > right) - return right - width; - return x; + mOriginX = x + container.getPaddingLeft(); + mOriginY = y + container.getPaddingTop(); } private boolean mIsDismissing; diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index 582509324..1480bba62 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -44,10 +44,11 @@ public class ProximityInfo { // TODO: Find a proper name for mKeyboardMinWidth private final int mKeyboardMinWidth; private final int mKeyboardHeight; + private final int mMostCommonKeyWidth; private final Key[][] mGridNeighbors; - ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, - int keyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection, + ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int mostCommonKeyWidth, + int mostCommonKeyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection, Map<Integer, List<Integer>> additionalProximityChars) { mGridWidth = gridWidth; mGridHeight = gridHeight; @@ -56,13 +57,15 @@ public class ProximityInfo { mCellHeight = (height + mGridHeight - 1) / mGridHeight; mKeyboardMinWidth = minWidth; mKeyboardHeight = height; - mKeyHeight = keyHeight; + mKeyHeight = mostCommonKeyHeight; + mMostCommonKeyWidth = mostCommonKeyWidth; mGridNeighbors = new Key[mGridSize][]; if (minWidth == 0 || height == 0) { // No proximity required. Keyboard might be more keys keyboard. return; } - computeNearestNeighbors(keyWidth, keys, touchPositionCorrection, additionalProximityChars); + computeNearestNeighbors( + mostCommonKeyWidth, keys, touchPositionCorrection, additionalProximityChars); } public static ProximityInfo createDummyProximityInfo() { @@ -74,8 +77,8 @@ public class ProximityInfo { final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo(); spellCheckerProximityInfo.mNativeProximityInfo = spellCheckerProximityInfo.setProximityInfoNative( - SpellCheckerProximityInfo.ROW_SIZE, 480, 300, 11, 3, proximity, 0, - null, null, null, null, null, null, null, null); + SpellCheckerProximityInfo.ROW_SIZE, 480, 300, 11, 3, (480 / 10), proximity, + 0, null, null, null, null, null, null, null, null); return spellCheckerProximityInfo; } @@ -85,7 +88,8 @@ public class ProximityInfo { } private native long setProximityInfoNative(int maxProximityCharsSize, int displayWidth, - int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray, + int displayHeight, int gridWidth, int gridHeight, + int mostCommonKeyWidth, int[] proximityCharsArray, int keyCount, int[] keyXCoordinates, int[] keyYCoordinates, int[] keyWidths, int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii); @@ -151,7 +155,8 @@ public class ProximityInfo { } mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE, - keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray, + keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth, + proximityCharsArray, keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii); } diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java new file mode 100644 index 000000000..1cbdbd650 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.view.HapticFeedbackConstants; +import android.view.View; + +import com.android.inputmethod.compat.VibratorCompatWrapper; +import com.android.inputmethod.keyboard.Keyboard; + +/** + * This class gathers audio feedback and haptic feedback functions. + * + * It offers a consistent and simple interface that allows LatinIME to forget about the + * complexity of settings and the like. + */ +public class AudioAndHapticFeedbackManager extends BroadcastReceiver { + final private SettingsValues mSettingsValues; + final private AudioManager mAudioManager; + final private VibratorCompatWrapper mVibrator; + private boolean mSoundOn; + + public AudioAndHapticFeedbackManager(final LatinIME latinIme, + final SettingsValues settingsValues) { + mSettingsValues = settingsValues; + mVibrator = VibratorCompatWrapper.getInstance(latinIme); + mAudioManager = (AudioManager) latinIme.getSystemService(Context.AUDIO_SERVICE); + mSoundOn = reevaluateIfSoundIsOn(); + } + + public void hapticAndAudioFeedback(final int primaryCode, + final View viewToPerformHapticFeedbackOn) { + vibrate(viewToPerformHapticFeedbackOn); + playKeyClick(primaryCode); + } + + private boolean reevaluateIfSoundIsOn() { + if (!mSettingsValues.mSoundOn || mAudioManager == null) { + return false; + } else { + return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL; + } + } + + private void playKeyClick(int primaryCode) { + // if mAudioManager is null, we can't play a sound anyway, so return + if (mAudioManager == null) return; + if (mSoundOn) { + final int sound; + switch (primaryCode) { + case Keyboard.CODE_DELETE: + sound = AudioManager.FX_KEYPRESS_DELETE; + break; + case Keyboard.CODE_ENTER: + sound = AudioManager.FX_KEYPRESS_RETURN; + break; + case Keyboard.CODE_SPACE: + sound = AudioManager.FX_KEYPRESS_SPACEBAR; + break; + default: + sound = AudioManager.FX_KEYPRESS_STANDARD; + break; + } + mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume); + } + } + + // TODO: make this private when LatinIME does not call it any more + public void vibrate(final View viewToPerformHapticFeedbackOn) { + if (!mSettingsValues.mVibrateOn) { + return; + } + if (mSettingsValues.mKeypressVibrationDuration < 0) { + // Go ahead with the system default + if (viewToPerformHapticFeedbackOn != null) { + viewToPerformHapticFeedbackOn.performHapticFeedback( + HapticFeedbackConstants.KEYBOARD_TAP, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } + } else if (mVibrator != null) { + mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration); + } + } + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + // The following test is supposedly useless since we only listen for the ringer event. + // Still, it's a good safety measure. + if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { + mSoundOn = reevaluateIfSoundIsOn(); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index bcb78919d..a9489da54 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -25,18 +25,16 @@ import java.util.Map; public class AutoCorrection { private static final boolean DBG = LatinImeLogger.sDBG; private static final String TAG = AutoCorrection.class.getSimpleName(); - private boolean mHasAutoCorrection; private CharSequence mAutoCorrectionWord; private double mNormalizedScore; public void init() { - mHasAutoCorrection = false; mAutoCorrectionWord = null; mNormalizedScore = Integer.MIN_VALUE; } public boolean hasAutoCorrection() { - return mHasAutoCorrection; + return null != mAutoCorrectionWord; } public CharSequence getAutoCorrectionWord() { @@ -47,22 +45,20 @@ public class AutoCorrection { return mNormalizedScore; } - public void updateAutoCorrectionStatus(Map<String, Dictionary> dictionaries, + public CharSequence updateAutoCorrectionStatus(Map<String, Dictionary> dictionaries, WordComposer wordComposer, ArrayList<CharSequence> suggestions, int[] sortedScores, CharSequence typedWord, double autoCorrectionThreshold, int correctionMode, CharSequence whitelistedWord) { if (hasAutoCorrectionForWhitelistedWord(whitelistedWord)) { - mHasAutoCorrection = true; mAutoCorrectionWord = whitelistedWord; } else if (hasAutoCorrectionForTypedWord( dictionaries, wordComposer, suggestions, typedWord, correctionMode)) { - mHasAutoCorrection = true; mAutoCorrectionWord = typedWord; } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions, correctionMode, sortedScores, typedWord, autoCorrectionThreshold)) { - mHasAutoCorrection = true; mAutoCorrectionWord = suggestions.get(0); } + return mAutoCorrectionWord; } public static boolean isValidWord( diff --git a/java/src/com/android/inputmethod/latin/ComposingStateManager.java b/java/src/com/android/inputmethod/latin/ComposingStateManager.java deleted file mode 100644 index 8811f2023..000000000 --- a/java/src/com/android/inputmethod/latin/ComposingStateManager.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.latin; - -import android.util.Log; - -public class ComposingStateManager { - private static final String TAG = ComposingStateManager.class.getSimpleName(); - private static final ComposingStateManager sInstance = new ComposingStateManager(); - private boolean mAutoCorrectionIndicatorOn; - private boolean mIsComposing; - - public static ComposingStateManager getInstance() { - return sInstance; - } - - private ComposingStateManager() { - mAutoCorrectionIndicatorOn = false; - mIsComposing = false; - } - - public synchronized void onStartComposingText() { - if (!mIsComposing) { - if (LatinImeLogger.sDBG) { - Log.i(TAG, "Start composing text."); - } - mAutoCorrectionIndicatorOn = false; - mIsComposing = true; - } - } - - public synchronized void onFinishComposingText() { - if (mIsComposing) { - if (LatinImeLogger.sDBG) { - Log.i(TAG, "Finish composing text."); - } - mAutoCorrectionIndicatorOn = false; - mIsComposing = false; - } - } - - public synchronized boolean isAutoCorrectionIndicatorOn() { - return mAutoCorrectionIndicatorOn; - } - - public synchronized void setAutoCorrectionIndicatorOn(boolean on) { - // Auto-correction indicator should be specified only when the current state is "composing". - if (!mIsComposing) return; - if (LatinImeLogger.sDBG) { - Log.i(TAG, "Set auto correction Indicator: " + on); - } - mAutoCorrectionIndicatorOn = on; - } -} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c16a34fac..273593dfb 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -40,7 +40,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; -import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; @@ -61,7 +60,6 @@ import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.SuggestionSpanUtils; -import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.deprecated.LanguageSwitcherProxy; import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethod.keyboard.Keyboard; @@ -223,10 +221,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private int mDeleteCount; private long mLastKeyTime; - private AudioManager mAudioManager; - private boolean mSilentModeOn; // System-wide current configuration - - private VibratorCompatWrapper mVibrator; + private AudioAndHapticFeedbackManager mFeedbackManager; // Member variables for remembering the current device orientation. private int mDisplayOrientation; @@ -238,8 +233,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Keeps track of most recently inserted text (multi-character key) for reverting private CharSequence mEnteredText; - private final ComposingStateManager mComposingStateManager = - ComposingStateManager.getInstance(); + private boolean mIsAutoCorrectionIndicatorOn; public final UIHandler mHandler = new UIHandler(this); @@ -511,7 +505,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar super.onCreate(); mImm = InputMethodManagerCompatWrapper.getInstance(); - mVibrator = VibratorCompatWrapper.getInstance(this); mHandler.onCreate(); DEBUG = LatinImeLogger.sDBG; @@ -538,11 +531,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Register to receive ringer mode change and network state change. // Also receive installation and removal of a dictionary pack. final IntentFilter filter = new IntentFilter(); - filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(mReceiver, filter); mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); + final IntentFilter ringerModeFilter = new IntentFilter(); + ringerModeFilter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); + registerReceiver(mFeedbackManager, ringerModeFilter); + final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); @@ -559,6 +555,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /* package */ void loadSettings() { if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); + mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); } @@ -647,6 +644,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mSuggest = null; } unregisterReceiver(mReceiver); + unregisterReceiver(mFeedbackManager); unregisterReceiver(mDictionaryPackInstallReceiver); mVoiceProxy.destroy(); LatinImeLogger.commit(); @@ -657,7 +655,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void onConfigurationChanged(Configuration conf) { mSubtypeSwitcher.onConfigurationChanged(conf); - mComposingStateManager.onFinishComposingText(); // If orientation changed while predicting, commit the change if (mDisplayOrientation != conf.orientation) { mDisplayOrientation = conf.orientation; @@ -1148,7 +1145,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // and the composingStateManager about it. private void resetEntireInputState() { resetComposingState(true /* alsoResetLastComposedWord */); - mComposingStateManager.onFinishComposingText(); updateSuggestions(); final InputConnection ic = getCurrentInputConnection(); if (ic != null) { @@ -1340,6 +1336,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // all inputs that do not result in a special state. Each character handling is then // free to override the state as they see fit. final int spaceState = mSpaceState; + if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false; // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. if (primaryCode != Keyboard.CODE_SPACE) { @@ -1589,7 +1586,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // it entirely and resume suggestions on the previous word, we'd like to still // have touch coordinates for it. resetComposingState(false /* alsoResetLastComposedWord */); - mComposingStateManager.onFinishComposingText(); clearSuggestions(); } } @@ -1600,7 +1596,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); - mComposingStateManager.onStartComposingText(); } ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } @@ -1632,7 +1627,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private boolean handleSeparator(final int primaryCode, final int x, final int y, final int spaceState) { mVoiceProxy.handleSeparator(); - mComposingStateManager.onFinishComposingText(); // Should dismiss the "Touch again to save" message when handling separator if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { @@ -1712,7 +1706,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } private CharSequence getTextWithUnderline(final CharSequence text) { - return mComposingStateManager.isAutoCorrectionIndicatorOn() + return mIsAutoCorrectionIndicatorOn ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) : text; } @@ -1788,15 +1782,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Put a blue underline to a word in TextView which will be auto-corrected. final InputConnection ic = getCurrentInputConnection(); if (ic != null) { - final boolean oldAutoCorrectionIndicator = - mComposingStateManager.isAutoCorrectionIndicatorOn(); - if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) { - mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator); - if (DEBUG) { - Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator - + " -> " + newAutoCorrectionIndicator); - } + if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator) { if (mWordComposer.isComposingWord()) { + mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator; final CharSequence textWithUnderline = getTextWithUnderline(mWordComposer.getTypedWord()); ic.setComposingText(textWithUnderline, 1); @@ -1942,7 +1930,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void pickSuggestionManually(final int index, final CharSequence suggestion) { - mComposingStateManager.onFinishComposingText(); final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, mSettingsValues.mWordSeparators); @@ -2145,14 +2132,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public boolean isCursorTouchingWord() { final InputConnection ic = getCurrentInputConnection(); if (ic == null) return false; - CharSequence toLeft = ic.getTextBeforeCursor(1, 0); - CharSequence toRight = ic.getTextAfterCursor(1, 0); - if (!TextUtils.isEmpty(toLeft) - && !mSettingsValues.isWordSeparator(toLeft.charAt(0))) { + CharSequence before = ic.getTextBeforeCursor(1, 0); + CharSequence after = ic.getTextAfterCursor(1, 0); + if (!TextUtils.isEmpty(before) && !mSettingsValues.isWordSeparator(before.charAt(0))) { return true; } - if (!TextUtils.isEmpty(toRight) - && !mSettingsValues.isWordSeparator(toRight.charAt(0))) { + if (!TextUtils.isEmpty(after) && !mSettingsValues.isWordSeparator(after.charAt(0))) { return true; } return false; @@ -2213,7 +2198,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, final CharSequence word) { mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); - mComposingStateManager.onStartComposingText(); ic.deleteSurroundingText(word.length(), 0); ic.setComposingText(word, 1); mHandler.postUpdateSuggestions(); @@ -2245,7 +2229,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // This is the case when we cancel a manual pick. // We should restart suggestion on the word right away. mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); - mComposingStateManager.onStartComposingText(); ic.setComposingText(originallyTypedWord, 1); } else { ic.commitText(originallyTypedWord, 1); @@ -2336,9 +2319,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } - public void hapticAndAudioFeedback(int primaryCode) { - vibrate(); - playKeyClick(primaryCode); + public void hapticAndAudioFeedback(final int primaryCode) { + mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView()); } @Override @@ -2368,76 +2350,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); - if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { - updateRingerMode(); - } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { mSubtypeSwitcher.onNetworkStateChanged(intent); } } }; - // update flags for silent mode - private void updateRingerMode() { - if (mAudioManager == null) { - mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - if (mAudioManager == null) return; - } - mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); - } - - private void playKeyClick(int primaryCode) { - // if mAudioManager is null, we don't have the ringer state yet - // mAudioManager will be set by updateRingerMode - if (mAudioManager == null) { - if (mKeyboardSwitcher.getKeyboardView() != null) { - updateRingerMode(); - } - } - if (isSoundOn()) { - final int sound; - switch (primaryCode) { - case Keyboard.CODE_DELETE: - sound = AudioManager.FX_KEYPRESS_DELETE; - break; - case Keyboard.CODE_ENTER: - sound = AudioManager.FX_KEYPRESS_RETURN; - break; - case Keyboard.CODE_SPACE: - sound = AudioManager.FX_KEYPRESS_SPACEBAR; - break; - default: - sound = AudioManager.FX_KEYPRESS_STANDARD; - break; - } - mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume); - } - } - + // TODO: remove this method when VoiceProxy has been removed public void vibrate() { - if (!mSettingsValues.mVibrateOn) { - return; - } - if (mSettingsValues.mKeypressVibrationDuration < 0) { - // Go ahead with the system default - LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); - if (inputView != null) { - inputView.performHapticFeedback( - HapticFeedbackConstants.KEYBOARD_TAP, - HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } - } else if (mVibrator != null) { - mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration); - } + mFeedbackManager.vibrate(mKeyboardSwitcher.getKeyboardView()); } public boolean isAutoCapitalized() { return mWordComposer.isAutoCapitalized(); } - boolean isSoundOn() { - return mSettingsValues.mSoundOn && !mSilentModeOn; - } - private void updateCorrectionMode() { // TODO: cleanup messy flags final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 1f7214777..f11b1a4c1 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -147,32 +147,22 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { mListener = listener; final View container = (View)getParent(); final MoreSuggestions pane = (MoreSuggestions)getKeyboard(); - - parentView.getLocationInWindow(mCoordinates); - final int paneLeft = pointX - (pane.mOccupiedWidth / 2) + parentView.getPaddingLeft(); - final int x = wrapUp(Math.max(0, Math.min(paneLeft, - parentView.getWidth() - pane.mOccupiedWidth)) - - container.getPaddingLeft() + mCoordinates[0], - container.getMeasuredWidth(), 0, parentView.getWidth()); - final int y = pointY - - (container.getMeasuredHeight() - container.getPaddingBottom()) - + parentView.getPaddingTop() + mCoordinates[1]; + final int defaultCoordX = pane.mOccupiedWidth / 2; + // The coordinates of panel's left-top corner in parentView's coordinate system. + final int x = pointX - defaultCoordX - container.getPaddingLeft() + + parentView.getPaddingLeft(); + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() + + parentView.getPaddingTop(); window.setContentView(container); window.setWidth(container.getMeasuredWidth()); window.setHeight(container.getMeasuredHeight()); - window.showAtLocation(parentView, Gravity.NO_GRAVITY, x, y); - - mOriginX = x + container.getPaddingLeft() - mCoordinates[0]; - mOriginY = y + container.getPaddingTop() - mCoordinates[1]; - } + parentView.getLocationInWindow(mCoordinates); + window.showAtLocation(parentView, Gravity.NO_GRAVITY, + x + mCoordinates[0], y + mCoordinates[1]); - private static int wrapUp(int x, int width, int left, int right) { - if (x < left) - return left; - if (x + width > right) - return right - width; - return x; + mOriginX = x + container.getPaddingLeft(); + mOriginY = y + container.getPaddingTop(); } private boolean mIsDismissing; |