diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
5 files changed, 340 insertions, 36 deletions
diff --git a/java/src/com/android/inputmethod/latin/ClipTouchEventWindowCallback.java b/java/src/com/android/inputmethod/latin/ClipTouchEventWindowCallback.java new file mode 100644 index 000000000..d12c70075 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ClipTouchEventWindowCallback.java @@ -0,0 +1,75 @@ +/* + * 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.view.MotionEvent; +import android.view.View; +import android.view.Window; + +public class ClipTouchEventWindowCallback extends WindowCallbackAdapter { + private final View mDecorView; + private final int mKeyboardBottomRowVerticalCorrection; + + public ClipTouchEventWindowCallback(Window window, int keyboardBottomRowVerticalCorrection) { + super(window.getCallback()); + mDecorView = window.getDecorView(); + mKeyboardBottomRowVerticalCorrection = keyboardBottomRowVerticalCorrection; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent me) { + final int height = mDecorView.getHeight(); + final MotionEvent event = clipMotionEvent(me, height, + height + mKeyboardBottomRowVerticalCorrection); + return super.dispatchTouchEvent(event); + } + + private static MotionEvent clipMotionEvent(MotionEvent me, int minHeight, int maxHeight) { + final int pointerCount = me.getPointerCount(); + boolean shouldClip = false; + for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) { + final float y = me.getY(pointerIndex); + if (y >= minHeight && y < maxHeight) { + shouldClip = true; + break; + } + } + if (!shouldClip) + return me; + + if (pointerCount == 1) { + me.setLocation(me.getX(), minHeight - 1); + return me; + } + + final int[] pointerIds = new int[pointerCount]; + final MotionEvent.PointerCoords[] pointerCoords = + new MotionEvent.PointerCoords[pointerCount]; + for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) { + pointerIds[pointerIndex] = me.getPointerId(pointerIndex); + final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords(); + me.getPointerCoords(pointerIndex, coords); + pointerCoords[pointerIndex] = coords; + if (coords.y >= minHeight && coords.y < maxHeight) + coords.y = minHeight - 1; + } + return MotionEvent.obtain( + me.getDownTime(), me.getEventTime(), me.getAction(), pointerCount, pointerIds, + pointerCoords, me.getMetaState(), me.getXPrecision(), me.getYPrecision(), + me.getDeviceId(), me.getEdgeFlags(), me.getSource(), me.getFlags()); + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 847038fee..84415ecee 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -84,8 +84,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "LatinIME"; private static final boolean PERF_DEBUG = false; - private static final boolean DEBUG = LatinImeLogger.sDBG; private static final boolean TRACE = false; + private static boolean DEBUG = LatinImeLogger.sDBG; private static final int DELAY_UPDATE_SUGGESTIONS = 180; private static final int DELAY_UPDATE_OLD_SUGGESTIONS = 300; @@ -97,10 +97,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Key events coming any faster than this are long-presses. private static final int QUICK_PRESS = 200; - // Contextual menu positions - private static final int POS_METHOD = 0; - private static final int POS_SETTINGS = 1; - private int mSuggestionVisibility; private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE = R.string.prefs_suggestion_visibility_show_value; @@ -161,6 +157,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private int mConfigDelayBeforeFadeoutLanguageOnSpacebar; private int mConfigDurationOfFadeoutLanguageOnSpacebar; private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar; + // For example, to deal with status bar on tablet. + private int mKeyboardBottomRowVerticalCorrection; private int mCorrectionMode; private int mCommittedLength; @@ -377,6 +375,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen R.integer.config_duration_of_fadeout_language_on_spacebar); mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; + mKeyboardBottomRowVerticalCorrection = (int)res.getDimension( + R.dimen.keyboard_bottom_row_vertical_correction); Utils.GCUtils.getInstance().reset(); boolean tryGC = true; @@ -514,6 +514,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final KeyboardSwitcher switcher = mKeyboardSwitcher; LatinKeyboardView inputView = switcher.getInputView(); + if(DEBUG) { + Log.d(TAG, "onStartInputView: " + inputView); + } // In landscape mode, this method gets called without the input view being created. if (inputView == null) { return; @@ -566,6 +569,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mVoiceConnector.onStartInputView(inputView.getWindowToken()); + if (mKeyboardBottomRowVerticalCorrection > 0) { + final Window window = getWindow().getWindow(); + if (!(window.getCallback() instanceof ClipTouchEventWindowCallback)) { + window.setCallback(new ClipTouchEventWindowCallback( + window, mKeyboardBottomRowVerticalCorrection)); + } + } + if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } @@ -880,15 +891,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mCandidateViewContainer != null) { ViewParent candidateParent = mCandidateViewContainer.getParent(); if (candidateParent instanceof FrameLayout) { - FrameLayout fl = (FrameLayout) candidateParent; - if (fl != null) { - // Check frame layout's visibility - if (fl.getVisibility() == View.INVISIBLE) { - y = fl.getHeight(); - height += y; - } else if (fl.getVisibility() == View.VISIBLE) { - height += fl.getHeight(); - } + final FrameLayout fl = (FrameLayout) candidateParent; + // Check frame layout's visibility + if (fl.getVisibility() == View.INVISIBLE) { + y = fl.getHeight(); + height += y; + } else if (fl.getVisibility() == View.VISIBLE) { + height += fl.getHeight(); } } } @@ -2213,15 +2222,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void showSubtypeSelectorAndSettings() { - showOptionsMenuInternal(new DialogInterface.OnClickListener() { + final CharSequence title = getString(R.string.english_ime_input_options); + final CharSequence[] items = new CharSequence[] { + // TODO: Should use new string "Select active input modes". + getString(R.string.language_selection_title), + getString(R.string.english_ime_settings), + }; + final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface di, int position) { di.dismiss(); switch (position) { - case POS_SETTINGS: + case 0: launchSettings(); break; - case POS_METHOD: + case 1: Intent intent = new Intent( android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK @@ -2233,36 +2248,41 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; } } - }); + }; + showOptionsMenuInternal(title, items, listener); } private void showOptionsMenu() { - showOptionsMenuInternal(new DialogInterface.OnClickListener() { + final CharSequence title = getString(R.string.english_ime_input_options); + final CharSequence[] items = new CharSequence[] { + getString(R.string.selectInputMethod), + getString(R.string.english_ime_settings), + }; + final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface di, int position) { di.dismiss(); switch (position) { - case POS_SETTINGS: + case 0: launchSettings(); break; - case POS_METHOD: + case 1: mImm.showInputMethodPicker(); break; } } - }); + }; + showOptionsMenuInternal(title, items, listener); } - private void showOptionsMenuInternal(DialogInterface.OnClickListener listener) { + private void showOptionsMenuInternal(CharSequence title, CharSequence[] items, + DialogInterface.OnClickListener listener) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setCancelable(true); builder.setIcon(R.drawable.ic_dialog_keyboard); builder.setNegativeButton(android.R.string.cancel, null); - CharSequence itemSettings = getString(R.string.english_ime_settings); - CharSequence itemInputMethod = getString(R.string.selectInputMethod); - builder.setItems(new CharSequence[] { - itemInputMethod, itemSettings}, listener); - builder.setTitle(mResources.getString(R.string.english_ime_input_options)); + builder.setItems(items, listener); + builder.setTitle(title); mOptionsDialog = builder.create(); mOptionsDialog.setCanceledOnTouchOutside(true); Window window = mOptionsDialog.getWindow(); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 653dbeaba..12338ce61 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -75,6 +75,7 @@ public class Settings extends PreferenceActivity private CheckBoxPreference mQuickFixes; private ListPreference mVoicePreference; private ListPreference mSettingsKeyPreference; + private ListPreference mShowCorrectionSuggestionsPreference; private ListPreference mAutoCorrectionThreshold; private CheckBoxPreference mBigramSuggestion; private boolean mVoiceOn; @@ -102,6 +103,8 @@ public class Settings extends PreferenceActivity mQuickFixes = (CheckBoxPreference) findPreference(PREF_QUICK_FIXES); mVoicePreference = (ListPreference) findPreference(PREF_VOICE_SETTINGS_KEY); mSettingsKeyPreference = (ListPreference) findPreference(PREF_SETTINGS_KEY); + mShowCorrectionSuggestionsPreference = + (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING); SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); @@ -188,6 +191,7 @@ public class Settings extends PreferenceActivity updateVoiceModeSummary(); } updateSettingsKeySummary(); + updateShowCorrectionSuggestionsSummary(); } @Override @@ -212,6 +216,7 @@ public class Settings extends PreferenceActivity .equals(mVoiceModeOff)); updateVoiceModeSummary(); updateSettingsKeySummary(); + updateShowCorrectionSuggestionsSummary(); } @Override @@ -230,6 +235,13 @@ public class Settings extends PreferenceActivity return false; } + private void updateShowCorrectionSuggestionsSummary() { + mShowCorrectionSuggestionsPreference.setSummary( + getResources().getStringArray(R.array.prefs_suggestion_visibilities) + [mShowCorrectionSuggestionsPreference.findIndexOfValue( + mShowCorrectionSuggestionsPreference.getValue())]); + } + private void updateSettingsKeySummary() { mSettingsKeyPreference.setSummary( getResources().getStringArray(R.array.settings_key_modes) diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index da46d26bf..c1e14ad18 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -41,7 +41,7 @@ import java.util.Locale; import java.util.Map; public class SubtypeSwitcher { - private static final boolean DBG = LatinImeLogger.sDBG; + private static boolean DBG = LatinImeLogger.sDBG; private static final String TAG = "SubtypeSwitcher"; private static final char LOCALE_SEPARATER = '_'; @@ -163,6 +163,12 @@ public class SubtypeSwitcher { } private void updateShortcutIME() { + if (DBG) { + Log.d(TAG, "Update shortcut IME from : " + + (mShortcutInfo == null ? "<null>" : mShortcutInfo.getId()) + ", " + + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale() + + ", " + mShortcutSubtype.getMode()))); + } // TODO: Update an icon for shortcut IME Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts = mImm.getShortcutInputMethodsAndSubtypes(); @@ -176,6 +182,12 @@ public class SubtypeSwitcher { mShortcutSubtype = subtypes.size() > 0 ? subtypes.get(0) : null; break; } + if (DBG) { + Log.d(TAG, "Update shortcut IME to : " + + (mShortcutInfo == null ? "<null>" : mShortcutInfo.getId()) + ", " + + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale() + + ", " + mShortcutSubtype.getMode()))); + } } // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. @@ -211,6 +223,9 @@ public class SubtypeSwitcher { } mMode = newMode; } + + // If the old mode is voice input, we need to reset or cancel its status. + // We cancel its status when we change mode, while we reset otherwise. if (isKeyboardMode()) { if (modeChanged) { if (VOICE_MODE.equals(oldMode) && mVoiceInput != null) { @@ -218,19 +233,26 @@ public class SubtypeSwitcher { } } if (modeChanged || languageChanged) { + updateShortcutIME(); mService.onRefreshKeyboard(); } - } else if (isVoiceMode()) { + } else if (isVoiceMode() && mVoiceInput != null) { + if (VOICE_MODE.equals(oldMode)) { + mVoiceInput.reset(); + } // If needsToShowWarningDialog is true, voice input need to show warning before // show recognition view. if (languageChanged || modeChanged || VoiceIMEConnector.getInstance().needsToShowWarningDialog()) { - if (mVoiceInput != null) { - triggerVoiceIME(); - } + triggerVoiceIME(); } } else { Log.w(TAG, "Unknown subtype mode: " + mMode); + if (VOICE_MODE.equals(oldMode) && mVoiceInput != null) { + // We need to reset the voice input to release the resources and to reset its status + // as it is not the current input mode. + mVoiceInput.reset(); + } } } @@ -266,11 +288,18 @@ public class SubtypeSwitcher { //////////////////////////// public void switchToShortcutIME() { - IBinder token = mService.getWindow().getWindow().getAttributes().token; + final IBinder token = mService.getWindow().getWindow().getAttributes().token; if (token == null || mShortcutInfo == null) { return; } - mImm.setInputMethodAndSubtype(token, mShortcutInfo.getId(), mShortcutSubtype); + final String imiId = mShortcutInfo.getId(); + final InputMethodSubtype subtype = mShortcutSubtype; + new Thread("SwitchToShortcutIME") { + @Override + public void run() { + mImm.setInputMethodAndSubtype(token, imiId, subtype); + } + }.start(); } public Drawable getShortcutIcon() { @@ -423,7 +452,7 @@ public class SubtypeSwitcher { mVoiceInput = vi; if (isVoiceMode()) { if (DBG) { - Log.d(TAG, "Set and call voice input."); + Log.d(TAG, "Set and call voice input.: " + getInputLocaleStr()); } triggerVoiceIME(); return true; diff --git a/java/src/com/android/inputmethod/latin/WindowCallbackAdapter.java b/java/src/com/android/inputmethod/latin/WindowCallbackAdapter.java new file mode 100644 index 000000000..be9bb2bd8 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/WindowCallbackAdapter.java @@ -0,0 +1,168 @@ +/* + * 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.view.ActionMode; +import android.view.ActionMode.Callback; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager.LayoutParams; +import android.view.accessibility.AccessibilityEvent; + +public class WindowCallbackAdapter implements Window.Callback { + private final Window.Callback mPreviousCallback; + + public WindowCallbackAdapter(Window.Callback previousCallback) { + mPreviousCallback = previousCallback; + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (mPreviousCallback != null) + return mPreviousCallback.dispatchKeyEvent(event); + return false; + } + + @Override + public boolean dispatchKeyShortcutEvent(KeyEvent event) { + if (mPreviousCallback != null) + return mPreviousCallback.dispatchKeyShortcutEvent(event); + return false; + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + if (mPreviousCallback != null) + return mPreviousCallback.dispatchPopulateAccessibilityEvent(event); + return false; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (mPreviousCallback != null) + return mPreviousCallback.dispatchTouchEvent(event); + return false; + } + + @Override + public boolean dispatchTrackballEvent(MotionEvent event) { + if (mPreviousCallback != null) + return mPreviousCallback.dispatchTrackballEvent(event); + return false; + } + + @Override + public void onActionModeFinished(ActionMode mode) { + if (mPreviousCallback != null) + mPreviousCallback.onActionModeFinished(mode); + } + + @Override + public void onActionModeStarted(ActionMode mode) { + if (mPreviousCallback != null) + mPreviousCallback.onActionModeStarted(mode); + } + + @Override + public void onAttachedToWindow() { + if (mPreviousCallback != null) + mPreviousCallback.onAttachedToWindow(); + } + + @Override + public void onContentChanged() { + if (mPreviousCallback != null) + mPreviousCallback.onContentChanged(); + } + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (mPreviousCallback != null) + return mPreviousCallback.onCreatePanelMenu(featureId, menu); + return false; + } + + @Override + public View onCreatePanelView(int featureId) { + if (mPreviousCallback != null) + return mPreviousCallback.onCreatePanelView(featureId); + return null; + } + + @Override + public void onDetachedFromWindow() { + if (mPreviousCallback != null) + mPreviousCallback.onDetachedFromWindow(); + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (mPreviousCallback != null) + return mPreviousCallback.onMenuItemSelected(featureId, item); + return false; + } + + @Override + public boolean onMenuOpened(int featureId, Menu menu) { + if (mPreviousCallback != null) + return mPreviousCallback.onMenuOpened(featureId, menu); + return false; + } + + @Override + public void onPanelClosed(int featureId, Menu menu) { + if (mPreviousCallback != null) + mPreviousCallback.onPanelClosed(featureId, menu); + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (mPreviousCallback != null) + return mPreviousCallback.onPreparePanel(featureId, view, menu); + return false; + } + + @Override + public boolean onSearchRequested() { + if (mPreviousCallback != null) + return mPreviousCallback.onSearchRequested(); + return false; + } + + @Override + public void onWindowAttributesChanged(LayoutParams attrs) { + if (mPreviousCallback != null) + mPreviousCallback.onWindowAttributesChanged(attrs); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + if (mPreviousCallback != null) + mPreviousCallback.onWindowFocusChanged(hasFocus); + } + + @Override + public ActionMode onWindowStartingActionMode(Callback callback) { + if (mPreviousCallback != null) + return mPreviousCallback.onWindowStartingActionMode(callback); + return null; + } +} |